loki: backend: add error-prop if loki parse error happened (#48860)

pull/48750/head
Gábor Farkas 3 years ago committed by GitHub
parent 8b9419222a
commit f866165445
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      public/app/plugins/datasource/loki/backendResultTransformer.test.ts
  2. 15
      public/app/plugins/datasource/loki/backendResultTransformer.ts
  3. 41
      public/app/plugins/datasource/loki/responseUtils.test.ts
  4. 6
      public/app/plugins/datasource/loki/responseUtils.ts
  5. 3
      public/app/plugins/datasource/loki/result_transformer.ts

@ -39,12 +39,11 @@ const inputFrame: DataFrame = {
{
name: 'labels',
type: FieldType.string,
config: {
custom: {
json: true,
},
},
values: new ArrayVector(['{ "level": "info", "code": "41🌙" }', '{ "level": "error", "code": "41🌙" }']),
config: {},
values: new ArrayVector([
{ level: 'info', code: '41🌙' },
{ level: 'error', code: '41🌙' },
]),
},
{
name: 'tsNs',
@ -157,4 +156,30 @@ describe('loki backendResultTransformer', () => {
result.data[0].fields.filter((field: Field) => field.name === 'derived1' && field.type === 'string').length
).toBe(1);
});
it('handle loki parsing errors', () => {
const clonedFrame = cloneDeep(inputFrame);
clonedFrame.fields[2] = {
name: 'labels',
type: FieldType.string,
config: {},
values: new ArrayVector([
{ level: 'info', code: '41🌙', __error__: 'LogfmtParserErr' },
{ level: 'error', code: '41🌙' },
]),
};
const response: DataQueryResponse = { data: [clonedFrame] };
const result = transformBackendResult(
response,
[
{
refId: 'A',
expr: LOKI_EXPR,
},
],
[]
);
expect(result.data[0]?.meta?.custom?.error).toBe('Error when parsing some of the logs');
});
});

@ -3,6 +3,7 @@ import { DataQueryResponse, DataFrame, isDataFrame, FieldType, QueryResultMeta }
import { getDerivedFields } from './getDerivedFields';
import { makeTableFrames } from './makeTableFrames';
import { formatQuery, getHighlighterExpressionsFromQuery } from './query_utils';
import { dataFrameHasLokiError } from './responseUtils';
import { DerivedFieldConfig, LokiQuery, LokiQueryType } from './types';
function isMetricFrame(frame: DataFrame): boolean {
@ -25,14 +26,20 @@ function processStreamFrame(
query: LokiQuery | undefined,
derivedFieldConfigs: DerivedFieldConfig[]
): DataFrame {
const custom: Record<string, string> = {
// used by logs_model
lokiQueryStatKey: 'Summary: total bytes processed',
};
if (dataFrameHasLokiError(frame)) {
custom.error = 'Error when parsing some of the logs';
}
const meta: QueryResultMeta = {
preferredVisualisationType: 'logs',
limit: query?.maxLines,
searchWords: query !== undefined ? getHighlighterExpressionsFromQuery(formatQuery(query.expr)) : undefined,
custom: {
// used by logs_model
lokiQueryStatKey: 'Summary: total bytes processed',
},
custom,
};
const newFrame = setFrameMeta(frame, meta);

@ -0,0 +1,41 @@
import { cloneDeep } from 'lodash';
import { ArrayVector, DataFrame, FieldType } from '@grafana/data';
import { dataFrameHasLokiError } from './responseUtils';
const frame: DataFrame = {
length: 1,
fields: [
{
name: 'Time',
config: {},
type: FieldType.time,
values: new ArrayVector([1]),
},
{
name: 'labels',
config: {},
type: FieldType.other,
values: new ArrayVector([{ level: 'info' }]),
},
{
name: 'Line',
config: {},
type: FieldType.string,
values: new ArrayVector(['line1']),
},
],
};
describe('dataframeHasParsingError', () => {
it('handles frame with parsing error', () => {
const input = cloneDeep(frame);
input.fields[1].values = new ArrayVector([{ level: 'info', __error__: 'error' }]);
expect(dataFrameHasLokiError(input)).toBe(true);
});
it('handles frame without parsing error', () => {
const input = cloneDeep(frame);
expect(dataFrameHasLokiError(input)).toBe(false);
});
});

@ -0,0 +1,6 @@
import { DataFrame, Labels } from '@grafana/data';
export function dataFrameHasLokiError(frame: DataFrame): boolean {
const labelSets: Labels[] = frame.fields.find((f) => f.name === 'labels')?.values.toArray() ?? [];
return labelSets.some((labels) => labels.__error__ !== undefined);
}

@ -25,6 +25,7 @@ import TableModel from 'app/core/table_model';
import { renderLegendFormat } from '../prometheus/legend';
import { formatQuery, getHighlighterExpressionsFromQuery } from './query_utils';
import { dataFrameHasLokiError } from './responseUtils';
import {
LokiRangeQueryRequest,
LokiResponse,
@ -346,7 +347,7 @@ export function lokiStreamsToDataFrames(
const dataFrame = lokiStreamsToRawDataFrame(data, target.refId);
enhanceDataFrame(dataFrame, config);
if (meta.custom && dataFrame.fields.some((f) => f.labels && Object.keys(f.labels).some((l) => l === '__error__'))) {
if (meta.custom && dataFrameHasLokiError(dataFrame)) {
meta.custom.error = 'Error when parsing some of the logs';
}

Loading…
Cancel
Save