traceIcons.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import {Fragment, useMemo} from 'react';
  2. import clamp from 'lodash/clamp';
  3. import {PlatformIcon} from 'platformicons';
  4. import {useHasTraceNewUi} from 'sentry/views/performance/newTraceDetails/useHasTraceNewUi';
  5. import {TraceIcons} from '../traceIcons';
  6. import type {TraceTree} from '../traceModels/traceTree';
  7. import type {TraceTreeNode} from '../traceModels/traceTreeNode';
  8. import type {VirtualizedViewManager} from '../traceRenderers/virtualizedViewManager';
  9. interface ErrorIconsProps {
  10. errors: TraceTreeNode<TraceTree.Transaction>['errors'];
  11. manager: VirtualizedViewManager;
  12. node_space: [number, number] | null;
  13. }
  14. export function TraceErrorIcons(props: ErrorIconsProps) {
  15. const errors = useMemo(() => {
  16. return [...props.errors];
  17. }, [props.errors]);
  18. if (!props.errors.size) {
  19. return null;
  20. }
  21. return (
  22. <Fragment>
  23. {errors.map((error, i) => {
  24. const timestamp = error.timestamp ? error.timestamp * 1e3 : props.node_space![0];
  25. // Clamp the error timestamp to the span's timestamp
  26. const left = props.manager.computeRelativeLeftPositionFromOrigin(
  27. clamp(
  28. timestamp,
  29. props.node_space![0],
  30. props.node_space![0] + props.node_space![1]
  31. ),
  32. props.node_space!
  33. );
  34. return (
  35. <div
  36. key={i}
  37. className={`TraceIcon ${error.level}`}
  38. style={{left: left * 100 + '%'}}
  39. >
  40. <TraceIcons.Icon event={error} />
  41. </div>
  42. );
  43. })}
  44. </Fragment>
  45. );
  46. }
  47. interface TracePerformanceIssueIconsProps {
  48. manager: VirtualizedViewManager;
  49. node_space: [number, number] | null;
  50. performance_issues: TraceTreeNode<TraceTree.Transaction>['performance_issues'];
  51. }
  52. export function TracePerformanceIssueIcons(props: TracePerformanceIssueIconsProps) {
  53. const performance_issues = useMemo(() => {
  54. return [...props.performance_issues];
  55. }, [props.performance_issues]);
  56. if (!props.performance_issues.size) {
  57. return null;
  58. }
  59. return (
  60. <Fragment>
  61. {performance_issues.map((issue, i) => {
  62. const timestamp = issue.timestamp
  63. ? issue.timestamp * 1e3
  64. : issue.start
  65. ? issue.start * 1e3
  66. : props.node_space![0];
  67. // Clamp the issue timestamp to the span's timestamp
  68. const left = props.manager.computeRelativeLeftPositionFromOrigin(
  69. clamp(
  70. timestamp,
  71. props.node_space![0],
  72. props.node_space![0] + props.node_space![1]
  73. ),
  74. props.node_space!
  75. );
  76. return (
  77. <div
  78. key={i}
  79. className={`TraceIcon performance_issue`}
  80. style={{left: left * 100 + '%'}}
  81. >
  82. <TraceIcons.Icon event={issue} />
  83. </div>
  84. );
  85. })}
  86. </Fragment>
  87. );
  88. }
  89. export function SpanProjectIcon({platform}: {platform: string}) {
  90. const hasTraceNewUi = useHasTraceNewUi();
  91. if (!hasTraceNewUi) {
  92. return null;
  93. }
  94. return <PlatformIcon platform={platform} />;
  95. }