aggregateFlamegraphPanel.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import styled from '@emotion/styled';
  2. import EmptyStateWarning from 'sentry/components/emptyStateWarning';
  3. import LoadingIndicator from 'sentry/components/loadingIndicator';
  4. import Panel from 'sentry/components/panels/panel';
  5. import {DeprecatedAggregateFlamegraph} from 'sentry/components/profiling/flamegraph/deprecatedAggregateFlamegraph';
  6. import {Flex} from 'sentry/components/profiling/flex';
  7. import QuestionTooltip from 'sentry/components/questionTooltip';
  8. import {t} from 'sentry/locale';
  9. import {space} from 'sentry/styles/space';
  10. import {FlamegraphStateProvider} from 'sentry/utils/profiling/flamegraph/flamegraphStateProvider/flamegraphContextProvider';
  11. import {FlamegraphThemeProvider} from 'sentry/utils/profiling/flamegraph/flamegraphThemeProvider';
  12. import {Frame} from 'sentry/utils/profiling/frame';
  13. import {useAggregateFlamegraphQuery} from 'sentry/utils/profiling/hooks/useAggregateFlamegraphQuery';
  14. import {useLocalStorageState} from 'sentry/utils/useLocalStorageState';
  15. import {ProfileGroupProvider} from 'sentry/views/profiling/profileGroupProvider';
  16. export function AggregateFlamegraphPanel({transaction}: {transaction: string}) {
  17. const [hideSystemFrames, setHideSystemFrames] = useLocalStorageState(
  18. 'profiling-flamegraph-collapsed-frames',
  19. true
  20. );
  21. const {data, isLoading} = useAggregateFlamegraphQuery({transaction});
  22. const isEmpty = data?.shared.frames.length === 0;
  23. return (
  24. <Flex column gap={space(1)}>
  25. <Flex align="center" gap={space(0.5)}>
  26. <HeaderTitle>{t('Aggregate Flamegraph')}</HeaderTitle>
  27. <QuestionTooltip
  28. size="sm"
  29. position="right"
  30. isHoverable
  31. title={
  32. <TooltipContent>
  33. <p>{t('An aggregate of profiles for this transaction.')}</p>
  34. <p>
  35. {t(
  36. 'Navigate the aggregate flamegraph by scrolling and by double clicking a frame to zoom.'
  37. )}
  38. </p>
  39. </TooltipContent>
  40. }
  41. />
  42. </Flex>
  43. <ProfileGroupProvider
  44. type="flamegraph"
  45. input={data ?? null}
  46. traceID=""
  47. frameFilter={hideSystemFrames ? applicationFrameOnly : undefined}
  48. >
  49. <FlamegraphStateProvider
  50. initialState={{
  51. preferences: {
  52. sorting: 'alphabetical',
  53. view: 'bottom up',
  54. },
  55. }}
  56. >
  57. <FlamegraphThemeProvider>
  58. <Panel>
  59. <Flex h={400} column justify="center">
  60. {isLoading ? (
  61. <LoadingIndicator>{t('Loading Aggregate Flamegraph')}</LoadingIndicator>
  62. ) : isEmpty ? (
  63. <EmptyStateWarning>
  64. <p>{t(`Aggregate flamegraph isn't available for your query`)}</p>
  65. </EmptyStateWarning>
  66. ) : (
  67. <DeprecatedAggregateFlamegraph
  68. hideSystemFrames={hideSystemFrames}
  69. setHideSystemFrames={setHideSystemFrames}
  70. />
  71. )}
  72. </Flex>
  73. </Panel>
  74. </FlamegraphThemeProvider>
  75. </FlamegraphStateProvider>
  76. </ProfileGroupProvider>
  77. </Flex>
  78. );
  79. }
  80. function applicationFrameOnly(frame: Frame): boolean {
  81. return frame.is_application;
  82. }
  83. export const HeaderTitle = styled('span')`
  84. ${p => p.theme.text.cardTitle};
  85. color: ${p => p.theme.headingColor};
  86. font-size: ${p => p.theme.fontSizeMedium};
  87. `;
  88. export const TooltipContent = styled('div')`
  89. & p {
  90. text-align: left;
  91. }
  92. & p:last-child {
  93. margin-bottom: 0;
  94. }
  95. `;