mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Support fields interpolation in logs panel (#58426)
This commit is contained in:
parent
b13b58ebf8
commit
039f4cb4dd
@ -79,7 +79,7 @@ interface Props extends Themeable2 {
|
|||||||
onStartScanning?: () => void;
|
onStartScanning?: () => void;
|
||||||
onStopScanning?: () => void;
|
onStopScanning?: () => void;
|
||||||
getRowContext?: (row: LogRowModel, options?: RowContextOptions) => Promise<any>;
|
getRowContext?: (row: LogRowModel, options?: RowContextOptions) => Promise<any>;
|
||||||
getFieldLinks: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
|
getFieldLinks: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>;
|
||||||
addResultsToCache: () => void;
|
addResultsToCache: () => void;
|
||||||
clearCache: () => void;
|
clearCache: () => void;
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
RawTimeRange,
|
RawTimeRange,
|
||||||
EventBus,
|
EventBus,
|
||||||
SplitOpen,
|
SplitOpen,
|
||||||
|
DataFrame,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { Collapse } from '@grafana/ui';
|
import { Collapse } from '@grafana/ui';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
@ -71,9 +72,9 @@ class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
getFieldLinks = (field: Field, rowIndex: number) => {
|
getFieldLinks = (field: Field, rowIndex: number, dataFrame: DataFrame) => {
|
||||||
const { splitOpenFn, range } = this.props;
|
const { splitOpenFn, range } = this.props;
|
||||||
return getFieldLinksForExplore({ field, rowIndex, splitOpenFn, range });
|
return getFieldLinksForExplore({ field, rowIndex, splitOpenFn, range, dataFrame });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
|
|||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import { Field, LinkModel, LogRowModel, GrafanaTheme2, CoreApp } from '@grafana/data';
|
import { Field, LinkModel, LogRowModel, GrafanaTheme2, CoreApp, DataFrame } from '@grafana/data';
|
||||||
import { withTheme2, Themeable2, Icon, Tooltip } from '@grafana/ui';
|
import { withTheme2, Themeable2, Icon, Tooltip } from '@grafana/ui';
|
||||||
|
|
||||||
import { calculateFieldStats, calculateLogsLabelStats, calculateStats, getParser } from '../utils';
|
import { calculateFieldStats, calculateLogsLabelStats, calculateStats, getParser } from '../utils';
|
||||||
@ -24,7 +24,7 @@ export interface Props extends Themeable2 {
|
|||||||
|
|
||||||
onClickFilterLabel?: (key: string, value: string) => void;
|
onClickFilterLabel?: (key: string, value: string) => void;
|
||||||
onClickFilterOutLabel?: (key: string, value: string) => void;
|
onClickFilterOutLabel?: (key: string, value: string) => void;
|
||||||
getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
|
getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>;
|
||||||
showDetectedFields?: string[];
|
showDetectedFields?: string[];
|
||||||
onClickShowDetectedField?: (key: string) => void;
|
onClickShowDetectedField?: (key: string) => void;
|
||||||
onClickHideDetectedField?: (key: string) => void;
|
onClickHideDetectedField?: (key: string) => void;
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
dateTimeFormat,
|
dateTimeFormat,
|
||||||
GrafanaTheme2,
|
GrafanaTheme2,
|
||||||
CoreApp,
|
CoreApp,
|
||||||
|
DataFrame,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { reportInteraction } from '@grafana/runtime';
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import { styleMixins, withTheme2, Themeable2, Icon, Tooltip } from '@grafana/ui';
|
import { styleMixins, withTheme2, Themeable2, Icon, Tooltip } from '@grafana/ui';
|
||||||
@ -52,7 +53,7 @@ interface Props extends Themeable2 {
|
|||||||
onClickFilterOutLabel?: (key: string, value: string) => void;
|
onClickFilterOutLabel?: (key: string, value: string) => void;
|
||||||
onContextClick?: () => void;
|
onContextClick?: () => void;
|
||||||
getRowContext: (row: LogRowModel, options?: RowContextOptions) => Promise<DataQueryResponse>;
|
getRowContext: (row: LogRowModel, options?: RowContextOptions) => Promise<DataQueryResponse>;
|
||||||
getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
|
getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>;
|
||||||
showContextToggle?: (row?: LogRowModel) => boolean;
|
showContextToggle?: (row?: LogRowModel) => boolean;
|
||||||
onClickShowDetectedField?: (key: string) => void;
|
onClickShowDetectedField?: (key: string) => void;
|
||||||
onClickHideDetectedField?: (key: string) => void;
|
onClickHideDetectedField?: (key: string) => void;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import { LogRowModel, Field, LinkModel } from '@grafana/data';
|
import { LogRowModel, Field, LinkModel, DataFrame } from '@grafana/data';
|
||||||
import { withTheme2, Themeable2 } from '@grafana/ui';
|
import { withTheme2, Themeable2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { getAllFields } from './logParser';
|
import { getAllFields } from './logParser';
|
||||||
@ -10,7 +10,7 @@ export interface Props extends Themeable2 {
|
|||||||
row: LogRowModel;
|
row: LogRowModel;
|
||||||
showDetectedFields: string[];
|
showDetectedFields: string[];
|
||||||
wrapLogMessage: boolean;
|
wrapLogMessage: boolean;
|
||||||
getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
|
getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnThemedLogRowMessageDetectedFields extends PureComponent<Props> {
|
class UnThemedLogRowMessageDetectedFields extends PureComponent<Props> {
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import { TimeZone, LogsDedupStrategy, LogRowModel, Field, LinkModel, LogsSortOrder, CoreApp } from '@grafana/data';
|
import {
|
||||||
|
TimeZone,
|
||||||
|
LogsDedupStrategy,
|
||||||
|
LogRowModel,
|
||||||
|
Field,
|
||||||
|
LinkModel,
|
||||||
|
LogsSortOrder,
|
||||||
|
CoreApp,
|
||||||
|
DataFrame,
|
||||||
|
} from '@grafana/data';
|
||||||
import { withTheme2, Themeable2 } from '@grafana/ui';
|
import { withTheme2, Themeable2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { sortLogRows } from '../utils';
|
import { sortLogRows } from '../utils';
|
||||||
@ -33,7 +42,7 @@ export interface Props extends Themeable2 {
|
|||||||
onClickFilterLabel?: (key: string, value: string) => void;
|
onClickFilterLabel?: (key: string, value: string) => void;
|
||||||
onClickFilterOutLabel?: (key: string, value: string) => void;
|
onClickFilterOutLabel?: (key: string, value: string) => void;
|
||||||
getRowContext?: (row: LogRowModel, options?: RowContextOptions) => Promise<any>;
|
getRowContext?: (row: LogRowModel, options?: RowContextOptions) => Promise<any>;
|
||||||
getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>;
|
getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>;
|
||||||
onClickShowDetectedField?: (key: string) => void;
|
onClickShowDetectedField?: (key: string) => void;
|
||||||
onClickHideDetectedField?: (key: string) => void;
|
onClickHideDetectedField?: (key: string) => void;
|
||||||
onLogRowHover?: (row?: LogRowModel) => void;
|
onLogRowHover?: (row?: LogRowModel) => void;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
|
|
||||||
import { Field, FieldType, LinkModel, LogRowModel } from '@grafana/data';
|
import { DataFrame, Field, FieldType, LinkModel, LogRowModel } from '@grafana/data';
|
||||||
|
|
||||||
import { getParser } from '../utils';
|
import { getParser } from '../utils';
|
||||||
|
|
||||||
@ -20,7 +20,10 @@ type FieldDef = {
|
|||||||
* found in the dataframe (they may contain links).
|
* found in the dataframe (they may contain links).
|
||||||
*/
|
*/
|
||||||
export const getAllFields = memoizeOne(
|
export const getAllFields = memoizeOne(
|
||||||
(row: LogRowModel, getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>) => {
|
(
|
||||||
|
row: LogRowModel,
|
||||||
|
getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>
|
||||||
|
) => {
|
||||||
const logMessageFields = parseMessage(row.entry);
|
const logMessageFields = parseMessage(row.entry);
|
||||||
const dataframeFields = getDataframeFields(row, getFieldLinks);
|
const dataframeFields = getDataframeFields(row, getFieldLinks);
|
||||||
const fieldsMap = [...dataframeFields, ...logMessageFields].reduce((acc, field) => {
|
const fieldsMap = [...dataframeFields, ...logMessageFields].reduce((acc, field) => {
|
||||||
@ -72,12 +75,15 @@ const parseMessage = memoizeOne((rowEntry): FieldDef[] => {
|
|||||||
|
|
||||||
// creates fields from the dataframe-fields, adding data-links, when field.config.links exists
|
// creates fields from the dataframe-fields, adding data-links, when field.config.links exists
|
||||||
const getDataframeFields = memoizeOne(
|
const getDataframeFields = memoizeOne(
|
||||||
(row: LogRowModel, getFieldLinks?: (field: Field, rowIndex: number) => Array<LinkModel<Field>>): FieldDef[] => {
|
(
|
||||||
|
row: LogRowModel,
|
||||||
|
getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>
|
||||||
|
): FieldDef[] => {
|
||||||
return row.dataFrame.fields
|
return row.dataFrame.fields
|
||||||
.map((field, index) => ({ ...field, index }))
|
.map((field, index) => ({ ...field, index }))
|
||||||
.filter((field, index) => !shouldRemoveField(field, index, row))
|
.filter((field, index) => !shouldRemoveField(field, index, row))
|
||||||
.map((field) => {
|
.map((field) => {
|
||||||
const links = getFieldLinks ? getFieldLinks(field, row.rowIndex) : [];
|
const links = getFieldLinks ? getFieldLinks(field, row.rowIndex, row.dataFrame) : [];
|
||||||
return {
|
return {
|
||||||
key: field.name,
|
key: field.name,
|
||||||
value: field.values.get(row.rowIndex).toString(),
|
value: field.values.get(row.rowIndex).toString(),
|
||||||
|
Loading…
Reference in New Issue
Block a user