mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
loki: query splitting: labels-based frame matching (#66677)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ArrayVector,
|
ArrayVector,
|
||||||
DataFrame,
|
DataFrame,
|
||||||
|
DataFrameType,
|
||||||
DataSourceInstanceSettings,
|
DataSourceInstanceSettings,
|
||||||
DataSourceSettings,
|
DataSourceSettings,
|
||||||
FieldType,
|
FieldType,
|
||||||
@@ -151,6 +152,9 @@ export function getMockFrames() {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
|
custom: {
|
||||||
|
frameType: 'LabeledTimeValues',
|
||||||
|
},
|
||||||
stats: [
|
stats: [
|
||||||
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 11 },
|
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 11 },
|
||||||
{ displayName: 'Ingester: total reached', value: 1 },
|
{ displayName: 'Ingester: total reached', value: 1 },
|
||||||
@@ -198,6 +202,9 @@ export function getMockFrames() {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
|
custom: {
|
||||||
|
frameType: 'LabeledTimeValues',
|
||||||
|
},
|
||||||
stats: [
|
stats: [
|
||||||
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 22 },
|
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 22 },
|
||||||
{ displayName: 'Ingester: total reached', value: 2 },
|
{ displayName: 'Ingester: total reached', value: 2 },
|
||||||
@@ -220,9 +227,13 @@ export function getMockFrames() {
|
|||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
config: {},
|
config: {},
|
||||||
values: new ArrayVector([5, 4]),
|
values: new ArrayVector([5, 4]),
|
||||||
|
labels: {
|
||||||
|
level: 'debug',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
|
type: DataFrameType.TimeSeriesMulti,
|
||||||
stats: [
|
stats: [
|
||||||
{ displayName: 'Ingester: total reached', value: 1 },
|
{ displayName: 'Ingester: total reached', value: 1 },
|
||||||
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 11 },
|
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 11 },
|
||||||
@@ -245,9 +256,13 @@ export function getMockFrames() {
|
|||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
config: {},
|
config: {},
|
||||||
values: new ArrayVector([6, 7]),
|
values: new ArrayVector([6, 7]),
|
||||||
|
labels: {
|
||||||
|
level: 'debug',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
|
type: DataFrameType.TimeSeriesMulti,
|
||||||
stats: [
|
stats: [
|
||||||
{ displayName: 'Ingester: total reached', value: 2 },
|
{ displayName: 'Ingester: total reached', value: 2 },
|
||||||
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 22 },
|
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 22 },
|
||||||
@@ -271,9 +286,13 @@ export function getMockFrames() {
|
|||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
config: {},
|
config: {},
|
||||||
values: new ArrayVector([6, 7]),
|
values: new ArrayVector([6, 7]),
|
||||||
|
labels: {
|
||||||
|
level: 'error',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
|
type: DataFrameType.TimeSeriesMulti,
|
||||||
stats: [
|
stats: [
|
||||||
{ displayName: 'Ingester: total reached', value: 2 },
|
{ displayName: 'Ingester: total reached', value: 2 },
|
||||||
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 33 },
|
{ displayName: 'Summary: total bytes processed', unit: 'decbytes', value: 33 },
|
||||||
|
|||||||
@@ -191,6 +191,9 @@ describe('combineResponses', () => {
|
|||||||
],
|
],
|
||||||
length: 4,
|
length: 4,
|
||||||
meta: {
|
meta: {
|
||||||
|
custom: {
|
||||||
|
frameType: 'LabeledTimeValues',
|
||||||
|
},
|
||||||
stats: [
|
stats: [
|
||||||
{
|
{
|
||||||
displayName: 'Summary: total bytes processed',
|
displayName: 'Summary: total bytes processed',
|
||||||
@@ -228,10 +231,14 @@ describe('combineResponses', () => {
|
|||||||
name: 'Value',
|
name: 'Value',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
values: new ArrayVector([6, 7, 5, 4]),
|
values: new ArrayVector([6, 7, 5, 4]),
|
||||||
|
labels: {
|
||||||
|
level: 'debug',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
length: 4,
|
length: 4,
|
||||||
meta: {
|
meta: {
|
||||||
|
type: 'timeseries-multi',
|
||||||
stats: [
|
stats: [
|
||||||
{
|
{
|
||||||
displayName: 'Summary: total bytes processed',
|
displayName: 'Summary: total bytes processed',
|
||||||
@@ -269,10 +276,14 @@ describe('combineResponses', () => {
|
|||||||
name: 'Value',
|
name: 'Value',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
values: new ArrayVector([6, 7, 5, 4]),
|
values: new ArrayVector([6, 7, 5, 4]),
|
||||||
|
labels: {
|
||||||
|
level: 'debug',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
length: 4,
|
length: 4,
|
||||||
meta: {
|
meta: {
|
||||||
|
type: 'timeseries-multi',
|
||||||
stats: [
|
stats: [
|
||||||
{
|
{
|
||||||
displayName: 'Summary: total bytes processed',
|
displayName: 'Summary: total bytes processed',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ArrayVector,
|
ArrayVector,
|
||||||
DataFrame,
|
DataFrame,
|
||||||
|
DataFrameType,
|
||||||
DataQueryResponse,
|
DataQueryResponse,
|
||||||
DataQueryResponseData,
|
DataQueryResponseData,
|
||||||
Field,
|
Field,
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
isValidGoDuration,
|
isValidGoDuration,
|
||||||
Labels,
|
Labels,
|
||||||
QueryResultMetaStat,
|
QueryResultMetaStat,
|
||||||
|
shallowCompare,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
import { isBytesString } from './languageUtils';
|
import { isBytesString } from './languageUtils';
|
||||||
@@ -123,7 +125,38 @@ function shouldCombine(frame1: DataFrame, frame2: DataFrame): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame1.name === frame2.name;
|
const frameType1 = frame1.meta?.type;
|
||||||
|
const frameType2 = frame2.meta?.type;
|
||||||
|
|
||||||
|
if (frameType1 !== frameType2) {
|
||||||
|
// we do not join things that have a different type
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// metric range query data
|
||||||
|
if (frameType1 === DataFrameType.TimeSeriesMulti) {
|
||||||
|
const field1 = frame1.fields.find((f) => f.type === FieldType.number);
|
||||||
|
const field2 = frame2.fields.find((f) => f.type === FieldType.number);
|
||||||
|
if (field1 === undefined || field2 === undefined) {
|
||||||
|
// should never happen
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shallowCompare(field1.labels ?? {}, field2.labels ?? {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// logs query data
|
||||||
|
// logs use a special attribute in the dataframe's "custom" section
|
||||||
|
// because we do not have a good "frametype" value for them yet.
|
||||||
|
const customType1 = frame1.meta?.custom?.frameType;
|
||||||
|
const customType2 = frame2.meta?.custom?.frameType;
|
||||||
|
|
||||||
|
if (customType1 === 'LabeledTimeValues' && customType2 === 'LabeledTimeValues') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// should never reach here
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function combineResponses(currentResult: DataQueryResponse | null, newResult: DataQueryResponse) {
|
export function combineResponses(currentResult: DataQueryResponse | null, newResult: DataQueryResponse) {
|
||||||
|
|||||||
Reference in New Issue
Block a user