timeSpentCell.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import clamp from 'lodash/clamp';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import {Tooltip} from 'sentry/components/tooltip';
  4. import {t, tct} from 'sentry/locale';
  5. import {defined} from 'sentry/utils';
  6. import {NumberContainer} from 'sentry/utils/discover/styles';
  7. import {formatPercentage, getDuration} from 'sentry/utils/formatters';
  8. interface Props {
  9. containerProps?: React.DetailedHTMLProps<
  10. React.HTMLAttributes<HTMLDivElement>,
  11. HTMLDivElement
  12. >;
  13. op?: string;
  14. percentage?: number;
  15. total?: number;
  16. }
  17. export function TimeSpentCell({percentage, total, op, containerProps}: Props) {
  18. const formattedPercentage = formatPercentage(clamp(percentage ?? 0, 0, 1));
  19. const formattedTotal = getDuration((total ?? 0) / 1000, 2, true);
  20. const tooltip = tct(
  21. 'The application spent [percentage] of its total time on this [span]. Read more about Time Spent in our [documentation:documentation].',
  22. {
  23. percentage: formattedPercentage,
  24. span: getSpanOperationDescription(op),
  25. documentation: (
  26. <ExternalLink href="https://docs.sentry.io/product/performance/queries/#what-is-time-spent" />
  27. ),
  28. }
  29. );
  30. return (
  31. <NumberContainer {...containerProps}>
  32. <Tooltip isHoverable title={tooltip} showUnderline>
  33. {defined(total) ? formattedTotal : '--'}
  34. </Tooltip>
  35. </NumberContainer>
  36. );
  37. }
  38. // TODO: This should use `getSpanOperationDescription` but it uppercases the
  39. // names. We should update `getSpanOperationDescription` to not uppercase the
  40. // descriptions needlessly, and use it here. Also, the names here are a little
  41. // shorter, which is friendlier
  42. function getSpanOperationDescription(spanOp?: string) {
  43. if (spanOp?.startsWith('http')) {
  44. return t('request');
  45. }
  46. if (spanOp?.startsWith('db')) {
  47. return t('query');
  48. }
  49. if (spanOp?.startsWith('task')) {
  50. return t('task');
  51. }
  52. if (spanOp?.startsWith('serialize')) {
  53. return t('serializer');
  54. }
  55. if (spanOp?.startsWith('middleware')) {
  56. return t('middleware');
  57. }
  58. return t('span');
  59. }