From 18cb2ac9dd391bbd703e9befe3b4a3e94ab21019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Farkas?= Date: Wed, 12 Apr 2023 15:41:33 +0200 Subject: [PATCH] GrafanaUI: Remove obsolete logs exports (#66268) * grafana-ui: removed obsolete logs exports * updated betterer stats * updated CODEOWNERS --- .betterer.results | 10 - .github/CODEOWNERS | 1 - .../src/components/Logs/LogDetails.tsx | 180 ------------ .../components/Logs/LogDetailsRow.test.tsx | 121 -------- .../src/components/Logs/LogDetailsRow.tsx | 224 --------------- .../src/components/Logs/LogLabelStats.tsx | 101 ------- .../src/components/Logs/LogLabelStatsRow.tsx | 85 ------ .../src/components/Logs/LogLabels.test.tsx | 27 -- .../src/components/Logs/LogLabels.tsx | 74 ----- .../components/Logs/LogMessageAnsi.test.tsx | 45 --- .../src/components/Logs/LogMessageAnsi.tsx | 107 ------- .../grafana-ui/src/components/Logs/LogRow.tsx | 261 ------------------ .../components/Logs/LogRowContext.test.tsx | 25 -- .../src/components/Logs/LogRowContext.tsx | 237 ---------------- .../components/Logs/LogRowContextProvider.tsx | 216 --------------- .../src/components/Logs/LogRowMessage.tsx | 191 ------------- .../Logs/LogRowMessageDetectedFields.tsx | 51 ---- .../src/components/Logs/LogRows.tsx | 194 ------------- .../src/components/Logs/getLogRowStyles.ts | 186 ------------- .../src/components/Logs/logParser.ts | 124 --------- packages/grafana-ui/src/components/index.ts | 4 - 21 files changed, 2464 deletions(-) delete mode 100644 packages/grafana-ui/src/components/Logs/LogDetails.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogDetailsRow.test.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogLabelStats.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogLabelStatsRow.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogLabels.test.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogLabels.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogMessageAnsi.test.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogMessageAnsi.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogRow.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogRowContext.test.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogRowContext.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogRowContextProvider.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogRowMessage.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogRowMessageDetectedFields.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/LogRows.tsx delete mode 100644 packages/grafana-ui/src/components/Logs/getLogRowStyles.ts delete mode 100644 packages/grafana-ui/src/components/Logs/logParser.ts diff --git a/.betterer.results b/.betterer.results index c1f01ae34a7..725c072dd3d 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1096,16 +1096,6 @@ exports[`better eslint`] = { "packages/grafana-ui/src/components/Layout/Layout.story.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], - "packages/grafana-ui/src/components/Logs/LogRowContextProvider.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"] - ], - "packages/grafana-ui/src/components/Logs/LogRows.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], - "packages/grafana-ui/src/components/Logs/logParser.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], "packages/grafana-ui/src/components/MatchersUI/FieldValueMatcher.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fe7ad32d3ab..7f881d08f34 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -304,7 +304,6 @@ /packages/grafana-ui/src/components/ @grafana/grafana-frontend-platform /packages/grafana-ui/src/components/DateTimePickers/ @grafana/grafana-frontend-platform /packages/grafana-ui/src/components/GraphNG/ @grafana/dataviz-squad -/packages/grafana-ui/src/components/Logs/ @grafana/observability-logs /packages/grafana-ui/src/components/Table/ @grafana/grafana-bi-squad /packages/grafana-ui/src/components/TimeSeries/ @grafana/dataviz-squad /packages/grafana-ui/src/components/uPlot/ @grafana/dataviz-squad diff --git a/packages/grafana-ui/src/components/Logs/LogDetails.tsx b/packages/grafana-ui/src/components/Logs/LogDetails.tsx deleted file mode 100644 index ffc0724151c..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogDetails.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import { css, cx } from '@emotion/css'; -import memoizeOne from 'memoize-one'; -import React, { PureComponent } from 'react'; - -import { - calculateFieldStats, - calculateLogsLabelStats, - calculateStats, - Field, - getParser, - LinkModel, - LogRowModel, - GrafanaTheme2, -} from '@grafana/data'; - -import { withTheme2 } from '../../themes/index'; -import { Themeable2 } from '../../types/theme'; -import { Icon } from '../Icon/Icon'; -import { Tooltip } from '../Tooltip/Tooltip'; - -import { LogDetailsRow } from './LogDetailsRow'; -import { getLogRowStyles } from './getLogRowStyles'; -import { getAllFields } from './logParser'; - -/** @deprecated will be removed in the next major version */ -export interface Props extends Themeable2 { - row: LogRowModel; - showDuplicates: boolean; - getRows: () => LogRowModel[]; - wrapLogMessage: boolean; - className?: string; - hasError?: boolean; - - onClickFilterLabel?: (key: string, value: string) => void; - onClickFilterOutLabel?: (key: string, value: string) => void; - getFieldLinks?: (field: Field, rowIndex: number) => Array>; - showDetectedFields?: string[]; - onClickShowDetectedField?: (key: string) => void; - onClickHideDetectedField?: (key: string) => void; -} - -const getStyles = (theme: GrafanaTheme2) => { - return { - logsRowLevelDetails: css` - label: logs-row__level_details; - &::after { - top: -3px; - } - `, - logDetails: css` - label: logDetailsDefaultCursor; - cursor: default; - - &:hover { - background-color: ${theme.colors.background.primary}; - } - `, - }; -}; - -class UnThemedLogDetails extends PureComponent { - getParser = memoizeOne(getParser); - - getStatsForDetectedField = (key: string) => { - const matcher = this.getParser(this.props.row.entry)!.buildMatcher(key); - return calculateFieldStats(this.props.getRows(), matcher); - }; - - render() { - const { - row, - theme, - hasError, - onClickFilterOutLabel, - onClickFilterLabel, - getRows, - showDuplicates, - className, - onClickShowDetectedField, - onClickHideDetectedField, - showDetectedFields, - getFieldLinks, - wrapLogMessage, - } = this.props; - const style = getLogRowStyles(theme, row.logLevel); - const styles = getStyles(theme); - const labels = row.labels ? row.labels : {}; - const labelsAvailable = Object.keys(labels).length > 0; - const fields = getAllFields(row, getFieldLinks); - const detectedFieldsAvailable = fields && fields.length > 0; - // If logs with error, we are not showing the level color - const levelClassName = cx(!hasError && [style.logsRowLevel, styles.logsRowLevelDetails]); - - return ( - - {showDuplicates && } - - -
- - - {labelsAvailable && ( - - - - )} - {Object.keys(labels) - .sort() - .map((key) => { - const value = labels[key]; - return ( - calculateLogsLabelStats(getRows(), key)} - onClickFilterOutLabel={onClickFilterOutLabel} - onClickFilterLabel={onClickFilterLabel} - /> - ); - })} - - {detectedFieldsAvailable && ( - - - - )} - {fields.sort().map((field) => { - const { key, value, links, fieldIndex } = field; - return ( - - fieldIndex === undefined - ? this.getStatsForDetectedField(key) - : calculateStats(row.dataFrame.fields[fieldIndex].values.toArray()) - } - showDetectedFields={showDetectedFields} - wrapLogMessage={wrapLogMessage} - /> - ); - })} - {!detectedFieldsAvailable && !labelsAvailable && ( - - - - )} - -
- Log labels -
- Detected fields - - - -
- No details available -
-
- - - ); - } -} - -/** @deprecated will be removed in the next major version */ -export const LogDetails = withTheme2(UnThemedLogDetails); -LogDetails.displayName = 'LogDetails'; diff --git a/packages/grafana-ui/src/components/Logs/LogDetailsRow.test.tsx b/packages/grafana-ui/src/components/Logs/LogDetailsRow.test.tsx deleted file mode 100644 index bf5583b6511..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogDetailsRow.test.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { screen, render, fireEvent } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { ComponentProps } from 'react'; - -import { LogDetailsRow } from './LogDetailsRow'; - -type Props = ComponentProps; - -const setup = (propOverrides?: Partial) => { - const props: Props = { - parsedValue: '', - parsedKey: '', - isLabel: true, - wrapLogMessage: false, - getStats: () => null, - onClickFilterLabel: () => {}, - onClickFilterOutLabel: () => {}, - onClickShowDetectedField: () => {}, - onClickHideDetectedField: () => {}, - showDetectedFields: [], - }; - - Object.assign(props, propOverrides); - - return render( - - - - -
- ); -}; - -describe('LogDetailsRow', () => { - it('should render parsed key', () => { - setup({ parsedKey: 'test key' }); - expect(screen.getByText('test key')).toBeInTheDocument(); - }); - it('should render parsed value', () => { - setup({ parsedValue: 'test value' }); - expect(screen.getByText('test value')).toBeInTheDocument(); - }); - - it('should render metrics button', () => { - setup(); - expect(screen.getAllByTitle('Ad-hoc statistics')).toHaveLength(1); - }); - - describe('if props is a label', () => { - it('should render filter label button', () => { - setup(); - expect(screen.getAllByTitle('Filter for value')).toHaveLength(1); - }); - it('should render filter out label button', () => { - setup(); - expect(screen.getAllByTitle('Filter out value')).toHaveLength(1); - }); - it('should not render filtering buttons if no filtering functions provided', () => { - setup({ onClickFilterLabel: undefined, onClickFilterOutLabel: undefined }); - expect(screen.queryByTitle('Filter out value')).not.toBeInTheDocument(); - }); - }); - - describe('if props is not a label', () => { - it('should not render a filter label button', () => { - setup({ isLabel: false }); - expect(screen.queryByTitle('Filter for value')).not.toBeInTheDocument(); - }); - it('should render a show toggleFieldButton button', () => { - setup({ isLabel: false }); - expect(screen.getAllByTitle('Show this field instead of the message')).toHaveLength(1); - }); - it('should not render a show toggleFieldButton button if no detected fields toggling functions provided', () => { - setup({ - isLabel: false, - onClickShowDetectedField: undefined, - onClickHideDetectedField: undefined, - }); - expect(screen.queryByTitle('Show this field instead of the message')).not.toBeInTheDocument(); - }); - }); - - it('should render stats when stats icon is clicked', () => { - setup({ - parsedKey: 'key', - parsedValue: 'value', - getStats: () => { - return [ - { - count: 1, - proportion: 1 / 2, - value: 'value', - }, - { - count: 1, - proportion: 1 / 2, - value: 'another value', - }, - ]; - }, - }); - - expect(screen.queryByTestId('logLabelStats')).not.toBeInTheDocument(); - const adHocStatsButton = screen.getByTitle('Ad-hoc statistics'); - fireEvent.click(adHocStatsButton); - expect(screen.getByTestId('logLabelStats')).toBeInTheDocument(); - expect(screen.getByTestId('logLabelStats')).toHaveTextContent('another value'); - }); - - it('should render clipboard button on hover of log row table value', async () => { - setup({ parsedKey: 'key', parsedValue: 'value' }); - - const valueCell = screen.getByRole('cell', { name: 'value' }); - await userEvent.hover(valueCell); - - expect(screen.getByRole('button', { name: 'Copy value to clipboard' })).toBeInTheDocument(); - await userEvent.unhover(valueCell); - - expect(screen.queryByRole('button', { name: 'Copy value to clipboard' })).not.toBeInTheDocument(); - }); -}); diff --git a/packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx b/packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx deleted file mode 100644 index 9c82ad9c791..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx +++ /dev/null @@ -1,224 +0,0 @@ -import { css, cx } from '@emotion/css'; -import React, { PureComponent } from 'react'; - -import { Field, LinkModel, LogLabelStatsModel, GrafanaTheme2 } from '@grafana/data'; - -import { withTheme2 } from '../../themes/index'; -import { Themeable2 } from '../../types/theme'; -import { ClipboardButton } from '../ClipboardButton/ClipboardButton'; -import { DataLinkButton } from '../DataLinks/DataLinkButton'; -import { IconButton } from '../IconButton/IconButton'; - -import { LogLabelStats } from './LogLabelStats'; -import { getLogRowStyles } from './getLogRowStyles'; - -/** @deprecated will be removed in the next major version */ -export interface Props extends Themeable2 { - parsedValue: string; - parsedKey: string; - wrapLogMessage?: boolean; - isLabel?: boolean; - onClickFilterLabel?: (key: string, value: string) => void; - onClickFilterOutLabel?: (key: string, value: string) => void; - links?: Array>; - getStats: () => LogLabelStatsModel[] | null; - showDetectedFields?: string[]; - onClickShowDetectedField?: (key: string) => void; - onClickHideDetectedField?: (key: string) => void; -} - -interface State { - showFieldsStats: boolean; - fieldCount: number; - fieldStats: LogLabelStatsModel[] | null; - mouseOver: boolean; -} - -const getStyles = (theme: GrafanaTheme2) => { - return { - noHoverBackground: css` - label: noHoverBackground; - :hover { - background-color: transparent; - } - `, - hoverCursor: css` - label: hoverCursor; - cursor: pointer; - `, - wordBreakAll: css` - label: wordBreakAll; - word-break: break-all; - `, - showingField: css` - color: ${theme.colors.primary.text}; - `, - hoverValueCopy: css` - margin: ${theme.spacing(0, 0, 0, 1.2)}; - position: absolute; - top: 0px; - justify-content: center; - border-radius: ${theme.shape.radius.circle}; - width: 26px; - height: 26px; - `, - wrapLine: css` - label: wrapLine; - white-space: pre-wrap; - `, - }; -}; -class UnThemedLogDetailsRow extends PureComponent { - state: State = { - showFieldsStats: false, - fieldCount: 0, - fieldStats: null, - mouseOver: false, - }; - - showField = () => { - const { onClickShowDetectedField, parsedKey } = this.props; - if (onClickShowDetectedField) { - onClickShowDetectedField(parsedKey); - } - }; - - hideField = () => { - const { onClickHideDetectedField, parsedKey } = this.props; - if (onClickHideDetectedField) { - onClickHideDetectedField(parsedKey); - } - }; - - filterLabel = () => { - const { onClickFilterLabel, parsedKey, parsedValue } = this.props; - if (onClickFilterLabel) { - onClickFilterLabel(parsedKey, parsedValue); - } - }; - - filterOutLabel = () => { - const { onClickFilterOutLabel, parsedKey, parsedValue } = this.props; - if (onClickFilterOutLabel) { - onClickFilterOutLabel(parsedKey, parsedValue); - } - }; - - showStats = () => { - const { showFieldsStats } = this.state; - if (!showFieldsStats) { - const fieldStats = this.props.getStats(); - const fieldCount = fieldStats ? fieldStats.reduce((sum, stat) => sum + stat.count, 0) : 0; - this.setState({ fieldStats, fieldCount }); - } - this.toggleFieldsStats(); - }; - - toggleFieldsStats() { - this.setState((state) => { - return { - showFieldsStats: !state.showFieldsStats, - }; - }); - } - - hoverValueCopy() { - const mouseOver = !this.state.mouseOver; - this.setState({ mouseOver }); - } - - render() { - const { - theme, - parsedKey, - parsedValue, - isLabel, - links, - showDetectedFields, - wrapLogMessage, - onClickShowDetectedField, - onClickHideDetectedField, - onClickFilterLabel, - onClickFilterOutLabel, - } = this.props; - const { showFieldsStats, fieldStats, fieldCount, mouseOver } = this.state; - const styles = getStyles(theme); - const style = getLogRowStyles(theme); - - const hasDetectedFieldsFunctionality = onClickShowDetectedField && onClickHideDetectedField; - const hasFilteringFunctionality = onClickFilterLabel && onClickFilterOutLabel; - - const toggleFieldButton = - !isLabel && showDetectedFields && showDetectedFields.includes(parsedKey) ? ( - - ) : ( - - ); - - return ( - - {/* Action buttons - show stats/filter results */} - - - - - {hasFilteringFunctionality && isLabel && ( - <> - - - - - - - - )} - - {hasDetectedFieldsFunctionality && !isLabel && ( - - {toggleFieldButton} - - )} - - {/* Key - value columns */} - {parsedKey} - - {parsedValue} - {mouseOver && ( - parsedValue} - title="Copy value to clipboard" - fill="text" - variant="secondary" - icon="copy" - size="sm" - className={styles.hoverValueCopy} - /> - )} - {links?.map((link) => ( - -   - - - ))} - {showFieldsStats && ( - - )} - - - ); - } -} - -/** @deprecated will be removed in the next major version */ -export const LogDetailsRow = withTheme2(UnThemedLogDetailsRow); -LogDetailsRow.displayName = 'LogDetailsRow'; diff --git a/packages/grafana-ui/src/components/Logs/LogLabelStats.tsx b/packages/grafana-ui/src/components/Logs/LogLabelStats.tsx deleted file mode 100644 index 96bba271e25..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogLabelStats.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { css } from '@emotion/css'; -import React, { PureComponent } from 'react'; - -import { LogLabelStatsModel, GrafanaTheme2 } from '@grafana/data'; - -import { stylesFactory } from '../../themes'; -import { withTheme2 } from '../../themes/index'; -import { Themeable2 } from '../../types/theme'; - -//Components -import { LogLabelStatsRow } from './LogLabelStatsRow'; - -const STATS_ROW_LIMIT = 5; - -const getStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - logsStats: css` - label: logs-stats; - background: inherit; - color: ${theme.colors.text.primary}; - word-break: break-all; - width: fit-content; - max-width: 100%; - `, - logsStatsHeader: css` - label: logs-stats__header; - border-bottom: 1px solid ${theme.colors.border.medium}; - display: flex; - `, - logsStatsTitle: css` - label: logs-stats__title; - font-weight: ${theme.typography.fontWeightMedium}; - padding-right: ${theme.spacing(2)}; - display: inline-block; - white-space: nowrap; - text-overflow: ellipsis; - flex-grow: 1; - `, - logsStatsClose: css` - label: logs-stats__close; - cursor: pointer; - `, - logsStatsBody: css` - label: logs-stats__body; - padding: 5px 0; - `, - }; -}); - -interface Props extends Themeable2 { - stats: LogLabelStatsModel[]; - label: string; - value: string; - rowCount: number; - isLabel?: boolean; -} - -class UnThemedLogLabelStats extends PureComponent { - render() { - const { label, rowCount, stats, value, theme, isLabel } = this.props; - const style = getStyles(theme); - const topRows = stats.slice(0, STATS_ROW_LIMIT); - let activeRow = topRows.find((row) => row.value === value); - let otherRows = stats.slice(STATS_ROW_LIMIT); - const insertActiveRow = !activeRow; - - // Remove active row from other to show extra - if (insertActiveRow) { - activeRow = otherRows.find((row) => row.value === value); - otherRows = otherRows.filter((row) => row.value !== value); - } - - const otherCount = otherRows.reduce((sum, row) => sum + row.count, 0); - const topCount = topRows.reduce((sum, row) => sum + row.count, 0); - const total = topCount + otherCount; - const otherProportion = otherCount / total; - - return ( -
-
-
- {label}: {total} of {rowCount} rows have that {isLabel ? 'label' : 'field'} -
-
-
- {topRows.map((stat) => ( - - ))} - {insertActiveRow && activeRow && } - {otherCount > 0 && ( - - )} -
-
- ); - } -} - -/** @deprecated will be removed in the next major version */ -export const LogLabelStats = withTheme2(UnThemedLogLabelStats); -LogLabelStats.displayName = 'LogLabelStats'; diff --git a/packages/grafana-ui/src/components/Logs/LogLabelStatsRow.tsx b/packages/grafana-ui/src/components/Logs/LogLabelStatsRow.tsx deleted file mode 100644 index 56c6ff201ec..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogLabelStatsRow.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { css, cx } from '@emotion/css'; -import React from 'react'; - -import { GrafanaTheme2 } from '@grafana/data'; - -import { useStyles2 } from '../../themes/ThemeContext'; - -const getStyles = (theme: GrafanaTheme2) => ({ - logsStatsRow: css` - label: logs-stats-row; - margin: ${parseInt(theme.spacing(2), 10) / 1.75}px 0; - `, - logsStatsRowActive: css` - label: logs-stats-row--active; - color: ${theme.colors.primary.text}; - position: relative; - `, - logsStatsRowLabel: css` - label: logs-stats-row__label; - display: flex; - margin-bottom: 1px; - `, - logsStatsRowValue: css` - label: logs-stats-row__value; - flex: 1; - text-overflow: ellipsis; - overflow: hidden; - `, - logsStatsRowCount: css` - label: logs-stats-row__count; - text-align: right; - margin-left: 0.5em; - `, - logsStatsRowPercent: css` - label: logs-stats-row__percent; - text-align: right; - margin-left: 0.5em; - width: 3em; - `, - logsStatsRowBar: css` - label: logs-stats-row__bar; - height: 4px; - overflow: hidden; - background: ${theme.colors.text.disabled}; - `, - logsStatsRowInnerBar: css` - label: logs-stats-row__innerbar; - height: 4px; - overflow: hidden; - background: ${theme.colors.primary.main}; - `, -}); - -/** @deprecated will be removed in the next major version */ -export interface Props { - active?: boolean; - count: number; - proportion: number; - value?: string; -} - -/** @deprecated will be removed in the next major version */ -export const LogLabelStatsRow = ({ active, count, proportion, value }: Props) => { - const style = useStyles2(getStyles); - const percent = `${Math.round(proportion * 100)}%`; - const barStyle = { width: percent }; - const className = active ? cx([style.logsStatsRow, style.logsStatsRowActive]) : cx([style.logsStatsRow]); - - return ( -
-
-
- {value} -
-
{count}
-
{percent}
-
-
-
-
-
- ); -}; - -LogLabelStatsRow.displayName = 'LogLabelStatsRow'; diff --git a/packages/grafana-ui/src/components/Logs/LogLabels.test.tsx b/packages/grafana-ui/src/components/Logs/LogLabels.test.tsx deleted file mode 100644 index e76459f0b65..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogLabels.test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import React from 'react'; - -import { LogLabels } from './LogLabels'; - -describe('', () => { - it('renders notice when no labels are found', () => { - render(); - expect(screen.queryByText('(no unique labels)')).toBeInTheDocument(); - }); - it('renders labels', () => { - render(); - expect(screen.queryByText('bar')).toBeInTheDocument(); - expect(screen.queryByText('42')).toBeInTheDocument(); - }); - it('excludes labels with certain names or labels starting with underscore', () => { - render(); - expect(screen.queryByText('bar')).toBeInTheDocument(); - expect(screen.queryByText('42')).not.toBeInTheDocument(); - expect(screen.queryByText('13')).not.toBeInTheDocument(); - }); - it('excludes labels with empty string values', () => { - render(); - expect(screen.queryByText('bar')).toBeInTheDocument(); - expect(screen.queryByText('baz')).not.toBeInTheDocument(); - }); -}); diff --git a/packages/grafana-ui/src/components/Logs/LogLabels.tsx b/packages/grafana-ui/src/components/Logs/LogLabels.tsx deleted file mode 100644 index 9a3126cf7f4..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogLabels.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { css, cx } from '@emotion/css'; -import React from 'react'; - -import { GrafanaTheme2, Labels } from '@grafana/data'; - -import { useStyles2 } from '../../themes/ThemeContext'; - -// Levels are already encoded in color, filename is a Loki-ism -const HIDDEN_LABELS = ['level', 'lvl', 'filename']; - -interface Props { - labels: Labels; -} - -/** @deprecated will be removed in the next major version */ -export const LogLabels = ({ labels }: Props) => { - const styles = useStyles2(getStyles); - const displayLabels = Object.keys(labels).filter((label) => !label.startsWith('_') && !HIDDEN_LABELS.includes(label)); - - if (displayLabels.length === 0) { - return ( - - (no unique labels) - - ); - } - - return ( - - {displayLabels.sort().map((label) => { - const value = labels[label]; - if (!value) { - return; - } - const tooltip = `${label}: ${value}`; - return ( - - - {value} - - - ); - })} - - ); -}; - -const getStyles = (theme: GrafanaTheme2) => { - return { - logsLabels: css` - display: flex; - flex-wrap: wrap; - font-size: ${theme.typography.size.xs}; - `, - logsLabel: css` - label: logs-label; - display: flex; - padding: 0 2px; - background-color: ${theme.colors.background.secondary}; - border-radius: ${theme.shape.borderRadius(1)}; - margin: 1px 4px 0 0; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - `, - logsLabelValue: css` - label: logs-label__value; - display: inline-block; - max-width: 20em; - text-overflow: ellipsis; - overflow: hidden; - `, - }; -}; diff --git a/packages/grafana-ui/src/components/Logs/LogMessageAnsi.test.tsx b/packages/grafana-ui/src/components/Logs/LogMessageAnsi.test.tsx deleted file mode 100644 index cfc197459b6..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogMessageAnsi.test.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { render, screen, within } from '@testing-library/react'; -import React from 'react'; - -import { createTheme } from '@grafana/data'; - -import { UnThemedLogMessageAnsi as LogMessageAnsi } from './LogMessageAnsi'; - -describe('', () => { - it('renders string without ANSI codes', () => { - render(); - - expect(screen.queryByTestId('ansiLogLine')).not.toBeInTheDocument(); - expect(screen.queryByText('Lorem ipsum')).toBeInTheDocument(); - }); - it('renders string with ANSI codes', () => { - const value = 'Lorem \u001B[31mipsum\u001B[0m et dolor'; - render(); - - expect(screen.queryByTestId('ansiLogLine')).toBeInTheDocument(); - expect(screen.getAllByTestId('ansiLogLine')).toHaveLength(1); - expect(screen.getAllByTestId('ansiLogLine').at(0)).toHaveAttribute('style', expect.stringMatching('color')); - - const { getByText } = within(screen.getAllByTestId('ansiLogLine').at(0)!); - expect(getByText('ipsum')).toBeInTheDocument(); - }); - it('renders string with ANSI codes with correctly converted css classnames', () => { - const value = 'Lorem \u001B[1;32mIpsum'; - render(); - - expect(screen.queryByTestId('ansiLogLine')).toBeInTheDocument(); - expect(screen.getAllByTestId('ansiLogLine')).toHaveLength(1); - - expect(screen.getAllByTestId('ansiLogLine').at(0)).toHaveAttribute('style', expect.stringMatching('font-weight')); - }); - it('renders string with ANSI dim code with appropriate themed color', () => { - const value = 'Lorem \u001B[1;2mIpsum'; - const theme = createTheme(); - render(); - - expect(screen.queryByTestId('ansiLogLine')).toBeInTheDocument(); - expect(screen.getAllByTestId('ansiLogLine')).toHaveLength(1); - - expect(screen.getAllByTestId('ansiLogLine').at(0)).toHaveStyle({ color: theme.colors.text.secondary }); - }); -}); diff --git a/packages/grafana-ui/src/components/Logs/LogMessageAnsi.tsx b/packages/grafana-ui/src/components/Logs/LogMessageAnsi.tsx deleted file mode 100644 index 0178098e851..00000000000 --- a/packages/grafana-ui/src/components/Logs/LogMessageAnsi.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import ansicolor from 'ansicolor'; -import React, { PureComponent } from 'react'; -import Highlighter from 'react-highlight-words'; - -import { findHighlightChunksInText, GrafanaTheme2 } from '@grafana/data'; - -import { withTheme2 } from '../../themes'; -import { Themeable2 } from '../../types'; - -interface Style { - [key: string]: string; -} - -interface ParsedChunk { - style: Style; - text: string; -} - -function convertCSSToStyle(theme: GrafanaTheme2, css: string): Style { - return css.split(/;\s*/).reduce