Explore: Fixes so Show context shows results again (#18675)

* Fix: Fixes so Show context shows results again
Fixes: #18656

* Refactor: Removes unused import that made it thrugh the pre-commit somehow
This commit is contained in:
Hugo Häggmark 2019-08-22 11:10:20 +02:00 committed by GitHub
parent 0ea3444d1b
commit 774b7267df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 131 additions and 14 deletions

View File

@ -1,4 +1,4 @@
import { FieldType, DataFrameDTO, FieldDTO } from '../types/index';
import { DataFrameDTO, FieldDTO, FieldType } from '../types';
import { DataFrameHelper } from './dataFrameHelper';
describe('dataFrameHelper', () => {
@ -87,3 +87,29 @@ describe('FieldCache', () => {
expect(fieldCache.getFieldByName('null')).toBeUndefined();
});
});
describe('reverse', () => {
describe('when called with a DataFrame', () => {
it('then it should reverse the order of values in all fields', () => {
const frame: DataFrameDTO = {
fields: [
{ name: 'time', type: FieldType.time, values: [100, 200, 300] },
{ name: 'name', type: FieldType.string, values: ['a', 'b', 'c'] },
{ name: 'value', type: FieldType.number, values: [1, 2, 3] },
],
};
const helper = new DataFrameHelper(frame);
expect(helper.getFieldByName('time')!.values.toArray()).toEqual([100, 200, 300]);
expect(helper.getFieldByName('name')!.values.toArray()).toEqual(['a', 'b', 'c']);
expect(helper.getFieldByName('value')!.values.toArray()).toEqual([1, 2, 3]);
helper.reverse();
expect(helper.getFieldByName('time')!.values.toArray()).toEqual([300, 200, 100]);
expect(helper.getFieldByName('name')!.values.toArray()).toEqual(['c', 'b', 'a']);
expect(helper.getFieldByName('value')!.values.toArray()).toEqual([3, 2, 1]);
});
});
});

View File

@ -44,10 +44,7 @@ export class DataFrameHelper implements DataFrame {
*/
reverse() {
for (const f of this.fields) {
if (isArray(f.values)) {
const arr = f.values as any[];
arr.reverse();
}
f.values.toArray().reverse();
}
}

View File

@ -0,0 +1,74 @@
import { DataFrameHelper, FieldType, LogRowModel } from '@grafana/data';
import { getRowContexts } from './LogRowContextProvider';
describe('getRowContexts', () => {
describe('when called with a DataFrame and results are returned', () => {
it('then the result should be in correct format', async () => {
const firstResult = new DataFrameHelper({
refId: 'B',
labels: {},
fields: [
{ name: 'ts', type: FieldType.time, values: [3, 2, 1] },
{ name: 'line', type: FieldType.string, values: ['3', '2', '1'] },
],
});
const secondResult = new DataFrameHelper({
refId: 'B',
labels: {},
fields: [
{ name: 'ts', type: FieldType.time, values: [6, 5, 4] },
{ name: 'line', type: FieldType.string, values: ['6', '5', '4'] },
],
});
const row: LogRowModel = {
entry: '4',
labels: null,
hasAnsi: false,
raw: '4',
logLevel: null,
timeEpochMs: 4,
timeFromNow: '',
timeLocal: '',
timeUtc: '',
timestamp: '4',
};
const getRowContext = jest
.fn()
.mockResolvedValueOnce({ data: [firstResult] })
.mockResolvedValueOnce({ data: [secondResult] });
const result = await getRowContexts(getRowContext, row, 10);
expect(result).toEqual({ data: [[['3', '2', '1']], [['6', '5', '4']]], errors: [null, null] });
});
});
describe('when called with a DataFrame and errors occur', () => {
it('then the result should be in correct format', async () => {
const firstError = new Error('Error 1');
const secondError = new Error('Error 2');
const row: LogRowModel = {
entry: '4',
labels: null,
hasAnsi: false,
raw: '4',
logLevel: null,
timeEpochMs: 4,
timeFromNow: '',
timeLocal: '',
timeUtc: '',
timestamp: '4',
};
const getRowContext = jest
.fn()
.mockRejectedValueOnce(firstError)
.mockRejectedValueOnce(secondError);
const result = await getRowContexts(getRowContext, row, 10);
expect(result).toEqual({ data: [[], []], errors: ['Error 1', 'Error 2'] });
});
});
});

View File

@ -1,5 +1,5 @@
import { DataQueryResponse, DataQueryError } from '@grafana/ui';
import { LogRowModel } from '@grafana/data';
import { LogRowModel, toDataFrame, Field } from '@grafana/data';
import { useState, useEffect } from 'react';
import flatten from 'lodash/flatten';
import useAsync from 'react-use/lib/useAsync';
@ -47,19 +47,39 @@ export const getRowContexts = async (
const results: Array<DataQueryResponse | DataQueryError> = await Promise.all(promises.map(p => p.catch(e => e)));
return {
data: results.map((result, index) => {
data: results.map(result => {
const dataResult: DataQueryResponse = result as DataQueryResponse;
if (!dataResult.data) {
return [];
}
// We need to filter out the row we're basing our search from because of how start/end params work in Loki API
// see https://github.com/grafana/loki/issues/597#issuecomment-506408980
// the alternative to create our own add 1 nanosecond method to the a timestamp string would be quite complex
return dataResult.data.map(series => {
const filteredRows = series.rows.filter((r: any) => r[0] !== row.timestamp);
return filteredRows.map((row: any) => row[1]);
});
const data: any[] = [];
for (let index = 0; index < dataResult.data.length; index++) {
const dataFrame = toDataFrame(dataResult.data[index]);
const timestampField: Field<string> = dataFrame.fields.filter(field => field.name === 'ts')[0];
for (let fieldIndex = 0; fieldIndex < timestampField.values.length; fieldIndex++) {
const timestamp = timestampField.values.get(fieldIndex);
// We need to filter out the row we're basing our search from because of how start/end params work in Loki API
// see https://github.com/grafana/loki/issues/597#issuecomment-506408980
// the alternative to create our own add 1 nanosecond method to the a timestamp string would be quite complex
if (timestamp === row.timestamp) {
continue;
}
const lineField: Field<string> = dataFrame.fields.filter(field => field.name === 'line')[0];
const line = lineField.values.get(fieldIndex); // assuming that both fields have same length
if (data.length === 0) {
data[0] = [line];
} else {
data[0].push(line);
}
}
}
return data;
}),
errors: results.map(result => {
const errorResult: DataQueryError = result as DataQueryError;