utils.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import {LocationDescriptorObject, Query} from 'history';
  2. import {PAGE_URL_PARAM} from 'sentry/constants/pageFilters';
  3. import {Organization, OrganizationSummary} from 'sentry/types';
  4. import {
  5. EventLite,
  6. TraceError,
  7. TraceFull,
  8. TraceFullDetailed,
  9. TraceSplitResults,
  10. } from 'sentry/utils/performance/quickTrace/types';
  11. import {isTraceSplitResult, reduceTrace} from 'sentry/utils/performance/quickTrace/utils';
  12. import {DEFAULT_TRACE_ROWS_LIMIT} from './limitExceededMessage';
  13. import {TraceInfo} from './types';
  14. export function getTraceDetailsUrl(
  15. organization: OrganizationSummary,
  16. traceSlug: string,
  17. dateSelection,
  18. query: Query
  19. ): LocationDescriptorObject {
  20. const {start, end, statsPeriod} = dateSelection;
  21. const queryParams = {
  22. ...query,
  23. statsPeriod,
  24. [PAGE_URL_PARAM.PAGE_START]: start,
  25. [PAGE_URL_PARAM.PAGE_END]: end,
  26. };
  27. if (organization.features.includes('trace-view-load-more')) {
  28. queryParams.limit = DEFAULT_TRACE_ROWS_LIMIT;
  29. }
  30. return {
  31. pathname: `/organizations/${organization.slug}/performance/trace/${traceSlug}/`,
  32. query: queryParams,
  33. };
  34. }
  35. function transactionVisitor() {
  36. return (accumulator: TraceInfo, event: TraceFullDetailed) => {
  37. for (const error of event.errors ?? []) {
  38. accumulator.errors.add(error.event_id);
  39. }
  40. for (const performanceIssue of event.performance_issues ?? []) {
  41. accumulator.performanceIssues.add(performanceIssue.event_id);
  42. }
  43. accumulator.transactions.add(event.event_id);
  44. accumulator.projects.add(event.project_slug);
  45. accumulator.startTimestamp = Math.min(
  46. accumulator.startTimestamp,
  47. event.start_timestamp
  48. );
  49. accumulator.endTimestamp = Math.max(accumulator.endTimestamp, event.timestamp);
  50. accumulator.maxGeneration = Math.max(accumulator.maxGeneration, event.generation);
  51. return accumulator;
  52. };
  53. }
  54. export function hasTraceData(
  55. traces: TraceFullDetailed[] | null | undefined,
  56. orphanErrors: TraceError[] | undefined
  57. ): boolean {
  58. return Boolean(
  59. (traces && traces.length > 0) || (orphanErrors && orphanErrors.length > 0)
  60. );
  61. }
  62. export function getTraceSplitResults<U extends TraceFullDetailed | TraceFull | EventLite>(
  63. trace: TraceSplitResults<U> | U[],
  64. organization: Organization
  65. ) {
  66. let transactions: U[] | undefined;
  67. let orphanErrors: TraceError[] | undefined;
  68. if (
  69. trace &&
  70. organization.features.includes('performance-tracing-without-performance') &&
  71. isTraceSplitResult<TraceSplitResults<U>, U[]>(trace)
  72. ) {
  73. orphanErrors = trace.orphan_errors;
  74. transactions = trace.transactions;
  75. }
  76. return {transactions, orphanErrors};
  77. }
  78. export function getTraceInfo(
  79. traces: TraceFullDetailed[] = [],
  80. orphanErrors: TraceError[] = []
  81. ) {
  82. const initial = {
  83. projects: new Set<string>(),
  84. errors: new Set<string>(),
  85. performanceIssues: new Set<string>(),
  86. transactions: new Set<string>(),
  87. startTimestamp: Number.MAX_SAFE_INTEGER,
  88. endTimestamp: 0,
  89. maxGeneration: 0,
  90. trailingOrphansCount: 0,
  91. };
  92. const transactionsInfo = traces.reduce(
  93. (info: TraceInfo, trace: TraceFullDetailed) =>
  94. reduceTrace<TraceInfo>(trace, transactionVisitor(), info),
  95. initial
  96. );
  97. // Accumulate orphan error information.
  98. return orphanErrors.reduce((accumulator: TraceInfo, event: TraceError) => {
  99. accumulator.errors.add(event.event_id);
  100. accumulator.trailingOrphansCount++;
  101. if (event.timestamp) {
  102. accumulator.startTimestamp = Math.min(accumulator.startTimestamp, event.timestamp);
  103. accumulator.endTimestamp = Math.max(accumulator.endTimestamp, event.timestamp);
  104. }
  105. return accumulator;
  106. }, transactionsInfo);
  107. }
  108. export function shortenErrorTitle(title: string): string {
  109. return title.split(':')[0];
  110. }
  111. export function isRootTransaction(trace: TraceFullDetailed): boolean {
  112. // Root transactions has no parent_span_id
  113. return trace.parent_span_id === null;
  114. }