mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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>
This commit is contained in:
parent
b0fbde3a0c
commit
05644e7042
@ -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[]) {
|
|||||||
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
|
|||||||
// 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
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user