Explore: Add switch to restructure logs for better readability (#36324)

* Add prettifyLogMessage to select components in test file

* Change entry depending on the value of prettifyLogMessage

* Add prettifyLogMessage to state

* Fix merge conflict

* Fixe bug where the log message wasn't parsed as JSON

* Implement function to restructure all logs

* Change elstic image version back to 7.7.1

* Add showCommonLabels that was missing

* Remove comment

* Put import of getParser together with the other imports

* Logs: fix bug where message isn't restructured if it contains ANSI code

* Logs: change label for switch to Restructure

* Remove unnecessary file

* Logs: added divider before switch component

* Add dividers between the different log options

* Remove unintentional changes

* Explore: remove dividers in log settings

* Explore: refactor for LogRowMessage for better readability

* remove unnecessary change

* Logs: fix bug where logs aren't restructured if they have highlights

* Logs: minor refactoring

* Logs: use memoizeOne to prevent parsing on every re-render

* Logs: calculate needsHilight inside renderLogMessage instead of outside

* Logs: fix bug where logs aren't prettified when wrap logs is disabled

* Explore: change name to prettify

* Remove console.log

Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>

* Dashboards: add switch to prettify log messages to the Logs fields

* Logs: make prettify only work for JSON logs

* Logs: fix bug with tests for logs

* Update public/app/plugins/panel/logs/module.tsx

Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>

Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>
This commit is contained in:
Olof Bourghardt
2021-07-16 15:08:47 +02:00
committed by GitHub
parent 96efbbaed1
commit f4f2c197ae
8 changed files with 92 additions and 17 deletions

View File

@@ -40,6 +40,7 @@ interface Props extends Themeable {
showLabels: boolean;
showTime: boolean;
wrapLogMessage: boolean;
prettifyLogMessage: boolean;
timeZone: TimeZone;
enableLogDetails: boolean;
logsSortOrder?: LogsSortOrder | null;
@@ -139,6 +140,7 @@ class UnThemedLogRow extends PureComponent<Props, State> {
showTime,
showDetectedFields,
wrapLogMessage,
prettifyLogMessage,
theme,
getFieldLinks,
forceEscape,
@@ -201,6 +203,7 @@ class UnThemedLogRow extends PureComponent<Props, State> {
contextIsOpen={showContext}
showContextToggle={showContextToggle}
wrapLogMessage={wrapLogMessage}
prettifyLogMessage={prettifyLogMessage}
onToggleContext={this.toggleContext}
/>
)}

View File

@@ -3,6 +3,7 @@ import { isEqual } from 'lodash';
import tinycolor from 'tinycolor2';
import { css, cx } from '@emotion/css';
import { LogRowModel, findHighlightChunksInText, GrafanaTheme } from '@grafana/data';
import memoizeOne from 'memoize-one';
// @ts-ignore
import Highlighter from 'react-highlight-words';
@@ -23,6 +24,7 @@ interface Props extends Themeable {
hasMoreContextRows?: HasMoreContextRows;
contextIsOpen: boolean;
wrapLogMessage: boolean;
prettifyLogMessage: boolean;
errors?: LogRowContextQueryErrors;
context?: LogRowContextRows;
showContextToggle?: (row?: LogRowModel) => boolean;
@@ -47,11 +49,46 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
`,
horizontalScroll: css`
label: verticalScroll;
white-space: nowrap;
white-space: pre;
`,
};
});
function renderLogMessage(
hasAnsi: boolean,
entry: string,
highlights: string[] | undefined,
highlightClassName: string
) {
const needsHighlighter =
highlights && highlights.length > 0 && highlights[0] && highlights[0].length > 0 && entry.length < MAX_CHARACTERS;
if (needsHighlighter) {
return (
<Highlighter
textToHighlight={entry}
searchWords={highlights ?? []}
findChunks={findHighlightChunksInText}
highlightClassName={highlightClassName}
/>
);
} else if (hasAnsi) {
return <LogMessageAnsi value={entry} />;
} else {
return entry;
}
}
const restructureLog = memoizeOne((line: string, prettifyLogMessage: boolean): string => {
if (prettifyLogMessage) {
try {
return JSON.stringify(JSON.parse(line), undefined, 2);
} catch (error) {
return line;
}
}
return line;
});
class UnThemedLogRowMessage extends PureComponent<Props> {
onContextToggle = (e: React.SyntheticEvent<HTMLElement>) => {
e.stopPropagation();
@@ -70,16 +107,16 @@ class UnThemedLogRowMessage extends PureComponent<Props> {
contextIsOpen,
showContextToggle,
wrapLogMessage,
prettifyLogMessage,
onToggleContext,
} = this.props;
const style = getLogRowStyles(theme, row.logLevel);
const { entry, hasAnsi, raw } = row;
const { hasAnsi, raw } = row;
const restructuredEntry = restructureLog(raw, prettifyLogMessage);
const previewHighlights = highlighterExpressions?.length && !isEqual(highlighterExpressions, row.searchWords);
const highlights = previewHighlights ? highlighterExpressions : row.searchWords;
const needsHighlighter =
highlights && highlights.length > 0 && highlights[0] && highlights[0].length > 0 && entry.length < MAX_CHARACTERS;
const highlightClassName = previewHighlights
? cx([style.logsRowMatchHighLight, style.logsRowMatchHighLightPreview])
: cx([style.logsRowMatchHighLight]);
@@ -103,18 +140,7 @@ class UnThemedLogRowMessage extends PureComponent<Props> {
/>
)}
<span className={cx(styles.positionRelative, { [styles.rowWithContext]: contextIsOpen })}>
{needsHighlighter ? (
<Highlighter
textToHighlight={entry}
searchWords={highlights ?? []}
findChunks={findHighlightChunksInText}
highlightClassName={highlightClassName}
/>
) : hasAnsi ? (
<LogMessageAnsi value={raw} />
) : (
entry
)}
{renderLogMessage(hasAnsi, restructuredEntry, highlights, highlightClassName)}
</span>
{showContextToggle?.(row) && (
<span onClick={this.onContextToggle} className={cx('log-row-context', style.context)}>

View File

@@ -16,6 +16,7 @@ describe('LogRows', () => {
showLabels={false}
showTime={false}
wrapLogMessage={true}
prettifyLogMessage={true}
timeZone={'utc'}
enableLogDetails={true}
/>
@@ -38,6 +39,7 @@ describe('LogRows', () => {
showLabels={false}
showTime={false}
wrapLogMessage={true}
prettifyLogMessage={true}
timeZone={'utc'}
previewLimit={1}
enableLogDetails={true}
@@ -69,6 +71,7 @@ describe('LogRows', () => {
showLabels={false}
showTime={false}
wrapLogMessage={true}
prettifyLogMessage={true}
timeZone={'utc'}
enableLogDetails={true}
/>
@@ -90,6 +93,7 @@ describe('LogRows', () => {
showLabels={false}
showTime={false}
wrapLogMessage={true}
prettifyLogMessage={true}
timeZone={'utc'}
enableLogDetails={true}
/>
@@ -112,6 +116,7 @@ describe('LogRows', () => {
showLabels={false}
showTime={false}
wrapLogMessage={true}
prettifyLogMessage={true}
timeZone={'utc'}
logsSortOrder={LogsSortOrder.Ascending}
enableLogDetails={true}
@@ -136,6 +141,7 @@ describe('LogRows', () => {
showLabels={false}
showTime={false}
wrapLogMessage={true}
prettifyLogMessage={true}
timeZone={'utc'}
logsSortOrder={LogsSortOrder.Descending}
enableLogDetails={true}

View File

@@ -20,6 +20,7 @@ export interface Props extends Themeable {
showLabels: boolean;
showTime: boolean;
wrapLogMessage: boolean;
prettifyLogMessage: boolean;
timeZone: TimeZone;
enableLogDetails: boolean;
logsSortOrder?: LogsSortOrder | null;
@@ -84,6 +85,7 @@ class UnThemedLogRows extends PureComponent<Props, State> {
showLabels,
showTime,
wrapLogMessage,
prettifyLogMessage,
logRows,
deduplicatedRows,
highlighterExpressions,
@@ -135,6 +137,7 @@ class UnThemedLogRows extends PureComponent<Props, State> {
showTime={showTime}
showDetectedFields={showDetectedFields}
wrapLogMessage={wrapLogMessage}
prettifyLogMessage={prettifyLogMessage}
timeZone={timeZone}
enableLogDetails={enableLogDetails}
onClickFilterLabel={onClickFilterLabel}
@@ -160,6 +163,7 @@ class UnThemedLogRows extends PureComponent<Props, State> {
showTime={showTime}
showDetectedFields={showDetectedFields}
wrapLogMessage={wrapLogMessage}
prettifyLogMessage={prettifyLogMessage}
timeZone={timeZone}
enableLogDetails={enableLogDetails}
onClickFilterLabel={onClickFilterLabel}