207 lines
5.9 KiB
TypeScript
207 lines
5.9 KiB
TypeScript
import { cloneDeep } from 'lodash';
|
|
|
|
import { DataFrame, FieldType } from '@grafana/data';
|
|
|
|
import {
|
|
dataFrameHasLevelLabel,
|
|
dataFrameHasLokiError,
|
|
extractLevelLikeLabelFromDataFrame,
|
|
extractLogParserFromDataFrame,
|
|
extractLabelKeysFromDataFrame,
|
|
extractUnwrapLabelKeysFromDataFrame,
|
|
} from './responseUtils';
|
|
import { LabelType } from './types';
|
|
|
|
const frame: DataFrame = {
|
|
length: 1,
|
|
fields: [
|
|
{
|
|
name: 'Time',
|
|
config: {},
|
|
type: FieldType.time,
|
|
values: [1],
|
|
},
|
|
{
|
|
name: 'labels',
|
|
config: {},
|
|
type: FieldType.other,
|
|
values: [{ level: 'info' }],
|
|
},
|
|
{
|
|
name: 'Line',
|
|
config: {},
|
|
type: FieldType.string,
|
|
values: ['line1'],
|
|
},
|
|
],
|
|
};
|
|
|
|
const frameWithTypes: DataFrame = {
|
|
length: 1,
|
|
fields: [
|
|
{
|
|
name: 'Time',
|
|
config: {},
|
|
type: FieldType.time,
|
|
values: [1],
|
|
},
|
|
{
|
|
name: 'labels',
|
|
config: {},
|
|
type: FieldType.other,
|
|
values: [{ level: 'info', structured: 'foo' }],
|
|
},
|
|
{
|
|
name: 'Line',
|
|
config: {},
|
|
type: FieldType.string,
|
|
values: ['line1'],
|
|
},
|
|
{
|
|
name: 'labelTypes',
|
|
config: {},
|
|
type: FieldType.other,
|
|
values: [{ level: 'I', structured: 'S' }],
|
|
},
|
|
],
|
|
};
|
|
|
|
const frameWithMultipleLabels: DataFrame = {
|
|
length: 1,
|
|
fields: [
|
|
{
|
|
name: 'Time',
|
|
config: {},
|
|
type: FieldType.time,
|
|
values: [1, 2, 3],
|
|
},
|
|
{
|
|
name: 'labels',
|
|
config: {},
|
|
type: FieldType.other,
|
|
values: [
|
|
{ level: 'info', foo: 'bar' },
|
|
{ level: 'info', foo: 'baz', new: 'yes' },
|
|
{ level: 'error', foo: 'baz' },
|
|
],
|
|
},
|
|
{
|
|
name: 'Line',
|
|
config: {},
|
|
type: FieldType.string,
|
|
values: ['line1', 'line2', 'line3'],
|
|
},
|
|
],
|
|
};
|
|
|
|
describe('dataFrameHasParsingError', () => {
|
|
it('handles frame with parsing error', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ level: 'info', __error__: 'error' }];
|
|
expect(dataFrameHasLokiError(input)).toBe(true);
|
|
});
|
|
it('handles frame without parsing error', () => {
|
|
const input = cloneDeep(frame);
|
|
expect(dataFrameHasLokiError(input)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('dataFrameHasLevelLabel', () => {
|
|
it('returns true if level label is present', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ level: 'info' }];
|
|
expect(dataFrameHasLevelLabel(input)).toBe(true);
|
|
});
|
|
it('returns false if level label is present', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ foo: 'bar' }];
|
|
expect(dataFrameHasLevelLabel(input)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('extractLevelLikeLabelFromDataFrame', () => {
|
|
it('returns label if lvl label is present', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ lvl: 'info' }];
|
|
expect(extractLevelLikeLabelFromDataFrame(input)).toBe('lvl');
|
|
});
|
|
it('returns label if level-like label is present', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ error_level: 'info' }];
|
|
expect(extractLevelLikeLabelFromDataFrame(input)).toBe('error_level');
|
|
});
|
|
it('returns label if detected_level label is present', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ detected_level: 'info' }];
|
|
expect(extractLevelLikeLabelFromDataFrame(input)).toBe('detected_level');
|
|
});
|
|
it('returns undefined if no level-like label is present', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ foo: 'info' }];
|
|
expect(extractLevelLikeLabelFromDataFrame(input)).toBe(null);
|
|
});
|
|
});
|
|
|
|
describe('extractLogParserFromDataFrame', () => {
|
|
it('returns false by default', () => {
|
|
const input = cloneDeep(frame);
|
|
expect(extractLogParserFromDataFrame(input)).toEqual({ hasJSON: false, hasLogfmt: false, hasPack: false });
|
|
});
|
|
it('identifies JSON', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[2].values = ['{"a":"b"}'];
|
|
expect(extractLogParserFromDataFrame(input)).toEqual({ hasJSON: true, hasLogfmt: false, hasPack: false });
|
|
});
|
|
it('identifies logfmt', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[2].values = ['a=b'];
|
|
expect(extractLogParserFromDataFrame(input)).toEqual({ hasJSON: false, hasLogfmt: true, hasPack: false });
|
|
});
|
|
});
|
|
|
|
describe('extractLabelKeysFromDataFrame', () => {
|
|
it('returns empty by default', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [];
|
|
expect(extractLabelKeysFromDataFrame(input)).toEqual([]);
|
|
});
|
|
|
|
it('extracts label keys', () => {
|
|
const input = cloneDeep(frame);
|
|
expect(extractLabelKeysFromDataFrame(input)).toEqual(['level']);
|
|
});
|
|
|
|
it('extracts label keys from all logs', () => {
|
|
const input = cloneDeep(frameWithMultipleLabels);
|
|
expect(extractLabelKeysFromDataFrame(input)).toEqual(['level', 'foo', 'new']);
|
|
});
|
|
|
|
it('extracts indexed label keys', () => {
|
|
const input = cloneDeep(frameWithTypes);
|
|
expect(extractLabelKeysFromDataFrame(input)).toEqual(['level']);
|
|
});
|
|
|
|
it('extracts structured metadata label keys', () => {
|
|
const input = cloneDeep(frameWithTypes);
|
|
expect(extractLabelKeysFromDataFrame(input, LabelType.StructuredMetadata)).toEqual(['structured']);
|
|
});
|
|
|
|
it('does not extract structured metadata label keys from non-typed frame', () => {
|
|
const input = cloneDeep(frame);
|
|
expect(extractLabelKeysFromDataFrame(input, LabelType.StructuredMetadata)).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('extractUnwrapLabelKeysFromDataFrame', () => {
|
|
it('returns empty by default', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [];
|
|
expect(extractUnwrapLabelKeysFromDataFrame(input)).toEqual([]);
|
|
});
|
|
it('extracts possible unwrap label keys', () => {
|
|
const input = cloneDeep(frame);
|
|
input.fields[1].values = [{ number: 13 }];
|
|
expect(extractUnwrapLabelKeysFromDataFrame(input)).toEqual(['number']);
|
|
});
|
|
});
|