2023-07-11 20:50:53 +08:00
|
|
|
import React, { useMemo } from 'react';
|
2022-09-19 16:51:46 +08:00
|
|
|
import Highlighter from 'react-highlight-words';
|
|
|
|
|
|
2023-06-06 02:24:41 +08:00
|
|
|
import { CoreApp, findHighlightChunksInText, LogRowModel } from '@grafana/data';
|
2022-09-19 16:51:46 +08:00
|
|
|
|
|
|
|
|
import { LogMessageAnsi } from './LogMessageAnsi';
|
2023-07-11 20:50:53 +08:00
|
|
|
import { LogRowMenuCell } from './LogRowMenuCell';
|
2023-02-01 22:28:10 +08:00
|
|
|
import { LogRowStyles } from './getLogRowStyles';
|
2022-09-19 16:51:46 +08:00
|
|
|
|
|
|
|
|
export const MAX_CHARACTERS = 100000;
|
|
|
|
|
|
2023-02-01 22:28:10 +08:00
|
|
|
interface Props {
|
2022-09-19 16:51:46 +08:00
|
|
|
row: LogRowModel;
|
|
|
|
|
wrapLogMessage: boolean;
|
|
|
|
|
prettifyLogMessage: boolean;
|
2022-09-29 16:00:01 +08:00
|
|
|
app?: CoreApp;
|
2022-09-19 16:51:46 +08:00
|
|
|
showContextToggle?: (row?: LogRowModel) => boolean;
|
2023-04-14 23:05:43 +08:00
|
|
|
onOpenContext: (row: LogRowModel) => void;
|
2023-06-16 20:07:51 +08:00
|
|
|
onPermalinkClick?: (row: LogRowModel) => Promise<void>;
|
2023-06-28 21:22:54 +08:00
|
|
|
onPinLine?: (row: LogRowModel) => void;
|
|
|
|
|
onUnpinLine?: (row: LogRowModel) => void;
|
|
|
|
|
pinned?: boolean;
|
2023-02-01 22:28:10 +08:00
|
|
|
styles: LogRowStyles;
|
2022-09-19 16:51:46 +08:00
|
|
|
}
|
|
|
|
|
|
2023-07-11 20:50:53 +08:00
|
|
|
interface LogMessageProps {
|
|
|
|
|
hasAnsi: boolean;
|
|
|
|
|
entry: string;
|
|
|
|
|
highlights: string[] | undefined;
|
|
|
|
|
styles: LogRowStyles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const LogMessage = ({ hasAnsi, entry, highlights, styles }: LogMessageProps) => {
|
2022-09-19 16:51:46 +08:00
|
|
|
const needsHighlighter =
|
|
|
|
|
highlights && highlights.length > 0 && highlights[0] && highlights[0].length > 0 && entry.length < MAX_CHARACTERS;
|
|
|
|
|
const searchWords = highlights ?? [];
|
|
|
|
|
if (hasAnsi) {
|
2023-07-11 20:50:53 +08:00
|
|
|
const highlight = needsHighlighter ? { searchWords, highlightClassName: styles.logsRowMatchHighLight } : undefined;
|
2022-09-19 16:51:46 +08:00
|
|
|
return <LogMessageAnsi value={entry} highlight={highlight} />;
|
|
|
|
|
} else if (needsHighlighter) {
|
|
|
|
|
return (
|
|
|
|
|
<Highlighter
|
|
|
|
|
textToHighlight={entry}
|
|
|
|
|
searchWords={searchWords}
|
|
|
|
|
findChunks={findHighlightChunksInText}
|
2023-07-11 20:50:53 +08:00
|
|
|
highlightClassName={styles.logsRowMatchHighLight}
|
2022-09-19 16:51:46 +08:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-07-11 20:50:53 +08:00
|
|
|
return <>{entry}</>;
|
|
|
|
|
};
|
2022-09-19 16:51:46 +08:00
|
|
|
|
2023-07-11 20:50:53 +08:00
|
|
|
const restructureLog = (line: string, prettifyLogMessage: boolean): string => {
|
2022-09-19 16:51:46 +08:00
|
|
|
if (prettifyLogMessage) {
|
|
|
|
|
try {
|
|
|
|
|
return JSON.stringify(JSON.parse(line), undefined, 2);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return line;
|
2023-07-11 20:50:53 +08:00
|
|
|
};
|
2023-05-23 20:36:05 +08:00
|
|
|
|
2023-07-11 20:50:53 +08:00
|
|
|
export const LogRowMessage = React.memo((props: Props) => {
|
|
|
|
|
const {
|
|
|
|
|
row,
|
|
|
|
|
wrapLogMessage,
|
|
|
|
|
prettifyLogMessage,
|
|
|
|
|
showContextToggle,
|
|
|
|
|
styles,
|
|
|
|
|
onOpenContext,
|
|
|
|
|
onPermalinkClick,
|
|
|
|
|
onUnpinLine,
|
|
|
|
|
onPinLine,
|
|
|
|
|
pinned,
|
|
|
|
|
} = props;
|
|
|
|
|
const { hasAnsi, raw } = row;
|
|
|
|
|
const restructuredEntry = useMemo(() => restructureLog(raw, prettifyLogMessage), [raw, prettifyLogMessage]);
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{
|
|
|
|
|
// When context is open, the position has to be NOT relative. // Setting the postion as inline-style to
|
|
|
|
|
// overwrite the more sepecific style definition from `styles.logsRowMessage`.
|
|
|
|
|
}
|
|
|
|
|
<td className={styles.logsRowMessage}>
|
|
|
|
|
<div className={wrapLogMessage ? styles.positionRelative : styles.horizontalScroll}>
|
|
|
|
|
<button className={`${styles.logLine} ${styles.positionRelative}`}>
|
|
|
|
|
<LogMessage hasAnsi={hasAnsi} entry={restructuredEntry} highlights={row.searchWords} styles={styles} />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
<td className={`log-row-menu-cell ${styles.logRowMenuCell}`}>
|
|
|
|
|
<LogRowMenuCell
|
|
|
|
|
logText={restructuredEntry}
|
|
|
|
|
row={row}
|
|
|
|
|
showContextToggle={showContextToggle}
|
|
|
|
|
onOpenContext={onOpenContext}
|
|
|
|
|
onPermalinkClick={onPermalinkClick}
|
|
|
|
|
onPinLine={onPinLine}
|
|
|
|
|
onUnpinLine={onUnpinLine}
|
|
|
|
|
pinned={pinned}
|
|
|
|
|
styles={styles}
|
|
|
|
|
/>
|
|
|
|
|
</td>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
});
|
2022-09-19 16:51:46 +08:00
|
|
|
|
2023-07-11 20:50:53 +08:00
|
|
|
LogRowMessage.displayName = 'LogRowMessage';
|