mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
Suggestions: Adds logs suggestions and sorting by score to suggestions (#41613)
* Suggestions: Adds logs suggestions for sorting by score to suggestions * Introduced an enum * review feedback
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { DataQueryError, DataQueryRequest, DataQueryTimings } from './datasource';
|
import { DataQueryError, DataQueryRequest, DataQueryTimings } from './datasource';
|
||||||
import { PluginMeta } from './plugin';
|
import { PluginMeta } from './plugin';
|
||||||
import { ScopedVars } from './ScopedVars';
|
import { ScopedVars } from './ScopedVars';
|
||||||
import { LoadingState } from './data';
|
import { LoadingState, PreferredVisualisationType } from './data';
|
||||||
import { DataFrame, FieldType } from './dataFrame';
|
import { DataFrame, FieldType } from './dataFrame';
|
||||||
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
||||||
import { EventBus } from '../events';
|
import { EventBus } from '../events';
|
||||||
@@ -203,6 +203,17 @@ export interface VisualizationSuggestion<TOptions = any, TFieldConfig = any> {
|
|||||||
transformations?: DataTransformerConfig[];
|
transformations?: DataTransformerConfig[];
|
||||||
/** Tweak for small preview */
|
/** Tweak for small preview */
|
||||||
previewModifier?: (suggestion: VisualizationSuggestion) => void;
|
previewModifier?: (suggestion: VisualizationSuggestion) => void;
|
||||||
|
/** A value between 0-100 how suitable suggestion is */
|
||||||
|
score?: VisualizationSuggestionScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum VisualizationSuggestionScore {
|
||||||
|
/** We are pretty sure this is the best possible option */
|
||||||
|
Best = 100,
|
||||||
|
/** Should be a really good option */
|
||||||
|
Good = 70,
|
||||||
|
/** Can be visualized but there are likely better options. If no score is set this score is assumed */
|
||||||
|
OK = 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -213,12 +224,15 @@ export interface PanelDataSummary {
|
|||||||
rowCountTotal: number;
|
rowCountTotal: number;
|
||||||
rowCountMax: number;
|
rowCountMax: number;
|
||||||
frameCount: number;
|
frameCount: number;
|
||||||
|
fieldCount: number;
|
||||||
numberFieldCount: number;
|
numberFieldCount: number;
|
||||||
timeFieldCount: number;
|
timeFieldCount: number;
|
||||||
stringFieldCount: number;
|
stringFieldCount: number;
|
||||||
hasNumberField?: boolean;
|
hasNumberField?: boolean;
|
||||||
hasTimeField?: boolean;
|
hasTimeField?: boolean;
|
||||||
hasStringField?: boolean;
|
hasStringField?: boolean;
|
||||||
|
/** The first frame that set's this value */
|
||||||
|
preferredVisualisationType?: PreferredVisualisationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,11 +266,19 @@ export class VisualizationSuggestionsBuilder {
|
|||||||
let stringFieldCount = 0;
|
let stringFieldCount = 0;
|
||||||
let rowCountTotal = 0;
|
let rowCountTotal = 0;
|
||||||
let rowCountMax = 0;
|
let rowCountMax = 0;
|
||||||
|
let fieldCount = 0;
|
||||||
|
let preferredVisualisationType: PreferredVisualisationType | undefined;
|
||||||
|
|
||||||
for (const frame of frames) {
|
for (const frame of frames) {
|
||||||
rowCountTotal += frame.length;
|
rowCountTotal += frame.length;
|
||||||
|
|
||||||
|
if (frame.meta?.preferredVisualisationType) {
|
||||||
|
preferredVisualisationType = frame.meta.preferredVisualisationType;
|
||||||
|
}
|
||||||
|
|
||||||
for (const field of frame.fields) {
|
for (const field of frame.fields) {
|
||||||
|
fieldCount++;
|
||||||
|
|
||||||
switch (field.type) {
|
switch (field.type) {
|
||||||
case FieldType.number:
|
case FieldType.number:
|
||||||
numberFieldCount += 1;
|
numberFieldCount += 1;
|
||||||
@@ -281,6 +303,8 @@ export class VisualizationSuggestionsBuilder {
|
|||||||
stringFieldCount,
|
stringFieldCount,
|
||||||
rowCountTotal,
|
rowCountTotal,
|
||||||
rowCountMax,
|
rowCountMax,
|
||||||
|
fieldCount,
|
||||||
|
preferredVisualisationType,
|
||||||
frameCount: frames.length,
|
frameCount: frames.length,
|
||||||
hasData: rowCountTotal > 0,
|
hasData: rowCountTotal > 0,
|
||||||
hasTimeField: timeFieldCount > 0,
|
hasTimeField: timeFieldCount > 0,
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ scenario('Single frame with string and 2 number field', (ctx) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
scenario('Single frame with string with only string field', (ctx) => {
|
scenario('Single frame with only string field', (ctx) => {
|
||||||
ctx.setData([
|
ctx.setData([
|
||||||
toDataFrame({
|
toDataFrame({
|
||||||
fields: [{ name: 'Name', type: FieldType.string, values: ['Hugo', 'Dominik', 'Marcus'] }],
|
fields: [{ name: 'Name', type: FieldType.string, values: ['Hugo', 'Dominik', 'Marcus'] }],
|
||||||
@@ -288,7 +288,7 @@ scenario('Single frame with string with only string field', (ctx) => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
it('should return correct suggestions', () => {
|
it('should return correct suggestions', () => {
|
||||||
expect(ctx.names()).toEqual([SuggestionName.Stat, SuggestionName.StatColoredBackground, SuggestionName.Table]);
|
expect(ctx.names()).toEqual([SuggestionName.Stat, SuggestionName.Table]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Stat panels have reduceOptions.fields set to show all fields', () => {
|
it('Stat panels have reduceOptions.fields set to show all fields', () => {
|
||||||
@@ -300,6 +300,32 @@ scenario('Single frame with string with only string field', (ctx) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
scenario('Given default loki logs data', (ctx) => {
|
||||||
|
ctx.setData([
|
||||||
|
toDataFrame({
|
||||||
|
fields: [
|
||||||
|
{ name: 'ts', type: FieldType.time, values: ['2021-11-11T13:38:45.440Z', '2021-11-11T13:38:45.190Z'] },
|
||||||
|
{
|
||||||
|
name: 'line',
|
||||||
|
type: FieldType.string,
|
||||||
|
values: [
|
||||||
|
't=2021-11-11T14:38:45+0100 lvl=dbug msg="Client connected" logger=live user=1 client=ee79155b-a8d1-4730-bcb3-94d8690df35c',
|
||||||
|
't=2021-11-11T14:38:45+0100 lvl=dbug msg="Adding CSP header to response" logger=http.server cfg=0xc0005fed00',
|
||||||
|
],
|
||||||
|
labels: { filename: '/var/log/grafana/grafana.log', job: 'grafana' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
meta: {
|
||||||
|
preferredVisualisationType: 'logs',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
it('should return correct suggestions', () => {
|
||||||
|
expect(ctx.names()).toEqual([SuggestionName.Logs, SuggestionName.Table]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function repeatFrame(count: number, frame: DataFrame): DataFrame[] {
|
function repeatFrame(count: number, frame: DataFrame): DataFrame[] {
|
||||||
const frames: DataFrame[] = [];
|
const frames: DataFrame[] = [];
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { PanelData, VisualizationSuggestion, VisualizationSuggestionsBuilder, PanelModel } from '@grafana/data';
|
import {
|
||||||
|
PanelData,
|
||||||
|
VisualizationSuggestion,
|
||||||
|
VisualizationSuggestionsBuilder,
|
||||||
|
PanelModel,
|
||||||
|
VisualizationSuggestionScore,
|
||||||
|
} from '@grafana/data';
|
||||||
import { importPanelPlugin } from 'app/features/plugins/importPanelPlugin';
|
import { importPanelPlugin } from 'app/features/plugins/importPanelPlugin';
|
||||||
|
|
||||||
export const panelsToCheckFirst = [
|
export const panelsToCheckFirst = [
|
||||||
@@ -13,6 +19,7 @@ export const panelsToCheckFirst = [
|
|||||||
'status-history',
|
'status-history',
|
||||||
'text',
|
'text',
|
||||||
'dashlist',
|
'dashlist',
|
||||||
|
'logs',
|
||||||
];
|
];
|
||||||
|
|
||||||
export async function getAllSuggestions(data?: PanelData, panel?: PanelModel): Promise<VisualizationSuggestion[]> {
|
export async function getAllSuggestions(data?: PanelData, panel?: PanelModel): Promise<VisualizationSuggestion[]> {
|
||||||
@@ -27,5 +34,7 @@ export async function getAllSuggestions(data?: PanelData, panel?: PanelModel): P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.getList();
|
return builder.getList().sort((a, b) => {
|
||||||
|
return (b.score ?? VisualizationSuggestionScore.OK) - (a.score ?? VisualizationSuggestionScore.OK);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,84 @@
|
|||||||
import { PanelPlugin, LogsSortOrder, LogsDedupStrategy, LogsDedupDescription } from '@grafana/data';
|
import { PanelPlugin, LogsSortOrder, LogsDedupStrategy, LogsDedupDescription } from '@grafana/data';
|
||||||
import { Options } from './types';
|
import { Options } from './types';
|
||||||
import { LogsPanel } from './LogsPanel';
|
import { LogsPanel } from './LogsPanel';
|
||||||
|
import { LogsPanelSuggestionsSupplier } from './suggestions';
|
||||||
|
|
||||||
export const plugin = new PanelPlugin<Options>(LogsPanel).setPanelOptions((builder) => {
|
export const plugin = new PanelPlugin<Options>(LogsPanel)
|
||||||
builder
|
.setPanelOptions((builder) => {
|
||||||
.addBooleanSwitch({
|
builder
|
||||||
path: 'showTime',
|
.addBooleanSwitch({
|
||||||
name: 'Time',
|
path: 'showTime',
|
||||||
description: '',
|
name: 'Time',
|
||||||
defaultValue: false,
|
description: '',
|
||||||
})
|
defaultValue: false,
|
||||||
.addBooleanSwitch({
|
})
|
||||||
path: 'showLabels',
|
.addBooleanSwitch({
|
||||||
name: 'Unique labels',
|
path: 'showLabels',
|
||||||
description: '',
|
name: 'Unique labels',
|
||||||
defaultValue: false,
|
description: '',
|
||||||
})
|
defaultValue: false,
|
||||||
.addBooleanSwitch({
|
})
|
||||||
path: 'showCommonLabels',
|
.addBooleanSwitch({
|
||||||
name: 'Common labels',
|
path: 'showCommonLabels',
|
||||||
description: '',
|
name: 'Common labels',
|
||||||
defaultValue: false,
|
description: '',
|
||||||
})
|
defaultValue: false,
|
||||||
.addBooleanSwitch({
|
})
|
||||||
path: 'wrapLogMessage',
|
.addBooleanSwitch({
|
||||||
name: 'Wrap lines',
|
path: 'wrapLogMessage',
|
||||||
description: '',
|
name: 'Wrap lines',
|
||||||
defaultValue: false,
|
description: '',
|
||||||
})
|
defaultValue: false,
|
||||||
.addBooleanSwitch({
|
})
|
||||||
path: 'prettifyLogMessage',
|
.addBooleanSwitch({
|
||||||
name: 'Prettify JSON',
|
path: 'prettifyLogMessage',
|
||||||
description: '',
|
name: 'Prettify JSON',
|
||||||
defaultValue: false,
|
description: '',
|
||||||
})
|
defaultValue: false,
|
||||||
.addBooleanSwitch({
|
})
|
||||||
path: 'enableLogDetails',
|
.addBooleanSwitch({
|
||||||
name: 'Enable log details',
|
path: 'enableLogDetails',
|
||||||
description: '',
|
name: 'Enable log details',
|
||||||
defaultValue: true,
|
description: '',
|
||||||
})
|
defaultValue: true,
|
||||||
.addRadio({
|
})
|
||||||
path: 'dedupStrategy',
|
.addRadio({
|
||||||
name: 'Deduplication',
|
path: 'dedupStrategy',
|
||||||
description: '',
|
name: 'Deduplication',
|
||||||
settings: {
|
description: '',
|
||||||
options: [
|
settings: {
|
||||||
{ value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
|
options: [
|
||||||
{
|
{ value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
|
||||||
value: LogsDedupStrategy.exact,
|
{
|
||||||
label: 'Exact',
|
value: LogsDedupStrategy.exact,
|
||||||
description: LogsDedupDescription[LogsDedupStrategy.exact],
|
label: 'Exact',
|
||||||
},
|
description: LogsDedupDescription[LogsDedupStrategy.exact],
|
||||||
{
|
},
|
||||||
value: LogsDedupStrategy.numbers,
|
{
|
||||||
label: 'Numbers',
|
value: LogsDedupStrategy.numbers,
|
||||||
description: LogsDedupDescription[LogsDedupStrategy.numbers],
|
label: 'Numbers',
|
||||||
},
|
description: LogsDedupDescription[LogsDedupStrategy.numbers],
|
||||||
{
|
},
|
||||||
value: LogsDedupStrategy.signature,
|
{
|
||||||
label: 'Signature',
|
value: LogsDedupStrategy.signature,
|
||||||
description: LogsDedupDescription[LogsDedupStrategy.signature],
|
label: 'Signature',
|
||||||
},
|
description: LogsDedupDescription[LogsDedupStrategy.signature],
|
||||||
],
|
},
|
||||||
},
|
],
|
||||||
defaultValue: LogsDedupStrategy.none,
|
},
|
||||||
})
|
defaultValue: LogsDedupStrategy.none,
|
||||||
.addRadio({
|
})
|
||||||
path: 'sortOrder',
|
.addRadio({
|
||||||
name: 'Order',
|
path: 'sortOrder',
|
||||||
description: '',
|
name: 'Order',
|
||||||
settings: {
|
description: '',
|
||||||
options: [
|
settings: {
|
||||||
{ value: LogsSortOrder.Descending, label: 'Descending' },
|
options: [
|
||||||
{ value: LogsSortOrder.Ascending, label: 'Ascending' },
|
{ value: LogsSortOrder.Descending, label: 'Descending' },
|
||||||
],
|
{ value: LogsSortOrder.Ascending, label: 'Ascending' },
|
||||||
},
|
],
|
||||||
defaultValue: LogsSortOrder.Descending,
|
},
|
||||||
});
|
defaultValue: LogsSortOrder.Descending,
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.setSuggestionsSupplier(new LogsPanelSuggestionsSupplier());
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { VisualizationSuggestionsBuilder, VisualizationSuggestionScore } from '@grafana/data';
|
||||||
|
import { SuggestionName } from 'app/types/suggestions';
|
||||||
|
import { Options } from './types';
|
||||||
|
|
||||||
|
export class LogsPanelSuggestionsSupplier {
|
||||||
|
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||||
|
const list = builder.getListAppender<Options, {}>({
|
||||||
|
name: '',
|
||||||
|
pluginId: 'logs',
|
||||||
|
options: {},
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
custom: {},
|
||||||
|
},
|
||||||
|
overrides: [],
|
||||||
|
},
|
||||||
|
previewModifier: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { dataSummary: ds } = builder;
|
||||||
|
|
||||||
|
// Require a string & time field
|
||||||
|
if (!ds.hasData || !ds.hasTimeField || !ds.hasStringField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds.preferredVisualisationType === 'logs') {
|
||||||
|
list.append({ name: SuggestionName.Logs, score: VisualizationSuggestionScore.Best });
|
||||||
|
} else {
|
||||||
|
list.append({ name: SuggestionName.Logs });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,6 @@ export class PieChartSuggestionsSupplier {
|
|||||||
previewModifier: (s) => {
|
previewModifier: (s) => {
|
||||||
// Hide labels in preview
|
// Hide labels in preview
|
||||||
s.options!.legend.displayMode = LegendDisplayMode.Hidden;
|
s.options!.legend.displayMode = LegendDisplayMode.Hidden;
|
||||||
s.options!.displayLabels = [];
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { StatPanelOptions } from './types';
|
|||||||
|
|
||||||
export class StatSuggestionsSupplier {
|
export class StatSuggestionsSupplier {
|
||||||
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||||
const { dataSummary } = builder;
|
const { dataSummary: ds } = builder;
|
||||||
|
|
||||||
if (!dataSummary.hasData) {
|
if (!ds.hasData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,14 +29,15 @@ export class StatSuggestionsSupplier {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (dataSummary.hasStringField && dataSummary.frameCount === 1 && dataSummary.rowCountTotal < 10) {
|
// String and number field with low row count show individual rows
|
||||||
|
if (ds.hasStringField && ds.hasNumberField && ds.frameCount === 1 && ds.rowCountTotal < 10) {
|
||||||
list.append({
|
list.append({
|
||||||
name: SuggestionName.Stat,
|
name: SuggestionName.Stat,
|
||||||
options: {
|
options: {
|
||||||
reduceOptions: {
|
reduceOptions: {
|
||||||
values: true,
|
values: true,
|
||||||
calcs: [],
|
calcs: [],
|
||||||
fields: dataSummary.hasNumberField ? undefined : '/.*/',
|
fields: '/.*/',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -46,12 +47,29 @@ export class StatSuggestionsSupplier {
|
|||||||
reduceOptions: {
|
reduceOptions: {
|
||||||
values: true,
|
values: true,
|
||||||
calcs: [],
|
calcs: [],
|
||||||
fields: dataSummary.hasNumberField ? undefined : '/.*/',
|
fields: '/.*/',
|
||||||
},
|
},
|
||||||
colorMode: BigValueColorMode.Background,
|
colorMode: BigValueColorMode.Background,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if (dataSummary.hasNumberField) {
|
}
|
||||||
|
|
||||||
|
// Just a single string field
|
||||||
|
if (ds.stringFieldCount === 1 && ds.frameCount === 1 && ds.rowCountTotal < 10 && ds.fieldCount === 1) {
|
||||||
|
list.append({
|
||||||
|
name: SuggestionName.Stat,
|
||||||
|
options: {
|
||||||
|
reduceOptions: {
|
||||||
|
values: true,
|
||||||
|
calcs: [],
|
||||||
|
fields: '/.*/',
|
||||||
|
},
|
||||||
|
colorMode: BigValueColorMode.None,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds.hasNumberField && ds.hasTimeField) {
|
||||||
list.append({
|
list.append({
|
||||||
options: {
|
options: {
|
||||||
reduceOptions: {
|
reduceOptions: {
|
||||||
|
|||||||
@@ -4,19 +4,24 @@ import { TimelineFieldConfig, TimelineOptions } from './types';
|
|||||||
|
|
||||||
export class StatTimelineSuggestionsSupplier {
|
export class StatTimelineSuggestionsSupplier {
|
||||||
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||||
const { dataSummary } = builder;
|
const { dataSummary: ds } = builder;
|
||||||
|
|
||||||
if (!dataSummary.hasData) {
|
if (!ds.hasData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This panel needs a time field and a string or number field
|
// This panel needs a time field and a string or number field
|
||||||
if (!dataSummary.hasTimeField || (!dataSummary.hasStringField && !dataSummary.hasNumberField)) {
|
if (!ds.hasTimeField || (!ds.hasStringField && !ds.hasNumberField)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are many series then they won't fit on y-axis so this panel is not good fit
|
// If there are many series then they won't fit on y-axis so this panel is not good fit
|
||||||
if (dataSummary.numberFieldCount >= 30) {
|
if (ds.numberFieldCount >= 30) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probably better ways to filter out this by inspecting the types of string values so view this as temporary
|
||||||
|
if (ds.preferredVisualisationType === 'logs') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,24 +4,29 @@ import { StatusPanelOptions, StatusFieldConfig } from './types';
|
|||||||
|
|
||||||
export class StatusHistorySuggestionsSupplier {
|
export class StatusHistorySuggestionsSupplier {
|
||||||
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||||
const { dataSummary } = builder;
|
const { dataSummary: ds } = builder;
|
||||||
|
|
||||||
if (!dataSummary.hasData) {
|
if (!ds.hasData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This panel needs a time field and a string or number field
|
// This panel needs a time field and a string or number field
|
||||||
if (!dataSummary.hasTimeField || (!dataSummary.hasStringField && !dataSummary.hasNumberField)) {
|
if (!ds.hasTimeField || (!ds.hasStringField && !ds.hasNumberField)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are many series then they won't fit on y-axis so this panel is not good fit
|
// If there are many series then they won't fit on y-axis so this panel is not good fit
|
||||||
if (dataSummary.numberFieldCount >= 30) {
|
if (ds.numberFieldCount >= 30) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there a lot of data points for each series then this is not a good match
|
// if there a lot of data points for each series then this is not a good match
|
||||||
if (dataSummary.rowCountMax > 100) {
|
if (ds.rowCountMax > 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probably better ways to filter out this by inspecting the types of string values so view this as temporary
|
||||||
|
if (ds.preferredVisualisationType === 'logs') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,4 +25,5 @@ export enum SuggestionName {
|
|||||||
StatusHistory = 'Status history',
|
StatusHistory = 'Status history',
|
||||||
TextPanel = 'Text panel',
|
TextPanel = 'Text panel',
|
||||||
DashboardList = 'Dashboard list',
|
DashboardList = 'Dashboard list',
|
||||||
|
Logs = 'Logs',
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user