Prometheus: Fix running of exemplar queries for non-histogram metrics (#42749)

* Prometheus: Fix running of exemplar queries for non-histogram mestrics

* Fix test

* Refactor based on review suggestions
pull/42919/head
Ivana Huckova 4 years ago committed by GitHub
parent 984d26ce86
commit e555221523
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 29
      public/app/plugins/datasource/prometheus/datasource.test.ts
  2. 22
      public/app/plugins/datasource/prometheus/datasource.ts

@ -1667,6 +1667,35 @@ describe('PrometheusDatasource', () => {
templateSrvStub.replace = jest.fn((a: string) => a);
});
});
it('should give back 1 exemplar target when multiple queries with exemplar enabled and same metric', () => {
const targetA: PromQuery = {
refId: 'A',
expr: 'histogram_quantile(0.95, sum(rate(tns_request_duration_seconds_bucket[5m])) by (le))',
exemplar: true,
};
const targetB: PromQuery = {
refId: 'B',
expr: 'histogram_quantile(0.5, sum(rate(tns_request_duration_seconds_bucket[5m])) by (le))',
exemplar: true,
};
ds.languageProvider = {
histogramMetrics: ['tns_request_duration_seconds_bucket'],
} as any;
const request = ({
targets: [targetA, targetB],
interval: '1s',
panelId: '',
} as any) as DataQueryRequest<PromQuery>;
const Aexemplars = ds.shouldRunExemplarQuery(targetA, request);
const BExpemplars = ds.shouldRunExemplarQuery(targetB, request);
expect(Aexemplars).toBe(true);
expect(BExpemplars).toBe(false);
});
});
describe('PrometheusDatasource for POST', () => {

@ -300,21 +300,19 @@ export class PrometheusDatasource extends DataSourceWithBackend<PromQuery, PromO
};
};
shouldRunExemplarQuery(target: PromQuery): boolean {
/* We want to run exemplar query only for histogram metrics:
1. If we haven't processd histogram metrics yet, we need to check if expr includes "_bucket" which means that it is probably histogram metric (can rarely lead to false positive).
2. If we have processed histogram metrics, check if it is part of query expr.
*/
shouldRunExemplarQuery(target: PromQuery, request: DataQueryRequest<PromQuery>): boolean {
if (target.exemplar) {
const histogramMetrics = this.languageProvider.histogramMetrics;
// We check all already processed targets and only create exemplar target for not used metric names
const metricName = this.languageProvider.histogramMetrics.find((m) => target.expr.includes(m));
// Remove targets that weren't processed yet (in targets array they are after current target)
const currentTargetIdx = request.targets.findIndex((t) => t.refId === target.refId);
const targets = request.targets.slice(0, currentTargetIdx);
if (histogramMetrics.length > 0) {
return !!histogramMetrics.find((metric) => target.expr.includes(metric));
} else {
return target.expr.includes('_bucket');
if (!metricName || (metricName && !targets.some((t) => t.expr.includes(metricName)))) {
return true;
}
return false;
}
return false;
}
@ -322,7 +320,7 @@ export class PrometheusDatasource extends DataSourceWithBackend<PromQuery, PromO
const processedTarget = {
...target,
queryType: PromQueryType.timeSeriesQuery,
exemplar: this.shouldRunExemplarQuery(target),
exemplar: this.shouldRunExemplarQuery(target, request),
requestId: request.panelId + target.refId,
// We need to pass utcOffsetSec to backend to calculate aligned range
utcOffsetSec: this.timeSrv.timeRange().to.utcOffset() * 60,

Loading…
Cancel
Save