initializePerformanceData.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {ProjectFixture} from 'sentry-fixture/project';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import type {RawSpanType} from 'sentry/components/events/interfaces/spans/types';
  5. import type {EventTransaction} from 'sentry/types/event';
  6. import {EntryType} from 'sentry/types/event';
  7. import type {Project} from 'sentry/types/project';
  8. import {defined} from 'sentry/utils';
  9. import EventView from 'sentry/utils/discover/eventView';
  10. import type {
  11. ExampleSpan,
  12. ExampleTransaction,
  13. SuspectSpan,
  14. } from 'sentry/utils/performance/suspectSpans/types';
  15. export interface InitializeDataSettings {
  16. features?: string[];
  17. project?: any; // TODO(k-fish): Fix this project type.
  18. projects?: Project[];
  19. query?: {};
  20. selectedProject?: any;
  21. }
  22. export function initializeData(settings?: InitializeDataSettings) {
  23. const _defaultProject = ProjectFixture();
  24. const _settings = {
  25. query: {},
  26. features: [],
  27. projects: [_defaultProject],
  28. project: _defaultProject,
  29. ...settings,
  30. };
  31. const {query, features, projects, selectedProject: project} = _settings;
  32. const organization = OrganizationFixture({
  33. features,
  34. projects,
  35. });
  36. const routerLocation: {query: {project?: string}} = {
  37. query: {
  38. ...query,
  39. },
  40. };
  41. if (settings?.selectedProject || settings?.project) {
  42. routerLocation.query.project = (project || settings?.project) as any;
  43. }
  44. const router = {
  45. location: routerLocation,
  46. };
  47. const initialData = initializeOrg({organization, projects, project, router});
  48. const location = initialData.router.location;
  49. const eventView = EventView.fromLocation(location);
  50. return {...initialData, location, eventView};
  51. }
  52. export const SAMPLE_SPANS = [
  53. {
  54. op: 'op1',
  55. group: 'aaaaaaaaaaaaaaaa',
  56. description: 'span-1',
  57. examples: [
  58. {
  59. id: 'abababababababab',
  60. description: 'span-1',
  61. spans: [{id: 'ababab11'}, {id: 'ababab22'}],
  62. },
  63. {
  64. id: 'acacacacacacacac',
  65. description: 'span-2',
  66. spans: [{id: 'acacac11'}, {id: 'acacac22'}],
  67. },
  68. {
  69. id: 'adadadadadadadad',
  70. description: 'span-3',
  71. spans: [{id: 'adadad11'}, {id: 'adadad22'}],
  72. },
  73. ],
  74. },
  75. {
  76. op: 'op2',
  77. group: 'bbbbbbbbbbbbbbbb',
  78. description: 'span-4',
  79. examples: [
  80. {
  81. id: 'bcbcbcbcbcbcbcbc',
  82. description: 'span-4',
  83. spans: [{id: 'bcbcbc11'}, {id: 'bcbcbc11'}],
  84. },
  85. {
  86. id: 'bdbdbdbdbdbdbdbd',
  87. description: 'span-5',
  88. spans: [{id: 'bdbdbd11'}, {id: 'bdbdbd22'}],
  89. },
  90. {
  91. id: 'bebebebebebebebe',
  92. description: 'span-6',
  93. spans: [{id: 'bebebe11'}, {id: 'bebebe22'}],
  94. },
  95. ],
  96. },
  97. ];
  98. type SpanOpt = {
  99. id: string;
  100. };
  101. type ExampleOpt = {
  102. description: string;
  103. id: string;
  104. spans: SpanOpt[];
  105. };
  106. type SuspectOpt = {
  107. description: string;
  108. examples: ExampleOpt[];
  109. group: string;
  110. op: string;
  111. };
  112. function makeSpan(opt: SpanOpt): ExampleSpan {
  113. const {id} = opt;
  114. return {
  115. id,
  116. trace: 'trace',
  117. startTimestamp: 10100,
  118. finishTimestamp: 10200,
  119. exclusiveTime: 100,
  120. };
  121. }
  122. function makeExample(opt: ExampleOpt): ExampleTransaction {
  123. const {id, description, spans} = opt;
  124. return {
  125. id,
  126. description,
  127. startTimestamp: 10000,
  128. finishTimestamp: 12000,
  129. nonOverlappingExclusiveTime: 2000,
  130. spans: spans.map(makeSpan),
  131. };
  132. }
  133. export function makeSuspectSpan(opt: SuspectOpt): SuspectSpan {
  134. const {op, group, description, examples} = opt;
  135. return {
  136. op,
  137. group,
  138. description,
  139. frequency: 1,
  140. count: 1,
  141. avgOccurrences: 1,
  142. sumExclusiveTime: 5,
  143. p50ExclusiveTime: 1,
  144. p75ExclusiveTime: 2,
  145. p95ExclusiveTime: 3,
  146. p99ExclusiveTime: 4,
  147. examples: examples.map(makeExample),
  148. };
  149. }
  150. export function generateSuspectSpansResponse(opts?: {
  151. examples?: number;
  152. examplesOnly?: boolean;
  153. }) {
  154. const {examples, examplesOnly} = opts ?? {};
  155. return SAMPLE_SPANS.map(sampleSpan => {
  156. const span = {...sampleSpan};
  157. if (defined(examples)) {
  158. span.examples = span.examples.slice(0, examples);
  159. }
  160. const suspectSpans = makeSuspectSpan(span);
  161. if (examplesOnly) {
  162. return {
  163. op: suspectSpans.op,
  164. group: suspectSpans.group,
  165. examples: suspectSpans.examples,
  166. };
  167. }
  168. return suspectSpans;
  169. });
  170. }
  171. export function generateSampleEvent(): EventTransaction {
  172. const event = {
  173. id: '2b658a829a21496b87fd1f14a61abf65',
  174. eventID: '2b658a829a21496b87fd1f14a61abf65',
  175. title: '/organizations/:orgId/discover/results/',
  176. type: 'transaction',
  177. startTimestamp: 1622079935.86141,
  178. endTimestamp: 1622079940.032905,
  179. contexts: {
  180. trace: {
  181. trace_id: '8cbbc19c0f54447ab702f00263262726',
  182. span_id: 'a000000000000000',
  183. op: 'pageload',
  184. status: 'unknown',
  185. type: 'trace',
  186. },
  187. },
  188. entries: [
  189. {
  190. data: [],
  191. type: EntryType.SPANS,
  192. },
  193. ],
  194. } as unknown as EventTransaction;
  195. return event;
  196. }
  197. export function generateSampleSpan(
  198. description: string | undefined,
  199. op: string | undefined,
  200. span_id: string,
  201. parent_span_id: string,
  202. event: EventTransaction
  203. ) {
  204. const span: RawSpanType = {
  205. start_timestamp: 1000,
  206. timestamp: 2000,
  207. description,
  208. op,
  209. span_id,
  210. parent_span_id,
  211. trace_id: '8cbbc19c0f54447ab702f00263262726',
  212. status: 'ok',
  213. tags: {
  214. 'http.status_code': '200',
  215. },
  216. data: {},
  217. };
  218. if (!Array.isArray(event.entries[0].data)) {
  219. throw new Error('Event entries data is not an array');
  220. }
  221. const data = event.entries[0].data as RawSpanType[];
  222. data.push(span);
  223. return span;
  224. }