LogsMetaRow.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import React from 'react';
  2. import { LogsDedupStrategy, LogsMetaItem, LogsMetaKind, LogRowModel } from '@grafana/data';
  3. import { Button, Tooltip, Icon, LogLabels } from '@grafana/ui';
  4. import { MAX_CHARACTERS } from '@grafana/ui/src/components/Logs/LogRowMessage';
  5. import { MetaInfoText, MetaItemProps } from './MetaInfoText';
  6. export type Props = {
  7. meta: LogsMetaItem[];
  8. dedupStrategy: LogsDedupStrategy;
  9. dedupCount: number;
  10. showDetectedFields: string[];
  11. hasUnescapedContent: boolean;
  12. forceEscape: boolean;
  13. logRows: LogRowModel[];
  14. onEscapeNewlines: () => void;
  15. clearDetectedFields: () => void;
  16. };
  17. export const LogsMetaRow: React.FC<Props> = React.memo(
  18. ({
  19. meta,
  20. dedupStrategy,
  21. dedupCount,
  22. showDetectedFields,
  23. clearDetectedFields,
  24. hasUnescapedContent,
  25. forceEscape,
  26. onEscapeNewlines,
  27. logRows,
  28. }) => {
  29. const logsMetaItem: Array<LogsMetaItem | MetaItemProps> = [...meta];
  30. // Add deduplication info
  31. if (dedupStrategy !== LogsDedupStrategy.none) {
  32. logsMetaItem.push({
  33. label: 'Dedup count',
  34. value: dedupCount,
  35. kind: LogsMetaKind.Number,
  36. });
  37. }
  38. // Add info about limit for highlighting
  39. if (logRows.some((r) => r.entry.length > MAX_CHARACTERS)) {
  40. logsMetaItem.push({
  41. label: 'Info',
  42. value: 'Logs with more than 100,000 characters could not be parsed and highlighted',
  43. kind: LogsMetaKind.String,
  44. });
  45. }
  46. // Add detected fields info
  47. if (showDetectedFields?.length > 0) {
  48. logsMetaItem.push(
  49. {
  50. label: 'Showing only detected fields',
  51. value: renderMetaItem(showDetectedFields, LogsMetaKind.LabelsMap),
  52. },
  53. {
  54. label: '',
  55. value: (
  56. <Button variant="secondary" size="sm" onClick={clearDetectedFields}>
  57. Show original line
  58. </Button>
  59. ),
  60. }
  61. );
  62. }
  63. // Add unescaped content info
  64. if (hasUnescapedContent) {
  65. logsMetaItem.push({
  66. label: 'Your logs might have incorrectly escaped content',
  67. value: (
  68. <Tooltip
  69. content="Fix incorrectly escaped newline and tab sequences in log lines. Manually review the results to confirm that the replacements are correct."
  70. placement="right"
  71. >
  72. <Button variant="secondary" size="sm" onClick={onEscapeNewlines}>
  73. <span>{forceEscape ? 'Remove escaping' : 'Escape newlines'}&nbsp;</span>
  74. <Icon name="exclamation-triangle" className="muted" size="sm" />
  75. </Button>
  76. </Tooltip>
  77. ),
  78. });
  79. }
  80. return (
  81. <>
  82. {logsMetaItem && (
  83. <MetaInfoText
  84. metaItems={logsMetaItem.map((item) => {
  85. return {
  86. label: item.label,
  87. value: 'kind' in item ? renderMetaItem(item.value, item.kind) : item.value,
  88. };
  89. })}
  90. />
  91. )}
  92. </>
  93. );
  94. }
  95. );
  96. LogsMetaRow.displayName = 'LogsMetaRow';
  97. function renderMetaItem(value: any, kind: LogsMetaKind) {
  98. if (kind === LogsMetaKind.LabelsMap) {
  99. return (
  100. <span className="logs-meta-item__labels">
  101. <LogLabels labels={value} />
  102. </span>
  103. );
  104. } else if (kind === LogsMetaKind.Error) {
  105. return <span className="logs-meta-item__error">{value}</span>;
  106. }
  107. return value;
  108. }