Explore: show meta data when available (#25798)

* Return valid metadata even if data is empty

* Make sure fields is not accessed when there is no data

* Meta Info should depend only on meta data

* Refactor condition for better reading

* Change data to empty array for better condition handling

* Remove unecessary checks

* Add test for showing metaData even when data is empty
This commit is contained in:
Besart Berisha
2020-07-17 10:30:27 +02:00
committed by GitHub
parent 7a11ed91cb
commit 373e869652
6 changed files with 89 additions and 31 deletions

View File

@@ -8,7 +8,7 @@ import {
MutableDataFrame,
toDataFrame,
} from '@grafana/data';
import { dataFrameToLogsModel, dedupLogRows, getSeriesProperties } from './logs_model';
import { dataFrameToLogsModel, dedupLogRows, getSeriesProperties, logSeriesToLogsModel } from './logs_model';
describe('dedupLogRows()', () => {
test('should return rows as is when dedup is set to none', () => {
@@ -596,6 +596,37 @@ describe('dataFrameToLogsModel', () => {
});
});
describe('logSeriesToLogsModel', () => {
it('should return correct metaData even if the data is empty', () => {
const logSeries: DataFrame[] = [
{
fields: [],
length: 0,
refId: 'A',
meta: {
searchWords: ['test'],
limit: 1000,
stats: [{ displayName: 'Summary: total bytes processed', value: 97048, unit: 'decbytes' }],
custom: { lokiQueryStatKey: 'Summary: total bytes processed' },
preferredVisualisationType: 'logs',
},
},
];
const metaData = {
hasUniqueLabels: false,
meta: [
{ label: 'Limit', value: '1000 (0 returned)', kind: 1 },
{ label: 'Total bytes processed', value: '97 kB', kind: 1 },
],
rows: [],
};
expect(logSeriesToLogsModel(logSeries)).toMatchObject(metaData);
});
});
describe('getSeriesProperties()', () => {
it('sets a minimum bucket size', () => {
const result = getSeriesProperties([], 2, undefined, 3, 123);

View File

@@ -269,7 +269,7 @@ function separateLogsAndMetrics(dataFrames: DataFrame[]) {
const logSeries: DataFrame[] = [];
for (const dataFrame of dataFrames) {
if (isLogsData(dataFrame)) {
if (isLogsData(dataFrame) || !dataFrame.fields.length) {
logSeries.push(dataFrame);
continue;
}
@@ -303,23 +303,29 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi
const allLabels: Labels[] = [];
// Find the fields we care about and collect all labels
const allSeries: LogFields[] = logSeries.map(series => {
const fieldCache = new FieldCache(series);
const stringField = fieldCache.getFirstFieldOfType(FieldType.string);
if (stringField?.labels) {
allLabels.push(stringField.labels);
}
return {
series,
timeField: fieldCache.getFirstFieldOfType(FieldType.time),
timeNanosecondField: fieldCache.hasFieldWithNameAndType('tsNs', FieldType.time)
? fieldCache.getFieldByName('tsNs')
: undefined,
stringField,
logLevelField: fieldCache.getFieldByName('level'),
idField: getIdField(fieldCache),
} as LogFields;
});
let allSeries: LogFields[] = [];
if (hasFields(logSeries)) {
allSeries = logSeries.map(series => {
const fieldCache = new FieldCache(series);
const stringField = fieldCache.getFirstFieldOfType(FieldType.string);
if (stringField?.labels) {
allLabels.push(stringField.labels);
}
return {
series,
timeField: fieldCache.getFirstFieldOfType(FieldType.time),
timeNanosecondField: fieldCache.hasFieldWithNameAndType('tsNs', FieldType.time)
? fieldCache.getFieldByName('tsNs')
: undefined,
stringField,
logLevelField: fieldCache.getFieldByName('level'),
idField: getIdField(fieldCache),
} as LogFields;
});
}
const commonLabels = allLabels.length > 0 ? findCommonLabels(allLabels) : {};
@@ -445,6 +451,10 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi
};
}
function hasFields(logSeries: DataFrame[]): boolean {
return logSeries.some(series => series.fields.length);
}
function getIdField(fieldCache: FieldCache): FieldWithIndex | undefined {
const idFieldNames = ['id'];
for (const fieldName of idFieldNames) {