Logs: Fix nanosecond partition in log context (#71346)

* add ts partition

* fix setting wrong loadingstate

* improve setContext

* update context and test
This commit is contained in:
Sven Grossmann
2023-07-11 16:20:41 +02:00
committed by GitHub
parent 7fdf855932
commit 9ddba37dbc
2 changed files with 41 additions and 25 deletions
@@ -189,12 +189,12 @@ describe('LogRowContextModal', () => {
}); });
it('should render 3 lines containing `foo123` with the same ms timestamp', async () => { it('should render 3 lines containing `foo123` with the same ms timestamp', async () => {
const dfBefore = createDataFrame({ const dfBeforeNs = createDataFrame({
fields: [ fields: [
{ {
name: 'time', name: 'time',
type: FieldType.time, type: FieldType.time,
values: [1689052469935, 1689052469935], values: [1, 1],
}, },
{ {
name: 'message', name: 'message',
@@ -204,16 +204,16 @@ describe('LogRowContextModal', () => {
{ {
name: 'tsNs', name: 'tsNs',
type: FieldType.string, type: FieldType.string,
values: ['1689052469935083353', '1689052469935083354'], values: ['1', '2'],
}, },
], ],
}); });
const dfNow = createDataFrame({ const dfNowNs = createDataFrame({
fields: [ fields: [
{ {
name: 'time', name: 'time',
type: FieldType.time, type: FieldType.time,
values: [1689052469935], values: [1],
}, },
{ {
name: 'message', name: 'message',
@@ -223,16 +223,16 @@ describe('LogRowContextModal', () => {
{ {
name: 'tsNs', name: 'tsNs',
type: FieldType.string, type: FieldType.string,
values: ['1689052469935083354'], values: ['2'],
}, },
], ],
}); });
const dfAfter = createDataFrame({ const dfAfterNs = createDataFrame({
fields: [ fields: [
{ {
name: 'time', name: 'time',
type: FieldType.time, type: FieldType.time,
values: [1689052469935, 1689052469935], values: [1, 1],
}, },
{ {
name: 'message', name: 'message',
@@ -242,36 +242,37 @@ describe('LogRowContextModal', () => {
{ {
name: 'tsNs', name: 'tsNs',
type: FieldType.string, type: FieldType.string,
values: ['1689052469935083354', '1689052469935083355'], values: ['2', '3'],
}, },
], ],
}); });
let uniqueRefIdCounter = 1; let uniqueRefIdCounter = 1;
const logs = dataFrameToLogsModel([dfNow]); const logs = dataFrameToLogsModel([dfNowNs]);
const row = logs.rows[0]; const row = logs.rows[0];
const getRowContext = jest.fn().mockImplementation(async (_, options) => { const getRowContext = jest.fn().mockImplementation(async (_, options) => {
uniqueRefIdCounter += 1; uniqueRefIdCounter += 1;
const refId = `refid_${uniqueRefIdCounter}`; const refId = `refid_${uniqueRefIdCounter}`;
if (options.direction === LogRowContextQueryDirection.Forward) { if (uniqueRefIdCounter === 2) {
return { return {
data: [ data: [
{ {
refId, refId,
...dfBefore, ...dfBeforeNs,
}, },
], ],
}; };
} else { } else if (uniqueRefIdCounter === 3) {
return { return {
data: [ data: [
{ {
refId, refId,
...dfAfter, ...dfAfterNs,
}, },
], ],
}; };
} }
return { data: [] };
}); });
render( render(
@@ -284,8 +285,11 @@ describe('LogRowContextModal', () => {
logsSortOrder={LogsSortOrder.Descending} logsSortOrder={LogsSortOrder.Descending}
/> />
); );
// there need to be 2 lines with that message. 1 in before, 1 in now, 1 in after
await waitFor(() => expect(screen.getAllByText('foo123').length).toBe(3)); // there need to be 3 lines with that message. 1 in before, 1 in now, 1 in after
await waitFor(() => {
expect(screen.getAllByText('foo123').length).toBe(3);
});
}); });
it('should show a split view button', async () => { it('should show a split view button', async () => {
@@ -1,4 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { partition } from 'lodash';
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { useAsync } from 'react-use'; import { useAsync } from 'react-use';
@@ -253,11 +254,7 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
generationRef.current += 1; // results from currently running loadMore calls will be ignored generationRef.current += 1; // results from currently running loadMore calls will be ignored
}; };
const loadMore = async (place: Place): Promise<LogRowModel[]> => { const loadMore = async (place: Place, allRows: LogRowModel[]): Promise<LogRowModel[]> => {
const { below, above } = context;
// we consider all the currently existing rows, even the original row,
// this way this array of rows will never be empty
const allRows = [...above.rows, row, ...below.rows];
const refRow = allRows.at(place === 'above' ? 0 : -1); const refRow = allRows.at(place === 'above' ? 0 : -1);
if (refRow == null) { if (refRow == null) {
throw new Error('should never happen. the array always contains at least 1 item (the middle row)'); throw new Error('should never happen. the array always contains at least 1 item (the middle row)');
@@ -305,6 +302,7 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
}; };
const maybeLoadMore = async (place: Place) => { const maybeLoadMore = async (place: Place) => {
const { below, above } = context;
const section = context[place]; const section = context[place];
if (section.loadingState === LoadingState.Loading) { if (section.loadingState === LoadingState.Loading) {
return; return;
@@ -317,11 +315,25 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
const currentGen = generationRef.current; const currentGen = generationRef.current;
try { try {
const newRows = await loadMore(place); // we consider all the currently existing rows, even the original row,
// this way this array of rows will never be empty
const allRows = [...above.rows, row, ...below.rows];
const newRows = await loadMore(place, allRows);
const [older, newer] = partition(newRows, (newRow) => newRow.timeEpochNs > row.timeEpochNs);
const newAbove = logsSortOrder === LogsSortOrder.Ascending ? newer : older;
const newBelow = logsSortOrder === LogsSortOrder.Ascending ? older : newer;
if (currentGen === generationRef.current) { if (currentGen === generationRef.current) {
setSection(place, (section) => ({ setContext((c) => ({
rows: place === 'above' ? [...newRows, ...section.rows] : [...section.rows, ...newRows], above: {
loadingState: newRows.length === 0 ? LoadingState.Done : LoadingState.NotStarted, rows: sortLogRows([...newAbove, ...c.above.rows], logsSortOrder),
loadingState: newRows.length === 0 ? LoadingState.Done : LoadingState.NotStarted,
},
below: {
rows: sortLogRows([...c.below.rows, ...newBelow], logsSortOrder),
loadingState: newRows.length === 0 ? LoadingState.Done : LoadingState.NotStarted,
},
})); }));
} }
} catch { } catch {