fieldRenderers.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import {Fragment} from 'react';
  2. import {DateTime} from 'sentry/components/dateTime';
  3. import {Tooltip} from 'sentry/components/tooltip';
  4. import {t} from 'sentry/locale';
  5. import {
  6. ColoredLogCircle,
  7. ColoredLogText,
  8. type getLogColors,
  9. LogDate,
  10. LogsHighlight,
  11. WrappingText,
  12. } from 'sentry/views/explore/logs/styles';
  13. import {
  14. type OurLogFieldKey,
  15. OurLogKnownFieldKey,
  16. type OurLogsResponseItem,
  17. } from 'sentry/views/explore/logs/types';
  18. import {
  19. getLogSeverityLevel,
  20. SeverityLevel,
  21. severityLevelToText,
  22. } from 'sentry/views/explore/logs/utils';
  23. interface FieldRendererProps {
  24. attribute_value: string | number | null;
  25. extra: RendererExtra;
  26. tableResultLogRow?: OurLogsResponseItem;
  27. }
  28. export interface RendererExtra {
  29. highlightTerms: string[];
  30. logColors: ReturnType<typeof getLogColors>;
  31. renderSeverityCircle?: boolean;
  32. useFullSeverityText?: boolean;
  33. wrapBody?: boolean;
  34. }
  35. function SeverityCircle(props: {
  36. level: SeverityLevel;
  37. levelLabel: string;
  38. logColors: ReturnType<typeof getLogColors>;
  39. severityText: string;
  40. }) {
  41. return (
  42. <Tooltip
  43. skipWrapper
  44. disabled={props.level === SeverityLevel.UNKNOWN}
  45. title={props.levelLabel}
  46. >
  47. <ColoredLogCircle logColors={props.logColors}>
  48. {props.severityText}
  49. </ColoredLogCircle>
  50. </Tooltip>
  51. );
  52. }
  53. export function severityTextRenderer(props: FieldRendererProps) {
  54. const attribute_value = props.attribute_value as string;
  55. const _severityNumber = props.tableResultLogRow?.[OurLogKnownFieldKey.SEVERITY_NUMBER];
  56. const severityNumber = _severityNumber ? Number(_severityNumber) : null;
  57. const useFullSeverityText = props.extra.useFullSeverityText ?? false;
  58. const level = getLogSeverityLevel(severityNumber, attribute_value);
  59. const levelLabel = useFullSeverityText ? attribute_value : severityLevelToText(level);
  60. const renderSeverityCircle = props.extra.renderSeverityCircle ?? false;
  61. return (
  62. <Fragment>
  63. {renderSeverityCircle && (
  64. <SeverityCircle
  65. level={level}
  66. levelLabel={levelLabel}
  67. severityText={attribute_value}
  68. logColors={props.extra.logColors}
  69. />
  70. )}
  71. <ColoredLogText logColors={props.extra.logColors}>[{levelLabel}]</ColoredLogText>
  72. </Fragment>
  73. );
  74. }
  75. export function TimestampRenderer(props: FieldRendererProps) {
  76. return (
  77. <LogDate>
  78. <DateTime seconds date={props.attribute_value} />
  79. </LogDate>
  80. );
  81. }
  82. export function bodyRenderer(props: FieldRendererProps) {
  83. const attribute_value = props.attribute_value as string;
  84. const highlightTerm = props.extra.highlightTerms[0] ?? '';
  85. // TODO: Allow more than one highlight term to be highlighted at once.
  86. return (
  87. <WrappingText wrap={props.extra.wrapBody}>
  88. <LogsHighlight text={highlightTerm}>{attribute_value}</LogsHighlight>
  89. </WrappingText>
  90. );
  91. }
  92. function wrappedSeverityTextRenderer(props: {
  93. attribute_value: string | number | null;
  94. extra?: RendererExtra;
  95. }) {
  96. const extra = props.extra || {
  97. highlightTerms: [],
  98. logColors: {} as ReturnType<typeof getLogColors>,
  99. };
  100. return severityTextRenderer({...props, extra});
  101. }
  102. export const LogAttributesRendererMap: Record<
  103. OurLogFieldKey,
  104. (props: {
  105. attribute_value: string | number | null;
  106. extra?: RendererExtra;
  107. }) => React.ReactNode
  108. > = {
  109. [OurLogKnownFieldKey.TIMESTAMP]: props => {
  110. // Ensure extra is defined for the wrapped function
  111. const extra = props.extra || {
  112. highlightTerms: [],
  113. logColors: {} as ReturnType<typeof getLogColors>,
  114. };
  115. return TimestampRenderer({...props, extra});
  116. },
  117. [OurLogKnownFieldKey.SEVERITY_TEXT]: wrappedSeverityTextRenderer,
  118. [OurLogKnownFieldKey.SENTRY_SEVERITY_TEXT]: wrappedSeverityTextRenderer,
  119. };
  120. export const LogAttributesHumanLabel: Record<OurLogFieldKey, string> = {
  121. [OurLogKnownFieldKey.TIMESTAMP]: t('Timestamp'),
  122. [OurLogKnownFieldKey.SEVERITY_TEXT]: t('Severity'),
  123. };
  124. export const HiddenLogAttributes: OurLogFieldKey[] = [
  125. OurLogKnownFieldKey.SEVERITY_NUMBER,
  126. OurLogKnownFieldKey.ID,
  127. OurLogKnownFieldKey.BODY,
  128. OurLogKnownFieldKey.PROJECT_ID,
  129. OurLogKnownFieldKey.SENTRY_ORGANIZATION_ID,
  130. OurLogKnownFieldKey.SENTRY_PROJECT_ID,
  131. OurLogKnownFieldKey.SENTRY_ITEM_TYPE,
  132. ];