mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore/Logs: Escaping of incorrectly escaped log lines (#31352)
* POC: Escaping of incorrectly escaped log lines * Remove unused import * Fix test, change copy * Make escapedNewlines optional * Fix typechecks * Remove loading state from the escaping button * Update namings
This commit is contained in:
@@ -62,6 +62,7 @@ export interface LogRowModel {
|
||||
// Actual log line
|
||||
entry: string;
|
||||
hasAnsi: boolean;
|
||||
hasUnescapedContent: boolean;
|
||||
labels: Labels;
|
||||
logLevel: LogLevel;
|
||||
raw: string;
|
||||
|
||||
@@ -295,6 +295,7 @@ describe('sortLogsResult', () => {
|
||||
dataFrame: new MutableDataFrame(),
|
||||
entry: '',
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {},
|
||||
logLevel: LogLevel.info,
|
||||
raw: '',
|
||||
@@ -312,6 +313,7 @@ describe('sortLogsResult', () => {
|
||||
dataFrame: new MutableDataFrame(),
|
||||
entry: '',
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {},
|
||||
logLevel: LogLevel.info,
|
||||
raw: '',
|
||||
|
||||
@@ -223,3 +223,6 @@ export const checkLogsError = (logRow: LogRowModel): { hasError: boolean; errorM
|
||||
hasError: false,
|
||||
};
|
||||
};
|
||||
|
||||
export const escapeUnescapedString = (string: string) =>
|
||||
string.replace(/\\n|\\t|\\r/g, (match: string) => (match.slice(1) === 't' ? '\t' : '\n'));
|
||||
|
||||
@@ -20,6 +20,7 @@ const setup = (propOverrides?: Partial<Props>, rowOverrides?: Partial<LogRowMode
|
||||
timeLocal: '',
|
||||
timeUtc: '',
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
entry: '',
|
||||
raw: '',
|
||||
uid: '0',
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
GrafanaTheme,
|
||||
dateTimeFormat,
|
||||
checkLogsError,
|
||||
escapeUnescapedString,
|
||||
} from '@grafana/data';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
import { Tooltip } from '../Tooltip/Tooltip';
|
||||
@@ -42,6 +43,8 @@ interface Props extends Themeable {
|
||||
timeZone: TimeZone;
|
||||
allowDetails?: boolean;
|
||||
logsSortOrder?: LogsSortOrder | null;
|
||||
forceEscape?: boolean;
|
||||
showDetectedFields?: string[];
|
||||
getRows: () => LogRowModel[];
|
||||
onClickFilterLabel?: (key: string, value: string) => void;
|
||||
onClickFilterOutLabel?: (key: string, value: string) => void;
|
||||
@@ -49,7 +52,6 @@ interface Props extends Themeable {
|
||||
getRowContext: (row: LogRowModel, options?: RowContextOptions) => Promise<DataQueryResponse>;
|
||||
getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
|
||||
showContextToggle?: (row?: LogRowModel) => boolean;
|
||||
showDetectedFields?: string[];
|
||||
onClickShowDetectedField?: (key: string) => void;
|
||||
onClickHideDetectedField?: (key: string) => void;
|
||||
}
|
||||
@@ -139,6 +141,7 @@ class UnThemedLogRow extends PureComponent<Props, State> {
|
||||
wrapLogMessage,
|
||||
theme,
|
||||
getFieldLinks,
|
||||
forceEscape,
|
||||
} = this.props;
|
||||
const { showDetails, showContext } = this.state;
|
||||
const style = getLogRowStyles(theme, row.logLevel);
|
||||
@@ -148,12 +151,15 @@ class UnThemedLogRow extends PureComponent<Props, State> {
|
||||
[styles.errorLogRow]: hasError,
|
||||
});
|
||||
|
||||
const processedRow =
|
||||
row.hasUnescapedContent && forceEscape ? { ...row, entry: escapeUnescapedString(row.entry) } : row;
|
||||
|
||||
return (
|
||||
<>
|
||||
<tr className={logRowBackground} onClick={this.toggleDetails}>
|
||||
{showDuplicates && (
|
||||
<td className={style.logsRowDuplicates}>
|
||||
{row.duplicates && row.duplicates > 0 ? `${row.duplicates + 1}x` : null}
|
||||
{processedRow.duplicates && processedRow.duplicates > 0 ? `${processedRow.duplicates + 1}x` : null}
|
||||
</td>
|
||||
)}
|
||||
<td className={cx({ [style.logsRowLevel]: !hasError })}>
|
||||
@@ -169,14 +175,14 @@ class UnThemedLogRow extends PureComponent<Props, State> {
|
||||
</td>
|
||||
)}
|
||||
{showTime && <td className={style.logsRowLocalTime}>{this.renderTimeStamp(row.timeEpochMs)}</td>}
|
||||
{showLabels && row.uniqueLabels && (
|
||||
{showLabels && processedRow.uniqueLabels && (
|
||||
<td className={style.logsRowLabels}>
|
||||
<LogLabels labels={row.uniqueLabels} />
|
||||
<LogLabels labels={processedRow.uniqueLabels} />
|
||||
</td>
|
||||
)}
|
||||
{showDetectedFields && showDetectedFields.length > 0 ? (
|
||||
<LogRowMessageDetectedFields
|
||||
row={row}
|
||||
row={processedRow}
|
||||
showDetectedFields={showDetectedFields!}
|
||||
getFieldLinks={getFieldLinks}
|
||||
wrapLogMessage={wrapLogMessage}
|
||||
@@ -184,7 +190,7 @@ class UnThemedLogRow extends PureComponent<Props, State> {
|
||||
) : (
|
||||
<LogRowMessage
|
||||
highlighterExpressions={highlighterExpressions}
|
||||
row={row}
|
||||
row={processedRow}
|
||||
getRows={getRows}
|
||||
errors={errors}
|
||||
hasMoreContextRows={hasMoreContextRows}
|
||||
@@ -207,7 +213,7 @@ class UnThemedLogRow extends PureComponent<Props, State> {
|
||||
onClickShowDetectedField={onClickShowDetectedField}
|
||||
onClickHideDetectedField={onClickHideDetectedField}
|
||||
getRows={getRows}
|
||||
row={row}
|
||||
row={processedRow}
|
||||
wrapLogMessage={wrapLogMessage}
|
||||
hasError={hasError}
|
||||
showDetectedFields={showDetectedFields}
|
||||
@@ -219,16 +225,12 @@ class UnThemedLogRow extends PureComponent<Props, State> {
|
||||
|
||||
render() {
|
||||
const { showContext } = this.state;
|
||||
const { logsSortOrder } = this.props;
|
||||
const { logsSortOrder, row, getRowContext } = this.props;
|
||||
|
||||
if (showContext) {
|
||||
return (
|
||||
<>
|
||||
<LogRowContextProvider
|
||||
row={this.props.row}
|
||||
getRowContext={this.props.getRowContext}
|
||||
logsSortOrder={logsSortOrder}
|
||||
>
|
||||
<LogRowContextProvider row={row} getRowContext={getRowContext} logsSortOrder={logsSortOrder}>
|
||||
{({ result, errors, hasMoreContextRows, updateLimit }) => {
|
||||
return <>{this.renderLogRow(result, errors, hasMoreContextRows, updateLimit)}</>;
|
||||
}}
|
||||
|
||||
@@ -181,6 +181,7 @@ const row: LogRowModel = {
|
||||
entry: '4',
|
||||
labels: (null as any) as Labels,
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
raw: '4',
|
||||
logLevel: LogLevel.info,
|
||||
timeEpochMs: 4,
|
||||
|
||||
@@ -155,6 +155,7 @@ const makeLog = (overrides: Partial<LogRowModel>): LogRowModel => {
|
||||
logLevel: LogLevel.debug,
|
||||
entry,
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {},
|
||||
raw: entry,
|
||||
timeFromNow: '',
|
||||
|
||||
@@ -17,7 +17,6 @@ export interface Props extends Themeable {
|
||||
deduplicatedRows?: LogRowModel[];
|
||||
dedupStrategy: LogsDedupStrategy;
|
||||
highlighterExpressions?: string[];
|
||||
showContextToggle?: (row?: LogRowModel) => boolean;
|
||||
showLabels: boolean;
|
||||
showTime: boolean;
|
||||
wrapLogMessage: boolean;
|
||||
@@ -28,11 +27,13 @@ export interface Props extends Themeable {
|
||||
// Passed to fix problems with inactive scrolling in Logs Panel
|
||||
// Can be removed when we unify scrolling for Panel and Explore
|
||||
disableCustomHorizontalScroll?: boolean;
|
||||
forceEscape?: boolean;
|
||||
showDetectedFields?: string[];
|
||||
showContextToggle?: (row?: LogRowModel) => boolean;
|
||||
onClickFilterLabel?: (key: string, value: string) => void;
|
||||
onClickFilterOutLabel?: (key: string, value: string) => void;
|
||||
getRowContext?: (row: LogRowModel, options?: RowContextOptions) => Promise<any>;
|
||||
getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
|
||||
showDetectedFields?: string[];
|
||||
onClickShowDetectedField?: (key: string) => void;
|
||||
onClickHideDetectedField?: (key: string) => void;
|
||||
}
|
||||
@@ -101,6 +102,7 @@ class UnThemedLogRows extends PureComponent<Props, State> {
|
||||
showDetectedFields,
|
||||
onClickShowDetectedField,
|
||||
onClickHideDetectedField,
|
||||
forceEscape,
|
||||
} = this.props;
|
||||
const { renderAll } = this.state;
|
||||
const { logsRowsTable, logsRowsHorizontalScroll } = getLogRowStyles(theme);
|
||||
@@ -151,6 +153,7 @@ class UnThemedLogRows extends PureComponent<Props, State> {
|
||||
onClickHideDetectedField={onClickHideDetectedField}
|
||||
getFieldLinks={getFieldLinks}
|
||||
logsSortOrder={logsSortOrder}
|
||||
forceEscape={forceEscape}
|
||||
/>
|
||||
))}
|
||||
{hasData &&
|
||||
@@ -175,6 +178,7 @@ class UnThemedLogRows extends PureComponent<Props, State> {
|
||||
onClickHideDetectedField={onClickHideDetectedField}
|
||||
getFieldLinks={getFieldLinks}
|
||||
logsSortOrder={logsSortOrder}
|
||||
forceEscape={forceEscape}
|
||||
/>
|
||||
))}
|
||||
{hasData && !renderAll && (
|
||||
|
||||
Reference in New Issue
Block a user