Commit 05644e70 by Ivana Huckova Committed by GitHub

Loki: Fix error when some queries return zero results (#28645)

* Fix logSeriesToLogsModel when some data frames have empty fields

* Update test

* Update public/app/core/logs_model.ts

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
parent b0fbde3a
...@@ -700,6 +700,78 @@ describe('logSeriesToLogsModel', () => { ...@@ -700,6 +700,78 @@ describe('logSeriesToLogsModel', () => {
expect(logSeriesToLogsModel(logSeries)).toMatchObject(metaData); expect(logSeriesToLogsModel(logSeries)).toMatchObject(metaData);
}); });
it('should return correct metaData when some data frames have empty fields', () => {
const logSeries: DataFrame[] = [
toDataFrame({
fields: [
{
name: 'ts',
type: FieldType.time,
values: ['1970-01-01T00:00:01Z', '1970-02-01T00:00:01Z', '1970-03-01T00:00:01Z'],
},
{
name: 'line',
type: FieldType.string,
values: ['WARN boooo 0', 'WARN boooo 1', 'WARN boooo 2'],
labels: {
foo: 'bar',
level: 'dbug',
},
},
{
name: 'id',
type: FieldType.string,
values: ['0', '1', '2'],
},
],
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',
},
}),
toDataFrame({
fields: [],
length: 0,
refId: 'B',
meta: {
searchWords: ['test'],
limit: 1000,
stats: [{ displayName: 'Summary: total bytes processed', value: 97048, unit: 'decbytes' }],
custom: { lokiQueryStatKey: 'Summary: total bytes processed' },
preferredVisualisationType: 'logs',
},
}),
];
const logsModel = dataFrameToLogsModel(logSeries, 0, 'utc');
expect(logsModel.meta).toMatchObject([
{ kind: 2, label: 'Common labels', value: { foo: 'bar', level: 'dbug' } },
{ kind: 1, label: 'Limit', value: '2000 (3 returned)' },
{ kind: 1, label: 'Total bytes processed', value: '194 kB' },
]);
expect(logsModel.rows).toHaveLength(3);
expect(logsModel.rows).toMatchObject([
{
entry: 'WARN boooo 0',
labels: { foo: 'bar' },
logLevel: LogLevel.debug,
},
{
entry: 'WARN boooo 1',
labels: { foo: 'bar' },
logLevel: LogLevel.debug,
},
{
entry: 'WARN boooo 2',
labels: { foo: 'bar' },
logLevel: LogLevel.debug,
},
]);
});
}); });
describe('getSeriesProperties()', () => { describe('getSeriesProperties()', () => {
......
...@@ -270,6 +270,7 @@ function separateLogsAndMetrics(dataFrames: DataFrame[]) { ...@@ -270,6 +270,7 @@ function separateLogsAndMetrics(dataFrames: DataFrame[]) {
const logSeries: DataFrame[] = []; const logSeries: DataFrame[] = [];
for (const dataFrame of dataFrames) { for (const dataFrame of dataFrames) {
// We want to show meta stats even if no result was returned. That's why we are pushing also data frames with no fields.
if (isLogsData(dataFrame) || !dataFrame.fields.length) { if (isLogsData(dataFrame) || !dataFrame.fields.length) {
logSeries.push(dataFrame); logSeries.push(dataFrame);
continue; continue;
...@@ -306,8 +307,12 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi ...@@ -306,8 +307,12 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi
// Find the fields we care about and collect all labels // Find the fields we care about and collect all labels
let allSeries: LogFields[] = []; let allSeries: LogFields[] = [];
if (hasFields(logSeries)) { // We are sometimes passing data frames with no fields because we want to calculate correct meta stats.
allSeries = logSeries.map(series => { // Therefore we need to filter out series with no fields. These series are used only for meta stats calculation.
const seriesWithFields = logSeries.filter(series => series.fields.length);
if (seriesWithFields.length) {
allSeries = seriesWithFields.map(series => {
const fieldCache = new FieldCache(series); const fieldCache = new FieldCache(series);
const stringField = fieldCache.getFirstFieldOfType(FieldType.string); const stringField = fieldCache.getFirstFieldOfType(FieldType.string);
...@@ -463,10 +468,6 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi ...@@ -463,10 +468,6 @@ 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 { function getIdField(fieldCache: FieldCache): FieldWithIndex | undefined {
const idFieldNames = ['id']; const idFieldNames = ['id'];
for (const fieldName of idFieldNames) { for (const fieldName of idFieldNames) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment