chore: render transformed default displayed fields
This commit is contained in:
Generated
+2
-2
@@ -43,14 +43,14 @@ export interface Options {
|
||||
onClickFilterLabel?: unknown;
|
||||
onClickFilterOutLabel?: unknown;
|
||||
setDisplayedFields?: unknown;
|
||||
showControls?: boolean;
|
||||
/**
|
||||
* showLabels: bool
|
||||
* showCommonLabels: bool
|
||||
* showFieldSelector?: bool
|
||||
* showTime: bool
|
||||
* showLogContextToggle: bool
|
||||
*/
|
||||
showLogContextToggle: boolean;
|
||||
showControls?: boolean;
|
||||
}
|
||||
|
||||
export const defaultOptions: Partial<Options> = {
|
||||
|
||||
@@ -367,8 +367,7 @@ const isFieldFilterable = (field: Field, bodyName: string, timeName: string) =>
|
||||
return true;
|
||||
};
|
||||
|
||||
// TODO: explore if `logsFrame.ts` can help us with getting the right fields
|
||||
// TODO Why is typeInfo not defined on the Field interface?
|
||||
// @todo move to logsFrame
|
||||
export function getLogsExtractFields(dataFrame: DataFrame) {
|
||||
return dataFrame.fields
|
||||
.filter((field: Field & { typeInfo?: { frame: string } }) => {
|
||||
|
||||
@@ -1,4 +1,134 @@
|
||||
export const LogsTable = () => {
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
return <div>Hello plugin</div>;
|
||||
import { useEffect, useState } from 'react';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
|
||||
import { DataFrame, PanelProps, transformDataFrame } from '@grafana/data';
|
||||
|
||||
import { getLogsExtractFields } from '../../../features/explore/Logs/LogsTable';
|
||||
import { LogsFrame, parseLogsFrame } from '../../../features/logs/logsFrame';
|
||||
import { TablePanel } from '../table/TablePanel';
|
||||
import type { Options as TableOptions } from '../table/panelcfg.gen';
|
||||
|
||||
import type { Options } from './panelcfg.gen';
|
||||
|
||||
interface LogsTablePanelProps extends PanelProps<Options> {
|
||||
frameIndex?: number;
|
||||
showHeader?: boolean;
|
||||
}
|
||||
|
||||
export const LogsTable = ({
|
||||
data,
|
||||
width,
|
||||
height,
|
||||
timeRange,
|
||||
fieldConfig,
|
||||
options,
|
||||
eventBus,
|
||||
frameIndex = 0,
|
||||
showHeader = true,
|
||||
onOptionsChange,
|
||||
onFieldConfigChange,
|
||||
replaceVariables,
|
||||
onChangeTimeRange,
|
||||
title,
|
||||
transparent,
|
||||
timeZone,
|
||||
id,
|
||||
renderCounter,
|
||||
}: LogsTablePanelProps) => {
|
||||
const logsFrame: LogsFrame | null = parseLogsFrame(data.series[frameIndex]);
|
||||
if (!logsFrame?.timeField.name || !logsFrame?.bodyField.name) {
|
||||
throw new Error(`Invalid logsFrame frame name: ${frameIndex}`);
|
||||
}
|
||||
|
||||
const [extractedFrame, setExtractedFrame] = useState<DataFrame | null>(null);
|
||||
const [organizedFrame, setOrganizedFrame] = useState<DataFrame | null>(null);
|
||||
|
||||
const onTableOptionsChange = (options: TableOptions) => {
|
||||
onOptionsChange({});
|
||||
};
|
||||
|
||||
const unTransformedDataFrame = data.series[frameIndex];
|
||||
|
||||
/**
|
||||
* Extract fields transform
|
||||
*/
|
||||
useEffect(() => {
|
||||
const extractFields = async () => {
|
||||
return await lastValueFrom(
|
||||
transformDataFrame(getLogsExtractFields(unTransformedDataFrame), [unTransformedDataFrame])
|
||||
);
|
||||
};
|
||||
|
||||
extractFields().then((frame) => {
|
||||
setExtractedFrame(frame[0]);
|
||||
});
|
||||
}, [unTransformedDataFrame]);
|
||||
|
||||
/**
|
||||
* Organize fields transform
|
||||
*/
|
||||
useEffect(() => {
|
||||
const organizeFields = async (displayedFields: string[]) => {
|
||||
if (!extractedFrame) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
let indexByName: Record<string, number> = {};
|
||||
let includeByName: Record<string, boolean> = {};
|
||||
if (displayedFields) {
|
||||
for (const [idx, field] of displayedFields.entries()) {
|
||||
indexByName[field] = idx;
|
||||
includeByName[field] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return await lastValueFrom(
|
||||
transformDataFrame(
|
||||
[
|
||||
{
|
||||
id: 'organize',
|
||||
options: {
|
||||
indexByName,
|
||||
includeByName,
|
||||
},
|
||||
},
|
||||
],
|
||||
[extractedFrame]
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
organizeFields(options.displayedFields ?? [logsFrame.timeField.name, logsFrame.bodyField.name]).then((frame) => {
|
||||
if (frame) {
|
||||
setOrganizedFrame(frame[0]);
|
||||
}
|
||||
});
|
||||
}, [extractedFrame, options.displayedFields, logsFrame.timeField.name, logsFrame.bodyField.name]);
|
||||
|
||||
if (extractedFrame === null || organizedFrame === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('render::LogsTable', { extractedFrame });
|
||||
|
||||
return (
|
||||
<TablePanel
|
||||
data={{ ...data, series: [organizedFrame] }}
|
||||
width={width}
|
||||
height={height}
|
||||
id={id}
|
||||
timeRange={timeRange}
|
||||
timeZone={timeZone}
|
||||
options={{ ...options, frameIndex: 0, showHeader }}
|
||||
transparent={transparent}
|
||||
fieldConfig={fieldConfig}
|
||||
renderCounter={renderCounter}
|
||||
title={title}
|
||||
eventBus={eventBus}
|
||||
onOptionsChange={onTableOptionsChange}
|
||||
onFieldConfigChange={onFieldConfigChange}
|
||||
replaceVariables={replaceVariables}
|
||||
onChangeTimeRange={onChangeTimeRange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,70 +1,54 @@
|
||||
import { PanelPlugin, LogsSortOrder, LogsDedupStrategy, LogsDedupDescription } from '@grafana/data';
|
||||
import { PanelPlugin } from '@grafana/data';
|
||||
|
||||
import { LogsTable } from './LogsTable';
|
||||
import { Options } from './panelcfg.gen';
|
||||
|
||||
export const plugin = new PanelPlugin<Options>(LogsTable).setPanelOptions((builder) => {
|
||||
builder
|
||||
.addBooleanSwitch({
|
||||
path: 'showTime',
|
||||
name: 'Time',
|
||||
description: '',
|
||||
defaultValue: false,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'wrapLogMessage',
|
||||
name: 'Wrap lines',
|
||||
description: '',
|
||||
defaultValue: false,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'enableLogDetails',
|
||||
name: 'Enable log details',
|
||||
description: '',
|
||||
defaultValue: true,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'enableInfiniteScrolling',
|
||||
name: 'Enable infinite scrolling',
|
||||
description: 'Experimental. Request more results by scrolling to the bottom of the logs list.',
|
||||
defaultValue: false,
|
||||
})
|
||||
.addRadio({
|
||||
path: 'dedupStrategy',
|
||||
name: 'Deduplication',
|
||||
description: '',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
|
||||
{
|
||||
value: LogsDedupStrategy.exact,
|
||||
label: 'Exact',
|
||||
description: LogsDedupDescription[LogsDedupStrategy.exact],
|
||||
},
|
||||
{
|
||||
value: LogsDedupStrategy.numbers,
|
||||
label: 'Numbers',
|
||||
description: LogsDedupDescription[LogsDedupStrategy.numbers],
|
||||
},
|
||||
{
|
||||
value: LogsDedupStrategy.signature,
|
||||
label: 'Signature',
|
||||
description: LogsDedupDescription[LogsDedupStrategy.signature],
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultValue: LogsDedupStrategy.none,
|
||||
})
|
||||
.addRadio({
|
||||
path: 'sortOrder',
|
||||
name: 'Order',
|
||||
description: '',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: LogsSortOrder.Descending, label: 'Newest first' },
|
||||
{ value: LogsSortOrder.Ascending, label: 'Oldest first' },
|
||||
],
|
||||
},
|
||||
defaultValue: LogsSortOrder.Descending,
|
||||
});
|
||||
builder.addBooleanSwitch({
|
||||
path: 'wrapLogMessage',
|
||||
name: 'Wrap lines',
|
||||
description: '',
|
||||
defaultValue: false,
|
||||
});
|
||||
|
||||
// @todo add table options?
|
||||
//
|
||||
// .addRadio({
|
||||
// path: 'dedupStrategy',
|
||||
// name: 'Deduplication',
|
||||
// description: '',
|
||||
// settings: {
|
||||
// options: [
|
||||
// { value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
|
||||
// {
|
||||
// value: LogsDedupStrategy.exact,
|
||||
// label: 'Exact',
|
||||
// description: LogsDedupDescription[LogsDedupStrategy.exact],
|
||||
// },
|
||||
// {
|
||||
// value: LogsDedupStrategy.numbers,
|
||||
// label: 'Numbers',
|
||||
// description: LogsDedupDescription[LogsDedupStrategy.numbers],
|
||||
// },
|
||||
// {
|
||||
// value: LogsDedupStrategy.signature,
|
||||
// label: 'Signature',
|
||||
// description: LogsDedupDescription[LogsDedupStrategy.signature],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// defaultValue: LogsDedupStrategy.none,
|
||||
// })
|
||||
// .addRadio({
|
||||
// path: 'sortOrder',
|
||||
// name: 'Order',
|
||||
// description: '',
|
||||
// settings: {
|
||||
// options: [
|
||||
// { value: LogsSortOrder.Descending, label: 'Newest first' },
|
||||
// { value: LogsSortOrder.Ascending, label: 'Oldest first' },
|
||||
// ],
|
||||
// },
|
||||
// defaultValue: LogsSortOrder.Descending,
|
||||
// });
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ composableKinds: PanelCfg: {
|
||||
// showCommonLabels: bool
|
||||
// showFieldSelector?: bool
|
||||
// showTime: bool
|
||||
showLogContextToggle: bool
|
||||
// showLogContextToggle: bool
|
||||
showControls?: bool
|
||||
controlsStorageKey?: string
|
||||
// wrapLogMessage: bool
|
||||
|
||||
+2
-2
@@ -41,14 +41,14 @@ export interface Options {
|
||||
onClickFilterLabel?: unknown;
|
||||
onClickFilterOutLabel?: unknown;
|
||||
setDisplayedFields?: unknown;
|
||||
showControls?: boolean;
|
||||
/**
|
||||
* showLabels: bool
|
||||
* showCommonLabels: bool
|
||||
* showFieldSelector?: bool
|
||||
* showTime: bool
|
||||
* showLogContextToggle: bool
|
||||
*/
|
||||
showLogContextToggle: boolean;
|
||||
showControls?: boolean;
|
||||
}
|
||||
|
||||
export const defaultOptions: Partial<Options> = {
|
||||
|
||||
Reference in New Issue
Block a user