grafana/public/app/features/logs/components/LogRowMessage.tsx

119 lines
3.6 KiB
TypeScript
Raw Normal View History

import React, { useMemo } from 'react';
import Highlighter from 'react-highlight-words';
import { CoreApp, findHighlightChunksInText, LogRowModel } from '@grafana/data';
import { LogMessageAnsi } from './LogMessageAnsi';
import { LogRowMenuCell } from './LogRowMenuCell';
import { LogRowStyles } from './getLogRowStyles';
export const MAX_CHARACTERS = 100000;
interface Props {
row: LogRowModel;
wrapLogMessage: boolean;
prettifyLogMessage: boolean;
app?: CoreApp;
showContextToggle?: (row?: LogRowModel) => boolean;
Logs: Redesign and improve LogContext (#65939) * Logs: Add new LogRowContext types to grafana/data * use right type for `RowContextOptions` * add missing renames * add show context modal * no need to call * removed unused css * sort properties * rename * use correct * use * add tests for * wip * remove add/minus buttons * add tests * disable processing of context results in Loki * moved into table to align properly * remove imports * add highlighting of opened logline * improve scrolling behavior * correct style for the table * use correct query direction * fix text * use LoadingBar * use overflow auto * rename `onToggleContext` to `onOpenContext` * add missing import * mock scrollIntoView * update unused props * remove unused import * no need to process context dataframes * only show `LogRowContextModal` if `getRowContext` is defined * remove unused param * use `userEvent` rather `fireEvent` * change to `TimeZone` * directly use style classes * revert change to public_dashboard_service_mock.go * improved styling * add missing await in test * fix lint * fix lint * remove LogRow scrolling when context is opened * remove references to `scrollElement` * Update public/app/features/logs/components/log-context/LogRowContextModal.tsx Co-authored-by: Matias Chomicki <matyax@gmail.com> * fix lint * add comment explaining `onCloseContext` * add comment about debounced onClose * add comments and remove `showRowMenu` * scroll twice to correctly center the element * revert double scrolling * remove unnecessary `processDataFrame` * trigger drone --------- Co-authored-by: Matias Chomicki <matyax@gmail.com>
2023-04-14 23:05:43 +08:00
onOpenContext: (row: LogRowModel) => void;
onPermalinkClick?: (row: LogRowModel) => Promise<void>;
onPinLine?: (row: LogRowModel) => void;
onUnpinLine?: (row: LogRowModel) => void;
pinned?: boolean;
styles: LogRowStyles;
mouseIsOver: boolean;
onBlur: () => void;
}
interface LogMessageProps {
hasAnsi: boolean;
entry: string;
highlights: string[] | undefined;
styles: LogRowStyles;
}
const LogMessage = ({ hasAnsi, entry, highlights, styles }: LogMessageProps) => {
const needsHighlighter =
highlights && highlights.length > 0 && highlights[0] && highlights[0].length > 0 && entry.length < MAX_CHARACTERS;
const searchWords = highlights ?? [];
if (hasAnsi) {
const highlight = needsHighlighter ? { searchWords, highlightClassName: styles.logsRowMatchHighLight } : undefined;
return <LogMessageAnsi value={entry} highlight={highlight} />;
} else if (needsHighlighter) {
return (
<Highlighter
textToHighlight={entry}
searchWords={searchWords}
findChunks={findHighlightChunksInText}
highlightClassName={styles.logsRowMatchHighLight}
/>
);
}
return <>{entry}</>;
};
const restructureLog = (line: string, prettifyLogMessage: boolean): string => {
if (prettifyLogMessage) {
try {
return JSON.stringify(JSON.parse(line), undefined, 2);
} catch (error) {
return line;
}
}
return line;
};
export const LogRowMessage = React.memo((props: Props) => {
const {
row,
wrapLogMessage,
prettifyLogMessage,
showContextToggle,
styles,
onOpenContext,
onPermalinkClick,
onUnpinLine,
onPinLine,
pinned,
mouseIsOver,
onBlur,
} = props;
const { hasAnsi, raw } = row;
const restructuredEntry = useMemo(() => restructureLog(raw, prettifyLogMessage), [raw, prettifyLogMessage]);
const shouldShowMenu = useMemo(() => mouseIsOver || pinned || true, [mouseIsOver, pinned]);
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}`}>
{shouldShowMenu && (
<LogRowMenuCell
logText={restructuredEntry}
row={row}
showContextToggle={showContextToggle}
onOpenContext={onOpenContext}
onPermalinkClick={onPermalinkClick}
onPinLine={onPinLine}
onUnpinLine={onUnpinLine}
pinned={pinned}
styles={styles}
mouseIsOver={mouseIsOver}
onBlur={onBlur}
/>
)}
</td>
</>
);
});
LogRowMessage.displayName = 'LogRowMessage';