initializePerformanceData.ts 5.6 KB

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