mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
242 lines
5.5 KiB
TypeScript
242 lines
5.5 KiB
TypeScript
import {OrganizationFixture} from 'sentry-fixture/organization';
|
|
import {ProjectFixture} from 'sentry-fixture/project';
|
|
|
|
import {initializeOrg} from 'sentry-test/initializeOrg';
|
|
|
|
import type {RawSpanType} from 'sentry/components/events/interfaces/spans/types';
|
|
import type {EventTransaction, Project} from 'sentry/types';
|
|
import {EntryType} from 'sentry/types';
|
|
import {defined} from 'sentry/utils';
|
|
import EventView from 'sentry/utils/discover/eventView';
|
|
import type {
|
|
ExampleSpan,
|
|
ExampleTransaction,
|
|
SuspectSpan,
|
|
} from 'sentry/utils/performance/suspectSpans/types';
|
|
|
|
export interface InitializeDataSettings {
|
|
features?: string[];
|
|
project?: any; // TODO(k-fish): Fix this project type.
|
|
projects?: Project[];
|
|
query?: {};
|
|
selectedProject?: any;
|
|
}
|
|
|
|
export function initializeData(settings?: InitializeDataSettings) {
|
|
const _defaultProject = ProjectFixture();
|
|
const _settings = {
|
|
query: {},
|
|
features: [],
|
|
projects: [_defaultProject],
|
|
project: _defaultProject,
|
|
...settings,
|
|
};
|
|
const {query, features, projects, selectedProject: project} = _settings;
|
|
|
|
const organization = OrganizationFixture({
|
|
features,
|
|
projects,
|
|
});
|
|
const routerLocation: {query: {project?: string}} = {
|
|
query: {
|
|
...query,
|
|
},
|
|
};
|
|
if (settings?.selectedProject || settings?.project) {
|
|
routerLocation.query.project = (project || settings?.project) as any;
|
|
}
|
|
const router = {
|
|
location: routerLocation,
|
|
};
|
|
const initialData = initializeOrg({organization, projects, project, router});
|
|
const location = initialData.router.location;
|
|
const eventView = EventView.fromLocation(location);
|
|
|
|
return {...initialData, location, eventView};
|
|
}
|
|
|
|
export const SAMPLE_SPANS = [
|
|
{
|
|
op: 'op1',
|
|
group: 'aaaaaaaaaaaaaaaa',
|
|
description: 'span-1',
|
|
examples: [
|
|
{
|
|
id: 'abababababababab',
|
|
description: 'span-1',
|
|
spans: [{id: 'ababab11'}, {id: 'ababab22'}],
|
|
},
|
|
{
|
|
id: 'acacacacacacacac',
|
|
description: 'span-2',
|
|
spans: [{id: 'acacac11'}, {id: 'acacac22'}],
|
|
},
|
|
{
|
|
id: 'adadadadadadadad',
|
|
description: 'span-3',
|
|
spans: [{id: 'adadad11'}, {id: 'adadad22'}],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
op: 'op2',
|
|
group: 'bbbbbbbbbbbbbbbb',
|
|
description: 'span-4',
|
|
examples: [
|
|
{
|
|
id: 'bcbcbcbcbcbcbcbc',
|
|
description: 'span-4',
|
|
spans: [{id: 'bcbcbc11'}, {id: 'bcbcbc11'}],
|
|
},
|
|
{
|
|
id: 'bdbdbdbdbdbdbdbd',
|
|
description: 'span-5',
|
|
spans: [{id: 'bdbdbd11'}, {id: 'bdbdbd22'}],
|
|
},
|
|
{
|
|
id: 'bebebebebebebebe',
|
|
description: 'span-6',
|
|
spans: [{id: 'bebebe11'}, {id: 'bebebe22'}],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
type SpanOpt = {
|
|
id: string;
|
|
};
|
|
|
|
type ExampleOpt = {
|
|
description: string;
|
|
id: string;
|
|
spans: SpanOpt[];
|
|
};
|
|
|
|
type SuspectOpt = {
|
|
description: string;
|
|
examples: ExampleOpt[];
|
|
group: string;
|
|
op: string;
|
|
};
|
|
|
|
function makeSpan(opt: SpanOpt): ExampleSpan {
|
|
const {id} = opt;
|
|
return {
|
|
id,
|
|
startTimestamp: 10100,
|
|
finishTimestamp: 10200,
|
|
exclusiveTime: 100,
|
|
};
|
|
}
|
|
|
|
function makeExample(opt: ExampleOpt): ExampleTransaction {
|
|
const {id, description, spans} = opt;
|
|
return {
|
|
id,
|
|
description,
|
|
startTimestamp: 10000,
|
|
finishTimestamp: 12000,
|
|
nonOverlappingExclusiveTime: 2000,
|
|
spans: spans.map(makeSpan),
|
|
};
|
|
}
|
|
|
|
export function makeSuspectSpan(opt: SuspectOpt): SuspectSpan {
|
|
const {op, group, description, examples} = opt;
|
|
return {
|
|
op,
|
|
group,
|
|
description,
|
|
frequency: 1,
|
|
count: 1,
|
|
avgOccurrences: 1,
|
|
sumExclusiveTime: 5,
|
|
p50ExclusiveTime: 1,
|
|
p75ExclusiveTime: 2,
|
|
p95ExclusiveTime: 3,
|
|
p99ExclusiveTime: 4,
|
|
examples: examples.map(makeExample),
|
|
};
|
|
}
|
|
|
|
export function generateSuspectSpansResponse(opts?: {
|
|
examples?: number;
|
|
examplesOnly?: boolean;
|
|
}) {
|
|
const {examples, examplesOnly} = opts ?? {};
|
|
return SAMPLE_SPANS.map(sampleSpan => {
|
|
const span = {...sampleSpan};
|
|
if (defined(examples)) {
|
|
span.examples = span.examples.slice(0, examples);
|
|
}
|
|
const suspectSpans = makeSuspectSpan(span);
|
|
if (examplesOnly) {
|
|
return {
|
|
op: suspectSpans.op,
|
|
group: suspectSpans.group,
|
|
examples: suspectSpans.examples,
|
|
};
|
|
}
|
|
return suspectSpans;
|
|
});
|
|
}
|
|
|
|
export function generateSampleEvent(): EventTransaction {
|
|
const event = {
|
|
id: '2b658a829a21496b87fd1f14a61abf65',
|
|
eventID: '2b658a829a21496b87fd1f14a61abf65',
|
|
title: '/organizations/:orgId/discover/results/',
|
|
type: 'transaction',
|
|
startTimestamp: 1622079935.86141,
|
|
endTimestamp: 1622079940.032905,
|
|
contexts: {
|
|
trace: {
|
|
trace_id: '8cbbc19c0f54447ab702f00263262726',
|
|
span_id: 'a000000000000000',
|
|
op: 'pageload',
|
|
status: 'unknown',
|
|
type: 'trace',
|
|
},
|
|
},
|
|
entries: [
|
|
{
|
|
data: [],
|
|
type: EntryType.SPANS,
|
|
},
|
|
],
|
|
} as unknown as EventTransaction;
|
|
|
|
return event;
|
|
}
|
|
|
|
export function generateSampleSpan(
|
|
description: string | undefined,
|
|
op: string | undefined,
|
|
span_id: string,
|
|
parent_span_id: string,
|
|
event: EventTransaction
|
|
) {
|
|
const span: RawSpanType = {
|
|
start_timestamp: 1000,
|
|
timestamp: 2000,
|
|
description,
|
|
op,
|
|
span_id,
|
|
parent_span_id,
|
|
trace_id: '8cbbc19c0f54447ab702f00263262726',
|
|
status: 'ok',
|
|
tags: {
|
|
'http.status_code': '200',
|
|
},
|
|
data: {},
|
|
};
|
|
|
|
if (!Array.isArray(event.entries[0].data)) {
|
|
throw new Error('Event entries data is not an array');
|
|
}
|
|
|
|
const data = event.entries[0].data as RawSpanType[];
|
|
data.push(span);
|
|
return span;
|
|
}
|