The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/features/logs/components/logParser.test.ts

225 lines
6.7 KiB

import { ArrayVector, FieldType, MutableDataFrame } from '@grafana/data';
import { ExploreFieldLinkModel } from 'app/features/explore/utils/links';
import { createLogRow } from './__mocks__/logRow';
import { getAllFields, createLogLineLinks, FieldDef } from './logParser';
describe('logParser', () => {
describe('getAllFields', () => {
it('should filter out field with labels name and other type', () => {
const logRow = createLogRow({
entryFieldIndex: 10,
dataFrame: new MutableDataFrame({
refId: 'A',
fields: [
testStringField,
{
name: 'labels',
type: FieldType.other,
config: {},
values: new ArrayVector([{ place: 'luna', source: 'data' }]),
},
],
}),
});
const fields = getAllFields(logRow);
expect(fields.length).toBe(1);
expect(fields.find((field) => field.keys[0] === 'labels')).toBe(undefined);
});
it('should not filter out field with labels name and string type', () => {
const logRow = createLogRow({
entryFieldIndex: 10,
dataFrame: new MutableDataFrame({
refId: 'A',
fields: [
testStringField,
{
name: 'labels',
type: FieldType.string,
config: {},
values: new ArrayVector([{ place: 'luna', source: 'data' }]),
},
],
}),
});
const fields = getAllFields(logRow);
expect(fields.length).toBe(2);
expect(fields.find((field) => field.keys[0] === 'labels')).not.toBe(undefined);
});
it('should filter out field with id name', () => {
const logRow = createLogRow({
entryFieldIndex: 10,
dataFrame: new MutableDataFrame({
refId: 'A',
fields: [
testStringField,
{
name: 'id',
type: FieldType.string,
config: {},
values: new ArrayVector(['1659620138401000000_8b1f7688_']),
},
],
}),
});
const fields = getAllFields(logRow);
expect(fields.length).toBe(1);
expect(fields.find((field) => field.keys[0] === 'id')).toBe(undefined);
});
it('should filter out field with config hidden field', () => {
const testField = { ...testStringField };
testField.config = {
custom: {
hidden: true,
},
};
const logRow = createLogRow({
entryFieldIndex: 10,
dataFrame: new MutableDataFrame({
refId: 'A',
fields: [{ ...testField }],
}),
});
const fields = getAllFields(logRow);
expect(fields.length).toBe(0);
expect(fields.find((field) => field.keys[0] === testField.name)).toBe(undefined);
});
it('should filter out field with null values', () => {
const logRow = createLogRow({
entryFieldIndex: 10,
dataFrame: new MutableDataFrame({
refId: 'A',
fields: [{ ...testFieldWithNullValue }],
}),
});
const fields = getAllFields(logRow);
expect(fields.length).toBe(0);
expect(fields.find((field) => field.keys[0] === testFieldWithNullValue.name)).toBe(undefined);
});
it('should not filter out field with string values', () => {
const logRow = createLogRow({
entryFieldIndex: 10,
dataFrame: new MutableDataFrame({
refId: 'A',
fields: [{ ...testStringField }],
}),
});
const fields = getAllFields(logRow);
expect(fields.length).toBe(1);
expect(fields.find((field) => field.keys[0] === testStringField.name)).not.toBe(undefined);
});
});
describe('createLogLineLinks', () => {
it('should change FieldDef to have keys of variable keys', () => {
const variableLink: ExploreFieldLinkModel = {
href: 'test',
onClick: () => {},
origin: {
config: { links: [] },
name: 'Line',
type: FieldType.string,
values: new ArrayVector(['a', 'b']),
},
title: 'test',
target: '_self',
variables: { path: 'test', msg: 'test msg' },
};
const fieldWithVarLink: FieldDef = {
fieldIndex: 2,
keys: ['Line'],
values: ['level=info msg="test msg" status_code=200 url=http://test'],
links: [variableLink],
};
const fields = createLogLineLinks([fieldWithVarLink]);
expect(fields.length).toBe(1);
expect(fields[0].keys.length).toBe(2);
expect(fields[0].keys[0]).toBe('path');
expect(fields[0].values[0]).toBe('test');
expect(fields[0].keys[1]).toBe('msg');
expect(fields[0].values[1]).toBe('test msg');
});
it('should convert null value to empty string and non string to string', () => {
const variableLink: ExploreFieldLinkModel = {
href: 'test',
onClick: () => {},
origin: {
config: { links: [] },
name: 'Line',
type: FieldType.string,
values: new ArrayVector(['a', 'b']),
},
title: 'test',
target: '_self',
variables: { path: undefined, message: false },
};
const fieldWithVarLink: FieldDef = {
fieldIndex: 2,
keys: ['Line'],
values: ['level=info msg="test msg" status_code=200 url=http://test'],
links: [variableLink],
};
const fields = createLogLineLinks([fieldWithVarLink]);
expect(fields.length).toBe(1);
expect(fields[0].keys.length).toBe(2);
expect(fields[0].keys[0]).toBe('path');
expect(fields[0].values[0]).toBe('');
expect(fields[0].keys[1]).toBe('message');
expect(fields[0].values[1]).toBe('false');
});
it('should return empty array if no variables', () => {
const variableLink: ExploreFieldLinkModel = {
href: 'test',
onClick: () => {},
origin: {
config: { links: [] },
name: 'Line',
type: FieldType.string,
values: new ArrayVector(['a', 'b']),
},
title: 'test',
target: '_self',
};
const fieldWithVarLink: FieldDef = {
fieldIndex: 2,
keys: ['Line'],
values: ['level=info msg="test msg" status_code=200 url=http://test'],
links: [variableLink],
};
const fields = createLogLineLinks([fieldWithVarLink]);
expect(fields.length).toBe(0);
});
});
});
const testStringField = {
name: 'test_field_string',
type: FieldType.string,
config: {},
values: new ArrayVector(['abc']),
};
const testFieldWithNullValue = {
name: 'test_field_null',
type: FieldType.string,
config: {},
values: new ArrayVector([null]),
};