[Logs UI] Speed up stream rendering using memoization (#59163)
This aims to be a quick performance improvement by memoizing the LogEntryRow component.
This commit is contained in:
parent
5408f45b52
commit
1a548a1e42
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
// import { darken, transparentize } from 'polished';
|
||||
import React, { useState, useCallback, useMemo } from 'react';
|
||||
import React, { memo, useState, useCallback, useMemo } from 'react';
|
||||
|
||||
import { euiStyled } from '../../../../../observability/public';
|
||||
import {
|
||||
|
@ -41,155 +41,157 @@ interface LogEntryRowProps {
|
|||
wrap: boolean;
|
||||
}
|
||||
|
||||
export const LogEntryRow = ({
|
||||
boundingBoxRef,
|
||||
columnConfigurations,
|
||||
columnWidths,
|
||||
highlights,
|
||||
isActiveHighlight,
|
||||
isHighlighted,
|
||||
logEntry,
|
||||
openFlyoutWithItem,
|
||||
scale,
|
||||
wrap,
|
||||
}: LogEntryRowProps) => {
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const setItemIsHovered = useCallback(() => {
|
||||
setIsHovered(true);
|
||||
}, []);
|
||||
|
||||
const setItemIsNotHovered = useCallback(() => {
|
||||
setIsHovered(false);
|
||||
}, []);
|
||||
|
||||
const openFlyout = useCallback(() => openFlyoutWithItem(logEntry.gid), [
|
||||
export const LogEntryRow = memo(
|
||||
({
|
||||
boundingBoxRef,
|
||||
columnConfigurations,
|
||||
columnWidths,
|
||||
highlights,
|
||||
isActiveHighlight,
|
||||
isHighlighted,
|
||||
logEntry,
|
||||
openFlyoutWithItem,
|
||||
logEntry.gid,
|
||||
]);
|
||||
scale,
|
||||
wrap,
|
||||
}: LogEntryRowProps) => {
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const logEntryColumnsById = useMemo(
|
||||
() =>
|
||||
logEntry.columns.reduce<{
|
||||
[columnId: string]: LogEntry['columns'][0];
|
||||
}>(
|
||||
(columnsById, column) => ({
|
||||
...columnsById,
|
||||
[column.columnId]: column,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
[logEntry.columns]
|
||||
);
|
||||
const setItemIsHovered = useCallback(() => {
|
||||
setIsHovered(true);
|
||||
}, []);
|
||||
|
||||
const highlightsByColumnId = useMemo(
|
||||
() =>
|
||||
highlights.reduce<{
|
||||
[columnId: string]: LogEntryHighlightColumn[];
|
||||
}>(
|
||||
(columnsById, highlight) =>
|
||||
highlight.columns.reduce(
|
||||
(innerColumnsById, column) => ({
|
||||
...innerColumnsById,
|
||||
[column.columnId]: [...(innerColumnsById[column.columnId] || []), column],
|
||||
}),
|
||||
columnsById
|
||||
),
|
||||
{}
|
||||
),
|
||||
[highlights]
|
||||
);
|
||||
const setItemIsNotHovered = useCallback(() => {
|
||||
setIsHovered(false);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<LogEntryRowWrapper
|
||||
data-test-subj="streamEntry logTextStreamEntry"
|
||||
ref={
|
||||
/* Workaround for missing RefObject support in styled-components */
|
||||
boundingBoxRef as any
|
||||
}
|
||||
onMouseEnter={setItemIsHovered}
|
||||
onMouseLeave={setItemIsNotHovered}
|
||||
scale={scale}
|
||||
>
|
||||
{columnConfigurations.map(columnConfiguration => {
|
||||
if (isTimestampLogColumnConfiguration(columnConfiguration)) {
|
||||
const column = logEntryColumnsById[columnConfiguration.timestampColumn.id];
|
||||
const columnWidth = columnWidths[columnConfiguration.timestampColumn.id];
|
||||
const openFlyout = useCallback(() => openFlyoutWithItem(logEntry.gid), [
|
||||
openFlyoutWithItem,
|
||||
logEntry.gid,
|
||||
]);
|
||||
|
||||
return (
|
||||
<LogEntryColumn
|
||||
data-test-subj="logColumn timestampLogColumn"
|
||||
key={columnConfiguration.timestampColumn.id}
|
||||
{...columnWidth}
|
||||
>
|
||||
{isTimestampColumn(column) ? (
|
||||
<LogEntryTimestampColumn
|
||||
isHighlighted={isHighlighted}
|
||||
isHovered={isHovered}
|
||||
time={column.timestamp}
|
||||
/>
|
||||
) : null}
|
||||
</LogEntryColumn>
|
||||
);
|
||||
} else if (isMessageLogColumnConfiguration(columnConfiguration)) {
|
||||
const column = logEntryColumnsById[columnConfiguration.messageColumn.id];
|
||||
const columnWidth = columnWidths[columnConfiguration.messageColumn.id];
|
||||
const logEntryColumnsById = useMemo(
|
||||
() =>
|
||||
logEntry.columns.reduce<{
|
||||
[columnId: string]: LogEntry['columns'][0];
|
||||
}>(
|
||||
(columnsById, column) => ({
|
||||
...columnsById,
|
||||
[column.columnId]: column,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
[logEntry.columns]
|
||||
);
|
||||
|
||||
return (
|
||||
<LogEntryColumn
|
||||
data-test-subj="logColumn messageLogColumn"
|
||||
key={columnConfiguration.messageColumn.id}
|
||||
{...columnWidth}
|
||||
>
|
||||
{column ? (
|
||||
<LogEntryMessageColumn
|
||||
columnValue={column}
|
||||
highlights={highlightsByColumnId[column.columnId] || []}
|
||||
isHighlighted={isHighlighted}
|
||||
isActiveHighlight={isActiveHighlight}
|
||||
isHovered={isHovered}
|
||||
isWrapped={wrap}
|
||||
/>
|
||||
) : null}
|
||||
</LogEntryColumn>
|
||||
);
|
||||
} else if (isFieldLogColumnConfiguration(columnConfiguration)) {
|
||||
const column = logEntryColumnsById[columnConfiguration.fieldColumn.id];
|
||||
const columnWidth = columnWidths[columnConfiguration.fieldColumn.id];
|
||||
const highlightsByColumnId = useMemo(
|
||||
() =>
|
||||
highlights.reduce<{
|
||||
[columnId: string]: LogEntryHighlightColumn[];
|
||||
}>(
|
||||
(columnsById, highlight) =>
|
||||
highlight.columns.reduce(
|
||||
(innerColumnsById, column) => ({
|
||||
...innerColumnsById,
|
||||
[column.columnId]: [...(innerColumnsById[column.columnId] || []), column],
|
||||
}),
|
||||
columnsById
|
||||
),
|
||||
{}
|
||||
),
|
||||
[highlights]
|
||||
);
|
||||
|
||||
return (
|
||||
<LogEntryColumn
|
||||
data-test-subj={`logColumn fieldLogColumn fieldLogColumn:${columnConfiguration.fieldColumn.field}`}
|
||||
key={columnConfiguration.fieldColumn.id}
|
||||
{...columnWidth}
|
||||
>
|
||||
{column ? (
|
||||
<LogEntryFieldColumn
|
||||
columnValue={column}
|
||||
highlights={highlightsByColumnId[column.columnId] || []}
|
||||
isActiveHighlight={isActiveHighlight}
|
||||
isHighlighted={isHighlighted}
|
||||
isHovered={isHovered}
|
||||
isWrapped={wrap}
|
||||
/>
|
||||
) : null}
|
||||
</LogEntryColumn>
|
||||
);
|
||||
return (
|
||||
<LogEntryRowWrapper
|
||||
data-test-subj="streamEntry logTextStreamEntry"
|
||||
ref={
|
||||
/* Workaround for missing RefObject support in styled-components */
|
||||
boundingBoxRef as any
|
||||
}
|
||||
})}
|
||||
<LogEntryColumn
|
||||
key="logColumn iconLogColumn iconLogColumn:details"
|
||||
{...columnWidths[iconColumnId]}
|
||||
onMouseEnter={setItemIsHovered}
|
||||
onMouseLeave={setItemIsNotHovered}
|
||||
scale={scale}
|
||||
>
|
||||
<LogEntryDetailsIconColumn
|
||||
isHighlighted={isHighlighted}
|
||||
isHovered={isHovered}
|
||||
openFlyout={openFlyout}
|
||||
/>
|
||||
</LogEntryColumn>
|
||||
</LogEntryRowWrapper>
|
||||
);
|
||||
};
|
||||
{columnConfigurations.map(columnConfiguration => {
|
||||
if (isTimestampLogColumnConfiguration(columnConfiguration)) {
|
||||
const column = logEntryColumnsById[columnConfiguration.timestampColumn.id];
|
||||
const columnWidth = columnWidths[columnConfiguration.timestampColumn.id];
|
||||
|
||||
return (
|
||||
<LogEntryColumn
|
||||
data-test-subj="logColumn timestampLogColumn"
|
||||
key={columnConfiguration.timestampColumn.id}
|
||||
{...columnWidth}
|
||||
>
|
||||
{isTimestampColumn(column) ? (
|
||||
<LogEntryTimestampColumn
|
||||
isHighlighted={isHighlighted}
|
||||
isHovered={isHovered}
|
||||
time={column.timestamp}
|
||||
/>
|
||||
) : null}
|
||||
</LogEntryColumn>
|
||||
);
|
||||
} else if (isMessageLogColumnConfiguration(columnConfiguration)) {
|
||||
const column = logEntryColumnsById[columnConfiguration.messageColumn.id];
|
||||
const columnWidth = columnWidths[columnConfiguration.messageColumn.id];
|
||||
|
||||
return (
|
||||
<LogEntryColumn
|
||||
data-test-subj="logColumn messageLogColumn"
|
||||
key={columnConfiguration.messageColumn.id}
|
||||
{...columnWidth}
|
||||
>
|
||||
{column ? (
|
||||
<LogEntryMessageColumn
|
||||
columnValue={column}
|
||||
highlights={highlightsByColumnId[column.columnId] || []}
|
||||
isHighlighted={isHighlighted}
|
||||
isActiveHighlight={isActiveHighlight}
|
||||
isHovered={isHovered}
|
||||
isWrapped={wrap}
|
||||
/>
|
||||
) : null}
|
||||
</LogEntryColumn>
|
||||
);
|
||||
} else if (isFieldLogColumnConfiguration(columnConfiguration)) {
|
||||
const column = logEntryColumnsById[columnConfiguration.fieldColumn.id];
|
||||
const columnWidth = columnWidths[columnConfiguration.fieldColumn.id];
|
||||
|
||||
return (
|
||||
<LogEntryColumn
|
||||
data-test-subj={`logColumn fieldLogColumn fieldLogColumn:${columnConfiguration.fieldColumn.field}`}
|
||||
key={columnConfiguration.fieldColumn.id}
|
||||
{...columnWidth}
|
||||
>
|
||||
{column ? (
|
||||
<LogEntryFieldColumn
|
||||
columnValue={column}
|
||||
highlights={highlightsByColumnId[column.columnId] || []}
|
||||
isActiveHighlight={isActiveHighlight}
|
||||
isHighlighted={isHighlighted}
|
||||
isHovered={isHovered}
|
||||
isWrapped={wrap}
|
||||
/>
|
||||
) : null}
|
||||
</LogEntryColumn>
|
||||
);
|
||||
}
|
||||
})}
|
||||
<LogEntryColumn
|
||||
key="logColumn iconLogColumn iconLogColumn:details"
|
||||
{...columnWidths[iconColumnId]}
|
||||
>
|
||||
<LogEntryDetailsIconColumn
|
||||
isHighlighted={isHighlighted}
|
||||
isHovered={isHovered}
|
||||
openFlyout={openFlyout}
|
||||
/>
|
||||
</LogEntryColumn>
|
||||
</LogEntryRowWrapper>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
interface LogEntryRowWrapperProps {
|
||||
scale: TextScale;
|
||||
|
|
Loading…
Reference in a new issue