mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Logs Panel: Table UI - Time range changes not reflecting in table (#78500)
* add hook to update selected dataframe when time range changes
This commit is contained in:
parent
d0b1ceb7d4
commit
392a4342a8
@ -1,4 +1,4 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { capitalize } from 'lodash';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import React, { createRef, PureComponent } from 'react';
|
||||
@ -59,7 +59,7 @@ import { changePanelState } from '../state/explorePane';
|
||||
|
||||
import { LogsMetaRow } from './LogsMetaRow';
|
||||
import LogsNavigation from './LogsNavigation';
|
||||
import { LogsTableWrap } from './LogsTableWrap';
|
||||
import { getLogsTableHeight, LogsTableWrap } from './LogsTableWrap';
|
||||
import { LogsVolumePanelList } from './LogsVolumePanelList';
|
||||
import { SETTINGS_KEYS } from './utils/logs';
|
||||
|
||||
@ -543,7 +543,8 @@ class UnthemedLogs extends PureComponent<Props, State> {
|
||||
contextRow,
|
||||
} = this.state;
|
||||
|
||||
const styles = getStyles(theme, wrapLogMessage);
|
||||
const tableHeight = getLogsTableHeight();
|
||||
const styles = getStyles(theme, wrapLogMessage, tableHeight);
|
||||
const hasData = logRows && logRows.length > 0;
|
||||
const hasUnescapedContent = this.checkUnescapedContent(logRows);
|
||||
|
||||
@ -727,7 +728,9 @@ class UnthemedLogs extends PureComponent<Props, State> {
|
||||
clearDetectedFields={this.clearDetectedFields}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.logsSection}>
|
||||
<div
|
||||
className={cx(styles.logsSection, this.state.visualisationType === 'table' ? styles.logsTable : undefined)}
|
||||
>
|
||||
{this.state.visualisationType === 'table' && hasData && (
|
||||
<div className={styles.logRows} data-testid="logRowsTable">
|
||||
{/* Width should be full width minus logs navigation and padding */}
|
||||
@ -821,7 +824,7 @@ class UnthemedLogs extends PureComponent<Props, State> {
|
||||
|
||||
export const Logs = withTheme2(UnthemedLogs);
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean) => {
|
||||
const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean, tableHeight: number) => {
|
||||
return {
|
||||
noData: css`
|
||||
> * {
|
||||
@ -858,6 +861,9 @@ const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean) => {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
`,
|
||||
logsTable: css({
|
||||
maxHeight: `${tableHeight}px`,
|
||||
}),
|
||||
logRows: css`
|
||||
overflow-x: ${scrollableLogsContainer ? 'scroll;' : `${wrapLogMessage ? 'unset' : 'scroll'};`}
|
||||
overflow-y: visible;
|
||||
|
@ -139,6 +139,27 @@ describe('LogsTableWrap', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should update selected dataframe when dataFrames update', async () => {
|
||||
const initialProps = { logsFrames: [getMockLokiFrameDataPlane(undefined, 3)] };
|
||||
const render = setup(initialProps);
|
||||
await waitFor(() => {
|
||||
const rows = render.getAllByRole('row');
|
||||
expect(rows.length).toBe(4);
|
||||
});
|
||||
|
||||
render.rerender(
|
||||
getComponent({
|
||||
...initialProps,
|
||||
logsFrames: [getMockLokiFrameDataPlane(undefined, 4)],
|
||||
})
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
const rows = render.getAllByRole('row');
|
||||
expect(rows.length).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
it('search input should search matching columns (dataplane)', async () => {
|
||||
config.featureToggles.lokiLogsDataplane = true;
|
||||
|
||||
|
@ -52,14 +52,13 @@ export function LogsTableWrap(props: Props) {
|
||||
// Filtered copy of columnsWithMeta that only includes matching results
|
||||
const [filteredColumnsWithMeta, setFilteredColumnsWithMeta] = useState<fieldNameMetaStore | undefined>(undefined);
|
||||
|
||||
const height = getTableHeight();
|
||||
const height = getLogsTableHeight();
|
||||
const panelStateRefId = props?.panelState?.refId;
|
||||
|
||||
// The current dataFrame containing the refId of the current query
|
||||
const [currentDataFrame, setCurrentDataFrame] = useState<DataFrame>(
|
||||
logsFrames.find((f) => f.refId === props?.panelState?.refId) ?? logsFrames[0]
|
||||
logsFrames.find((f) => f.refId === panelStateRefId) ?? logsFrames[0]
|
||||
);
|
||||
// The refId of the current frame being displayed
|
||||
const currentFrameRefId = currentDataFrame.refId;
|
||||
|
||||
const getColumnsFromProps = useCallback(
|
||||
(fieldNames: fieldNameMetaStore) => {
|
||||
@ -76,6 +75,16 @@ export function LogsTableWrap(props: Props) {
|
||||
[props.panelState?.columns]
|
||||
);
|
||||
|
||||
/**
|
||||
* When logs frame updates (e.g. query|range changes), we need to set the selected frame to state
|
||||
*/
|
||||
useEffect(() => {
|
||||
const newFrame = logsFrames.find((f) => f.refId === panelStateRefId) ?? logsFrames[0];
|
||||
if (newFrame) {
|
||||
setCurrentDataFrame(newFrame);
|
||||
}
|
||||
}, [logsFrames, panelStateRefId]);
|
||||
|
||||
/**
|
||||
* Keeps the filteredColumnsWithMeta state in sync with the columnsWithMeta state,
|
||||
* which can be updated by explore browser history state changes
|
||||
@ -336,7 +345,7 @@ export function LogsTableWrap(props: Props) {
|
||||
<Select
|
||||
inputId={'explore_logs_table_frame_selector'}
|
||||
aria-label={'Select query by name'}
|
||||
value={currentFrameRefId}
|
||||
value={currentDataFrame.refId}
|
||||
options={logsFrames.map((frame) => {
|
||||
return {
|
||||
label: frame.refId,
|
||||
@ -394,7 +403,7 @@ function getStyles(theme: GrafanaTheme2, height: number, width: number) {
|
||||
};
|
||||
}
|
||||
|
||||
const getTableHeight = () => {
|
||||
export const getLogsTableHeight = () => {
|
||||
// Instead of making the height of the table based on the content (like in the table panel itself), let's try to use the vertical space that is available.
|
||||
// Since this table is in explore, we can expect the user to be running multiple queries that return disparate numbers of rows and labels in the same session
|
||||
// Also changing the height of the table between queries can be and cause content to jump, so we'll set a minimum height of 500px, and a max based on the innerHeight
|
||||
|
@ -52,7 +52,10 @@ export const getMockLokiFrame = (override?: Partial<DataFrame>) => {
|
||||
};
|
||||
return { ...testDataFrame, ...override };
|
||||
};
|
||||
export const getMockLokiFrameDataPlane = (override?: Partial<DataFrame>): DataFrame => {
|
||||
export const getMockLokiFrameDataPlane = (override?: Partial<DataFrame>, howManyValues = 3): DataFrame => {
|
||||
if (howManyValues > 6) {
|
||||
throw new Error('only 6 or fewer values are supported');
|
||||
}
|
||||
const testDataFrame: DataFrame = {
|
||||
meta: {
|
||||
type: DataFrameType.LogLines,
|
||||
@ -72,25 +75,53 @@ export const getMockLokiFrameDataPlane = (override?: Partial<DataFrame>): DataFr
|
||||
config: {},
|
||||
name: 'timestamp',
|
||||
type: FieldType.time,
|
||||
values: ['2019-01-01 10:00:00', '2019-01-01 11:00:00', '2019-01-01 12:00:00'],
|
||||
values: [
|
||||
'2019-01-01 10:00:00',
|
||||
'2019-01-01 11:00:00',
|
||||
'2019-01-01 12:00:00',
|
||||
'2019-01-01 13:00:00',
|
||||
'2019-01-01 14:00:00',
|
||||
'2019-01-01 15:00:00',
|
||||
].slice(0, howManyValues),
|
||||
},
|
||||
{
|
||||
config: {},
|
||||
name: 'body',
|
||||
type: FieldType.string,
|
||||
values: ['log message 1', 'log message 2', 'log message 3'],
|
||||
values: [
|
||||
'log message 1',
|
||||
'log message 2',
|
||||
'log message 3',
|
||||
'log message 4',
|
||||
'log message 5',
|
||||
'log message 6',
|
||||
].slice(0, howManyValues),
|
||||
},
|
||||
{
|
||||
config: {},
|
||||
name: 'tsNs',
|
||||
type: FieldType.string,
|
||||
values: ['1697561006608165746', '1697560998869868000', '1697561010006578474'],
|
||||
values: [
|
||||
'1697561006608165746',
|
||||
'1697560998869868000',
|
||||
'1697561010006578474',
|
||||
'1697561010006578475',
|
||||
'1697561010006578476',
|
||||
'1697561010006578477',
|
||||
].slice(0, howManyValues),
|
||||
},
|
||||
{
|
||||
config: {},
|
||||
name: 'id',
|
||||
type: FieldType.string,
|
||||
values: ['1697561006608165746_b4cc4b72', '1697560998869868000_eeb96c0f', '1697561010006578474_ad5e2e5a'],
|
||||
values: [
|
||||
'1697561006608165746_b4cc4b72',
|
||||
'1697560998869868000_eeb96c0f',
|
||||
'1697561010006578474_ad5e2e5a',
|
||||
'1697561010006578474_ad5e2e5b',
|
||||
'1697561010006578474_ad5e2e5c',
|
||||
'1697561010006578474_ad5e2e5d',
|
||||
].slice(0, howManyValues),
|
||||
},
|
||||
{
|
||||
config: {
|
||||
@ -103,10 +134,10 @@ export const getMockLokiFrameDataPlane = (override?: Partial<DataFrame>): DataFr
|
||||
},
|
||||
name: 'traceID',
|
||||
type: FieldType.string,
|
||||
values: ['trace1', 'trace2', 'trace3'],
|
||||
values: ['trace1', 'trace2', 'trace3', 'trace4', 'trace5', 'trace6'].slice(0, howManyValues),
|
||||
},
|
||||
],
|
||||
length: 3,
|
||||
length: howManyValues,
|
||||
};
|
||||
return { ...testDataFrame, ...override };
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user