mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Logs: Added multi-line display control to the "wrap lines" option (#88144)
* LogRowMessage: strip new lines when wrapping is disabled * LogRowMessage: prevent conflicts between failed json parsing and unwrapping * LogRowMessage: expand multi-line unwrapped logs when opening details * Add unit test * Prettier * chore: update comment
This commit is contained in:
parent
6f9527b4c2
commit
97cb92eb1e
public/app/features/logs/components
@ -308,6 +308,7 @@ class UnThemedLogRow extends PureComponent<Props, State> {
|
|||||||
pinned={this.props.pinned}
|
pinned={this.props.pinned}
|
||||||
mouseIsOver={this.state.mouseIsOver}
|
mouseIsOver={this.state.mouseIsOver}
|
||||||
onBlur={this.onMouseLeave}
|
onBlur={this.onMouseLeave}
|
||||||
|
expanded={this.state.showDetails}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -160,4 +160,41 @@ describe('LogRowMessage', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('For multi-line logs', () => {
|
||||||
|
const entry = `Line1
|
||||||
|
line2
|
||||||
|
line3`;
|
||||||
|
const singleLineEntry = entry.replace(/(\r\n|\n|\r)/g, '');
|
||||||
|
it('Displays the original log line when wrapping is enabled', () => {
|
||||||
|
setup({
|
||||||
|
row: createLogRow({ entry, logLevel: LogLevel.error, timeEpochMs: 1546297200000 }),
|
||||||
|
wrapLogMessage: true,
|
||||||
|
});
|
||||||
|
expect(screen.getByText(/Line1/)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(/line2/)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(/line3/)).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText(singleLineEntry)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Removes new lines from the original log line when wrapping is disabled', () => {
|
||||||
|
setup({
|
||||||
|
row: createLogRow({ entry, logLevel: LogLevel.error, timeEpochMs: 1546297200000 }),
|
||||||
|
wrapLogMessage: false,
|
||||||
|
});
|
||||||
|
expect(screen.getByText(singleLineEntry)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Displays the original log line when the line is expanded', () => {
|
||||||
|
setup({
|
||||||
|
row: createLogRow({ entry, logLevel: LogLevel.error, timeEpochMs: 1546297200000 }),
|
||||||
|
wrapLogMessage: true,
|
||||||
|
expanded: true,
|
||||||
|
});
|
||||||
|
expect(screen.getByText(/Line1/)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(/line2/)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(/line3/)).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText(singleLineEntry)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -29,6 +29,7 @@ interface Props {
|
|||||||
styles: LogRowStyles;
|
styles: LogRowStyles;
|
||||||
mouseIsOver: boolean;
|
mouseIsOver: boolean;
|
||||||
onBlur: () => void;
|
onBlur: () => void;
|
||||||
|
expanded?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LogMessageProps {
|
interface LogMessageProps {
|
||||||
@ -58,13 +59,20 @@ const LogMessage = ({ hasAnsi, entry, highlights, styles }: LogMessageProps) =>
|
|||||||
return <>{entry}</>;
|
return <>{entry}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const restructureLog = (line: string, prettifyLogMessage: boolean): string => {
|
const restructureLog = (
|
||||||
|
line: string,
|
||||||
|
prettifyLogMessage: boolean,
|
||||||
|
wrapLogMessage: boolean,
|
||||||
|
expanded: boolean
|
||||||
|
): string => {
|
||||||
if (prettifyLogMessage) {
|
if (prettifyLogMessage) {
|
||||||
try {
|
try {
|
||||||
return JSON.stringify(JSON.parse(line), undefined, 2);
|
return JSON.stringify(JSON.parse(line), undefined, 2);
|
||||||
} catch (error) {
|
} catch (error) {}
|
||||||
return line;
|
|
||||||
}
|
}
|
||||||
|
// With wrapping disabled, we want to turn it into a single-line log entry unless the line is expanded
|
||||||
|
if (!wrapLogMessage && !expanded) {
|
||||||
|
line = line.replace(/(\r\n|\n|\r)/g, '');
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
};
|
};
|
||||||
@ -84,9 +92,13 @@ export const LogRowMessage = React.memo((props: Props) => {
|
|||||||
mouseIsOver,
|
mouseIsOver,
|
||||||
onBlur,
|
onBlur,
|
||||||
getRowContextQuery,
|
getRowContextQuery,
|
||||||
|
expanded,
|
||||||
} = props;
|
} = props;
|
||||||
const { hasAnsi, raw } = row;
|
const { hasAnsi, raw } = row;
|
||||||
const restructuredEntry = useMemo(() => restructureLog(raw, prettifyLogMessage), [raw, prettifyLogMessage]);
|
const restructuredEntry = useMemo(
|
||||||
|
() => restructureLog(raw, prettifyLogMessage, wrapLogMessage, Boolean(expanded)),
|
||||||
|
[raw, prettifyLogMessage, wrapLogMessage, expanded]
|
||||||
|
);
|
||||||
const shouldShowMenu = useMemo(() => mouseIsOver || pinned, [mouseIsOver, pinned]);
|
const shouldShowMenu = useMemo(() => mouseIsOver || pinned, [mouseIsOver, pinned]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
Loading…
Reference in New Issue
Block a user