spanDescriptionCell.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import {Fragment, useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Hovercard} from 'sentry/components/hovercard';
  4. import {t} from 'sentry/locale';
  5. import {space} from 'sentry/styles/space';
  6. import {SQLishFormatter} from 'sentry/utils/sqlish/SQLishFormatter';
  7. import {FullSpanDescription} from 'sentry/views/insights/common/components/fullSpanDescription';
  8. import {SpanGroupDetailsLink} from 'sentry/views/insights/common/components/spanGroupDetailsLink';
  9. import {SupportedDatabaseSystem} from 'sentry/views/insights/database/utils/constants';
  10. import {formatMongoDBQuery} from 'sentry/views/insights/database/utils/formatMongoDBQuery';
  11. import {ModuleName, SpanMetricsField} from 'sentry/views/insights/types';
  12. const formatter = new SQLishFormatter();
  13. const {SPAN_OP} = SpanMetricsField;
  14. interface Props {
  15. description: string;
  16. moduleName: ModuleName.DB | ModuleName.RESOURCE;
  17. projectId: number;
  18. extraLinkQueryParams?: Record<string, string>;
  19. group?: string;
  20. spanAction?: string;
  21. spanOp?: string;
  22. system?: string;
  23. }
  24. export function SpanDescriptionCell({
  25. description: rawDescription,
  26. group,
  27. moduleName,
  28. spanOp,
  29. projectId,
  30. system,
  31. spanAction,
  32. extraLinkQueryParams,
  33. }: Props) {
  34. const formatterDescription = useMemo(() => {
  35. if (moduleName !== ModuleName.DB) {
  36. return rawDescription;
  37. }
  38. if (system === SupportedDatabaseSystem.MONGODB) {
  39. return spanAction ? formatMongoDBQuery(rawDescription, spanAction) : rawDescription;
  40. }
  41. return formatter.toSimpleMarkup(rawDescription);
  42. }, [moduleName, rawDescription, spanAction, system]);
  43. if (!rawDescription) {
  44. return NULL_DESCRIPTION;
  45. }
  46. const descriptionLink = (
  47. <SpanGroupDetailsLink
  48. moduleName={moduleName}
  49. group={group}
  50. projectId={projectId}
  51. spanOp={spanOp}
  52. description={formatterDescription}
  53. extraLinkQueryParams={extraLinkQueryParams}
  54. />
  55. );
  56. if (moduleName === ModuleName.DB) {
  57. return (
  58. <WiderHovercard
  59. position="right"
  60. body={
  61. <FullSpanDescription
  62. group={group}
  63. shortDescription={rawDescription}
  64. moduleName={moduleName}
  65. />
  66. }
  67. >
  68. {descriptionLink}
  69. </WiderHovercard>
  70. );
  71. }
  72. if (moduleName === ModuleName.RESOURCE) {
  73. return (
  74. <WiderHovercard
  75. position="right"
  76. body={
  77. <Fragment>
  78. <TitleWrapper>{t('Example')}</TitleWrapper>
  79. <FullSpanDescription
  80. group={group}
  81. shortDescription={rawDescription}
  82. moduleName={moduleName}
  83. filters={spanOp ? {[SPAN_OP]: spanOp} : undefined}
  84. />
  85. </Fragment>
  86. }
  87. >
  88. {descriptionLink}
  89. </WiderHovercard>
  90. );
  91. }
  92. return descriptionLink;
  93. }
  94. const NULL_DESCRIPTION = <span>&lt;null&gt;</span>;
  95. export const WiderHovercard = styled(
  96. ({children, className, ...props}: React.ComponentProps<typeof Hovercard>) => (
  97. <Hovercard
  98. className={(className ?? '') + ' wider'}
  99. containerDisplayMode="inline-flex"
  100. {...props}
  101. >
  102. {children}
  103. </Hovercard>
  104. )
  105. )`
  106. &.wider {
  107. width: auto;
  108. max-width: 550px;
  109. }
  110. `;
  111. const TitleWrapper = styled('div')`
  112. margin-bottom: ${space(1)};
  113. `;