123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967 |
- import { DataFrame, FieldType, DataQueryRequest, DataQueryResponse, MutableDataFrame } from '@grafana/data';
- import { transform, transformV2, transformDFToTable, parseSampleValue } from './result_transformer';
- import { PromQuery } from './types';
- jest.mock('@grafana/runtime', () => ({
- getTemplateSrv: () => ({
- replace: (str: string) => str,
- }),
- getDataSourceSrv: () => {
- return {
- getInstanceSettings: () => {
- return { name: 'Tempo' };
- },
- };
- },
- }));
- const matrixResponse = {
- status: 'success',
- data: {
- resultType: 'matrix',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob' },
- values: [
- [1, '10'],
- [2, '0'],
- ],
- },
- ],
- },
- };
- describe('Prometheus Result Transformer', () => {
- describe('parse variants of "+Inf" and "-Inf" strings', () => {
- it('+Inf', () => {
- expect(parseSampleValue('+Inf')).toEqual(Number.POSITIVE_INFINITY);
- });
- it('Inf', () => {
- expect(parseSampleValue('Inf')).toEqual(Number.POSITIVE_INFINITY);
- });
- it('inf', () => {
- expect(parseSampleValue('inf')).toEqual(Number.POSITIVE_INFINITY);
- });
- it('+Infinity', () => {
- expect(parseSampleValue('+Infinity')).toEqual(Number.POSITIVE_INFINITY);
- });
- it('+infinity', () => {
- expect(parseSampleValue('+infinity')).toEqual(Number.POSITIVE_INFINITY);
- });
- it('infinity', () => {
- expect(parseSampleValue('infinity')).toEqual(Number.POSITIVE_INFINITY);
- });
- it('-Inf', () => {
- expect(parseSampleValue('-Inf')).toEqual(Number.NEGATIVE_INFINITY);
- });
- it('-inf', () => {
- expect(parseSampleValue('-inf')).toEqual(Number.NEGATIVE_INFINITY);
- });
- it('-Infinity', () => {
- expect(parseSampleValue('-Infinity')).toEqual(Number.NEGATIVE_INFINITY);
- });
- it('-infinity', () => {
- expect(parseSampleValue('-infinity')).toEqual(Number.NEGATIVE_INFINITY);
- });
- });
- describe('transformV2', () => {
- it('results with time_series format should be enriched with preferredVisualisationType', () => {
- const request = {
- targets: [
- {
- format: 'time_series',
- refId: 'A',
- },
- ],
- } as unknown as DataQueryRequest<PromQuery>;
- const response = {
- state: 'Done',
- data: [
- {
- fields: [],
- length: 2,
- name: 'ALERTS',
- refId: 'A',
- },
- ],
- } as unknown as DataQueryResponse;
- const series = transformV2(response, request, {});
- expect(series).toEqual({
- data: [{ fields: [], length: 2, meta: { preferredVisualisationType: 'graph' }, name: 'ALERTS', refId: 'A' }],
- state: 'Done',
- });
- });
- it('results with table format should be transformed to table dataFrames', () => {
- const request = {
- targets: [
- {
- format: 'table',
- refId: 'A',
- },
- ],
- } as unknown as DataQueryRequest<PromQuery>;
- const response = {
- state: 'Done',
- data: [
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'value',
- type: FieldType.number,
- values: [6, 5, 4],
- labels: { label1: 'value1', label2: 'value2' },
- },
- ],
- }),
- ],
- } as unknown as DataQueryResponse;
- const series = transformV2(response, request, {});
- expect(series.data[0].fields[0].name).toEqual('Time');
- expect(series.data[0].fields[1].name).toEqual('label1');
- expect(series.data[0].fields[2].name).toEqual('label2');
- expect(series.data[0].fields[3].name).toEqual('Value');
- expect(series.data[0].meta?.preferredVisualisationType).toEqual('table');
- });
- it('results with table format and multiple data frames should be transformed to 1 table dataFrame', () => {
- const request = {
- targets: [
- {
- format: 'table',
- refId: 'A',
- },
- ],
- } as unknown as DataQueryRequest<PromQuery>;
- const response = {
- state: 'Done',
- data: [
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'value',
- type: FieldType.number,
- values: [6, 5, 4],
- labels: { label1: 'value1', label2: 'value2' },
- },
- ],
- }),
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'time', type: FieldType.time, values: [2, 3, 7] },
- {
- name: 'value',
- type: FieldType.number,
- values: [2, 3, 7],
- labels: { label3: 'value3', label4: 'value4' },
- },
- ],
- }),
- ],
- } as unknown as DataQueryResponse;
- const series = transformV2(response, request, {});
- expect(series.data.length).toEqual(1);
- expect(series.data[0].fields[0].name).toEqual('Time');
- expect(series.data[0].fields[1].name).toEqual('label1');
- expect(series.data[0].fields[2].name).toEqual('label2');
- expect(series.data[0].fields[3].name).toEqual('label3');
- expect(series.data[0].fields[4].name).toEqual('label4');
- expect(series.data[0].fields[5].name).toEqual('Value');
- expect(series.data[0].meta?.preferredVisualisationType).toEqual('table');
- });
- it('results with table and time_series format should be correctly transformed', () => {
- const options = {
- targets: [
- {
- format: 'table',
- refId: 'A',
- },
- {
- format: 'time_series',
- refId: 'B',
- },
- ],
- } as unknown as DataQueryRequest<PromQuery>;
- const response = {
- state: 'Done',
- data: [
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'value',
- type: FieldType.number,
- values: [6, 5, 4],
- labels: { label1: 'value1', label2: 'value2' },
- },
- ],
- }),
- new MutableDataFrame({
- refId: 'B',
- fields: [
- { name: 'time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'value',
- type: FieldType.number,
- values: [6, 5, 4],
- labels: { label1: 'value1', label2: 'value2' },
- },
- ],
- }),
- ],
- } as unknown as DataQueryResponse;
- const series = transformV2(response, options, {});
- expect(series.data[0].fields.length).toEqual(2);
- expect(series.data[0].meta?.preferredVisualisationType).toEqual('graph');
- expect(series.data[1].fields.length).toEqual(4);
- expect(series.data[1].meta?.preferredVisualisationType).toEqual('table');
- });
- it('results with heatmap format should be correctly transformed', () => {
- const options = {
- targets: [
- {
- format: 'heatmap',
- refId: 'A',
- },
- ],
- } as unknown as DataQueryRequest<PromQuery>;
- const response = {
- state: 'Done',
- data: [
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'Time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'Value',
- type: FieldType.number,
- values: [10, 10, 0],
- labels: { le: '1' },
- },
- ],
- }),
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'Time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'Value',
- type: FieldType.number,
- values: [20, 10, 30],
- labels: { le: '2' },
- },
- ],
- }),
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'Time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'Value',
- type: FieldType.number,
- values: [30, 10, 40],
- labels: { le: '3' },
- },
- ],
- }),
- ],
- } as unknown as DataQueryResponse;
- const series = transformV2(response, options, {});
- expect(series.data[0].fields.length).toEqual(4);
- expect(series.data[0].fields[1].values.toArray()).toEqual([10, 10, 0]);
- expect(series.data[0].fields[2].values.toArray()).toEqual([10, 0, 30]);
- expect(series.data[0].fields[3].values.toArray()).toEqual([10, 0, 10]);
- });
- it('Retains exemplar frames when data returned is a heatmap', () => {
- const options = {
- targets: [
- {
- format: 'heatmap',
- refId: 'A',
- },
- ],
- } as unknown as DataQueryRequest<PromQuery>;
- const response = {
- state: 'Done',
- data: [
- new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'Time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'Value',
- type: FieldType.number,
- values: [10, 10, 0],
- labels: { le: '1' },
- },
- ],
- }),
- new MutableDataFrame({
- refId: 'A',
- name: 'exemplar',
- meta: {
- custom: {
- resultType: 'exemplar',
- },
- },
- fields: [
- { name: 'Time', type: FieldType.time, values: [6, 5, 4, 3, 2, 1] },
- {
- name: 'Value',
- type: FieldType.number,
- values: [30, 10, 40, 90, 14, 21],
- labels: { le: '6' },
- },
- {
- name: 'Test',
- type: FieldType.string,
- values: ['hello', 'doctor', 'name', 'continue', 'yesterday', 'tomorrow'],
- labels: { le: '6' },
- },
- ],
- }),
- ],
- } as unknown as DataQueryResponse;
- const series = transformV2(response, options, {});
- expect(series.data[0].fields.length).toEqual(2);
- expect(series.data.length).toEqual(2);
- expect(series.data[1].fields[2].values.toArray()).toEqual([
- 'hello',
- 'doctor',
- 'name',
- 'continue',
- 'yesterday',
- 'tomorrow',
- ]);
- expect(series.data[1].fields.length).toEqual(3);
- });
- });
- describe('transformDFToTable', () => {
- it('transforms dataFrame with response length 1 to table dataFrame', () => {
- const df = new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'value',
- type: FieldType.number,
- values: [6, 5, 4],
- labels: { label1: 'value1', label2: 'value2' },
- },
- ],
- });
- const tableDf = transformDFToTable([df])[0];
- expect(tableDf.fields.length).toBe(4);
- expect(tableDf.fields[0].name).toBe('Time');
- expect(tableDf.fields[1].name).toBe('label1');
- expect(tableDf.fields[1].values.get(0)).toBe('value1');
- expect(tableDf.fields[2].name).toBe('label2');
- expect(tableDf.fields[2].values.get(0)).toBe('value2');
- expect(tableDf.fields[3].name).toBe('Value');
- });
- it('transforms dataFrame with response length 2 to table dataFrame', () => {
- const df = new MutableDataFrame({
- refId: 'A',
- fields: [
- { name: 'time', type: FieldType.time, values: [6, 5, 4] },
- {
- name: 'value',
- type: FieldType.number,
- values: [6, 5, 4],
- labels: { label1: 'value1', label2: 'value2' },
- },
- ],
- });
- const tableDf = transformDFToTable([df])[0];
- expect(tableDf.fields.length).toBe(4);
- expect(tableDf.fields[0].name).toBe('Time');
- expect(tableDf.fields[1].name).toBe('label1');
- expect(tableDf.fields[1].values.get(0)).toBe('value1');
- expect(tableDf.fields[2].name).toBe('label2');
- expect(tableDf.fields[2].values.get(0)).toBe('value2');
- expect(tableDf.fields[3].name).toBe('Value');
- });
- });
- describe('transform', () => {
- const options: any = { target: {}, query: {} };
- describe('When nothing is returned', () => {
- it('should return empty array', () => {
- const response = {
- status: 'success',
- data: {
- resultType: '',
- result: null,
- },
- };
- const series = transform({ data: response } as any, options);
- expect(series).toEqual([]);
- });
- it('should return empty array', () => {
- const response = {
- status: 'success',
- data: {
- resultType: '',
- result: null,
- },
- };
- const result = transform({ data: response } as any, { ...options, target: { format: 'table' } });
- expect(result).toHaveLength(0);
- });
- });
- describe('When resultFormat is table', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'matrix',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob' },
- values: [
- [1443454528, '3846'],
- [1443454530, '3848'],
- ],
- },
- {
- metric: {
- __name__: 'test2',
- instance: 'localhost:8080',
- job: 'otherjob',
- },
- values: [
- [1443454529, '3847'],
- [1443454531, '3849'],
- ],
- },
- ],
- },
- };
- it('should return data frame', () => {
- const result = transform({ data: response } as any, {
- ...options,
- target: {
- responseListLength: 0,
- refId: 'A',
- format: 'table',
- },
- });
- expect(result[0].fields[0].values.toArray()).toEqual([
- 1443454528000, 1443454530000, 1443454529000, 1443454531000,
- ]);
- expect(result[0].fields[0].name).toBe('Time');
- expect(result[0].fields[0].type).toBe(FieldType.time);
- expect(result[0].fields[1].values.toArray()).toEqual(['test', 'test', 'test2', 'test2']);
- expect(result[0].fields[1].name).toBe('__name__');
- expect(result[0].fields[1].config.filterable).toBe(true);
- expect(result[0].fields[1].type).toBe(FieldType.string);
- expect(result[0].fields[2].values.toArray()).toEqual(['', '', 'localhost:8080', 'localhost:8080']);
- expect(result[0].fields[2].name).toBe('instance');
- expect(result[0].fields[2].type).toBe(FieldType.string);
- expect(result[0].fields[3].values.toArray()).toEqual(['testjob', 'testjob', 'otherjob', 'otherjob']);
- expect(result[0].fields[3].name).toBe('job');
- expect(result[0].fields[3].type).toBe(FieldType.string);
- expect(result[0].fields[4].values.toArray()).toEqual([3846, 3848, 3847, 3849]);
- expect(result[0].fields[4].name).toEqual('Value');
- expect(result[0].fields[4].type).toBe(FieldType.number);
- expect(result[0].refId).toBe('A');
- });
- it('should include refId if response count is more than 2', () => {
- const result = transform({ data: response } as any, {
- ...options,
- target: {
- refId: 'B',
- format: 'table',
- },
- responseListLength: 2,
- });
- expect(result[0].fields[4].name).toEqual('Value #B');
- });
- });
- describe('When resultFormat is table and instant = true', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'vector',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob' },
- value: [1443454528, '3846'],
- },
- ],
- },
- };
- it('should return data frame', () => {
- const result = transform({ data: response } as any, { ...options, target: { format: 'table' } });
- expect(result[0].fields[0].values.toArray()).toEqual([1443454528000]);
- expect(result[0].fields[0].name).toBe('Time');
- expect(result[0].fields[1].values.toArray()).toEqual(['test']);
- expect(result[0].fields[1].name).toBe('__name__');
- expect(result[0].fields[2].values.toArray()).toEqual(['testjob']);
- expect(result[0].fields[2].name).toBe('job');
- expect(result[0].fields[3].values.toArray()).toEqual([3846]);
- expect(result[0].fields[3].name).toEqual('Value');
- });
- it('should return le label values parsed as numbers', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'vector',
- result: [
- {
- metric: { le: '102' },
- value: [1594908838, '0'],
- },
- ],
- },
- };
- const result = transform({ data: response } as any, { ...options, target: { format: 'table' } });
- expect(result[0].fields[1].values.toArray()).toEqual([102]);
- expect(result[0].fields[1].type).toEqual(FieldType.number);
- });
- });
- describe('When instant = true', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'vector',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob' },
- value: [1443454528, '3846'],
- },
- ],
- },
- };
- it('should return data frame', () => {
- const result: DataFrame[] = transform({ data: response } as any, { ...options, query: { instant: true } });
- expect(result[0].name).toBe('test{job="testjob"}');
- });
- });
- describe('When resultFormat is heatmap', () => {
- const getResponse = (result: any) => ({
- status: 'success',
- data: {
- resultType: 'matrix',
- result,
- },
- });
- const options = {
- format: 'heatmap',
- start: 1445000010,
- end: 1445000030,
- legendFormat: '{{le}}',
- };
- it('should convert cumulative histogram to regular', () => {
- const response = getResponse([
- {
- metric: { __name__: 'test', job: 'testjob', le: '1' },
- values: [
- [1445000010, '10'],
- [1445000020, '10'],
- [1445000030, '0'],
- ],
- },
- {
- metric: { __name__: 'test', job: 'testjob', le: '2' },
- values: [
- [1445000010, '20'],
- [1445000020, '10'],
- [1445000030, '30'],
- ],
- },
- {
- metric: { __name__: 'test', job: 'testjob', le: '3' },
- values: [
- [1445000010, '30'],
- [1445000020, '10'],
- [1445000030, '40'],
- ],
- },
- ]);
- const result = transform({ data: response } as any, { query: options, target: options } as any);
- expect(result[0].fields[0].values.toArray()).toEqual([1445000010000, 1445000020000, 1445000030000]);
- expect(result[0].fields[1].values.toArray()).toEqual([10, 10, 0]);
- expect(result[0].fields[2].values.toArray()).toEqual([10, 0, 30]);
- expect(result[0].fields[3].values.toArray()).toEqual([10, 0, 10]);
- });
- it('should handle missing datapoints', () => {
- const response = getResponse([
- {
- metric: { __name__: 'test', job: 'testjob', le: '1' },
- values: [
- [1445000010, '1'],
- [1445000020, '2'],
- ],
- },
- {
- metric: { __name__: 'test', job: 'testjob', le: '2' },
- values: [
- [1445000010, '2'],
- [1445000020, '5'],
- [1445000030, '1'],
- ],
- },
- {
- metric: { __name__: 'test', job: 'testjob', le: '3' },
- values: [
- [1445000010, '3'],
- [1445000020, '7'],
- ],
- },
- ]);
- const result = transform({ data: response } as any, { query: options, target: options } as any);
- expect(result[0].fields[1].values.toArray()).toEqual([1, 2]);
- expect(result[0].fields[2].values.toArray()).toEqual([1, 3, 1]);
- expect(result[0].fields[3].values.toArray()).toEqual([1, 2]);
- });
- });
- describe('When the response is a matrix', () => {
- it('should have labels with the value field', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'matrix',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob', instance: 'testinstance' },
- values: [
- [0, '10'],
- [1, '10'],
- [2, '0'],
- ],
- },
- ],
- },
- };
- const result: DataFrame[] = transform({ data: response } as any, {
- ...options,
- });
- expect(result[0].fields[1].labels).toBeDefined();
- expect(result[0].fields[1].labels?.instance).toBe('testinstance');
- expect(result[0].fields[1].labels?.job).toBe('testjob');
- });
- it('should transform into a data frame', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'matrix',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob' },
- values: [
- [0, '10'],
- [1, '10'],
- [2, '0'],
- ],
- },
- ],
- },
- };
- const result: DataFrame[] = transform({ data: response } as any, {
- ...options,
- query: {
- start: 0,
- end: 2,
- },
- });
- expect(result[0].fields[0].values.toArray()).toEqual([0, 1000, 2000]);
- expect(result[0].fields[1].values.toArray()).toEqual([10, 10, 0]);
- expect(result[0].name).toBe('test{job="testjob"}');
- });
- it('should fill null values', () => {
- const result = transform({ data: matrixResponse } as any, {
- ...options,
- query: { step: 1, start: 0, end: 2 },
- });
- expect(result[0].fields[0].values.toArray()).toEqual([0, 1000, 2000]);
- expect(result[0].fields[1].values.toArray()).toEqual([null, 10, 0]);
- });
- it('should use __name__ label as series name', () => {
- const result = transform({ data: matrixResponse } as any, {
- ...options,
- query: {
- step: 1,
- start: 0,
- end: 2,
- },
- });
- expect(result[0].name).toEqual('test{job="testjob"}');
- });
- it('should use query as series name when __name__ is not available and metric is empty', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'matrix',
- result: [
- {
- metric: {},
- values: [[0, '10']],
- },
- ],
- },
- };
- const expr = 'histogram_quantile(0.95, sum(rate(tns_request_duration_seconds_bucket[5m])) by (le))';
- const result = transform({ data: response } as any, {
- ...options,
- query: {
- step: 1,
- start: 0,
- end: 2,
- expr,
- },
- });
- expect(result[0].name).toEqual(expr);
- });
- it('should set frame name to undefined if no __name__ label but there are other labels', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'matrix',
- result: [
- {
- metric: { job: 'testjob' },
- values: [
- [1, '10'],
- [2, '0'],
- ],
- },
- ],
- },
- };
- const result = transform({ data: response } as any, {
- ...options,
- query: {
- step: 1,
- start: 0,
- end: 2,
- },
- });
- expect(result[0].name).toBe('{job="testjob"}');
- });
- it('should not set displayName for ValueFields', () => {
- const result = transform({ data: matrixResponse } as any, options);
- expect(result[0].fields[1].config.displayName).toBeUndefined();
- expect(result[0].fields[1].config.displayNameFromDS).toBe('test{job="testjob"}');
- });
- it('should align null values with step', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'matrix',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob' },
- values: [
- [4, '10'],
- [8, '10'],
- ],
- },
- ],
- },
- };
- const result = transform({ data: response } as any, { ...options, query: { step: 2, start: 0, end: 8 } });
- expect(result[0].fields[0].values.toArray()).toEqual([0, 2000, 4000, 6000, 8000]);
- expect(result[0].fields[1].values.toArray()).toEqual([null, null, 10, null, 10]);
- });
- });
- describe('When infinity values are returned', () => {
- describe('When resultType is scalar', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'scalar',
- result: [1443454528, '+Inf'],
- },
- };
- it('should correctly parse values', () => {
- const result: DataFrame[] = transform({ data: response } as any, {
- ...options,
- target: { format: 'table' },
- });
- expect(result[0].fields[1].values.toArray()).toEqual([Number.POSITIVE_INFINITY]);
- });
- });
- describe('When resultType is vector', () => {
- const response = {
- status: 'success',
- data: {
- resultType: 'vector',
- result: [
- {
- metric: { __name__: 'test', job: 'testjob' },
- value: [1443454528, '+Inf'],
- },
- {
- metric: { __name__: 'test', job: 'testjob' },
- value: [1443454528, '-Inf'],
- },
- ],
- },
- };
- describe('When format is table', () => {
- it('should correctly parse values', () => {
- const result: DataFrame[] = transform({ data: response } as any, {
- ...options,
- target: { format: 'table' },
- });
- expect(result[0].fields[3].values.toArray()).toEqual([Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]);
- });
- });
- });
- });
- const exemplarsResponse = {
- status: 'success',
- data: [
- {
- seriesLabels: { __name__: 'test' },
- exemplars: [
- {
- timestamp: 1610449069.957,
- labels: { traceID: '5020b5bc45117f07' },
- value: 0.002074123,
- },
- ],
- },
- ],
- };
- describe('When the response is exemplar data', () => {
- it('should return as an data frame with a dataTopic annotations', () => {
- const result = transform({ data: exemplarsResponse } as any, options);
- expect(result[0].meta?.dataTopic).toBe('annotations');
- expect(result[0].fields.length).toBe(4); // __name__, traceID, Time, Value
- expect(result[0].length).toBe(1);
- });
- it('should return with an empty array when data is empty', () => {
- const result = transform(
- {
- data: {
- status: 'success',
- data: [],
- },
- } as any,
- options
- );
- expect(result).toHaveLength(0);
- });
- it('should remove exemplars that are too close to each other', () => {
- const response = {
- status: 'success',
- data: [
- {
- exemplars: [
- {
- timestamp: 1610449070.0,
- value: 5,
- },
- {
- timestamp: 1610449070.0,
- value: 1,
- },
- {
- timestamp: 1610449070.5,
- value: 13,
- },
- {
- timestamp: 1610449070.3,
- value: 20,
- },
- ],
- },
- ],
- };
- /**
- * the standard deviation for the above values is 8.4 this means that we show the highest
- * value (20) and then the next value should be 2 times the standard deviation which is 1
- **/
- const result = transform({ data: response } as any, options);
- expect(result[0].length).toBe(2);
- });
- describe('data link', () => {
- it('should be added to the field if found with url', () => {
- const result = transform({ data: exemplarsResponse } as any, {
- ...options,
- exemplarTraceIdDestinations: [{ name: 'traceID', url: 'http://localhost' }],
- });
- expect(result[0].fields.some((f) => f.config.links?.length)).toBe(true);
- });
- it('should be added to the field if found with internal link', () => {
- const result = transform({ data: exemplarsResponse } as any, {
- ...options,
- exemplarTraceIdDestinations: [{ name: 'traceID', datasourceUid: 'jaeger' }],
- });
- expect(result[0].fields.some((f) => f.config.links?.length)).toBe(true);
- });
- it('should not add link if exemplarTraceIdDestinations is not configured', () => {
- const result = transform({ data: exemplarsResponse } as any, options);
- expect(result[0].fields.some((f) => f.config.links?.length)).toBe(false);
- });
- });
- });
- });
- });
|