Prometheus: Add metadata for summary metrics (#24201)

* Prometheus: Add metadata for summary metrics

- summary metrics don't have metadata available from the metadata API,
so Grafana can help and just add it
- given a summary metric `foo`, we add metadata info for `foo_sum` and
`foo_count`
- with tests

* Update public/app/plugins/datasource/prometheus/language_utils.ts

Co-authored-by: gotjosh <josue@grafana.com>

Co-authored-by: gotjosh <josue@grafana.com>
This commit is contained in:
David 2020-05-07 12:02:45 +02:00 committed by GitHub
parent dc49d81693
commit 9208c8efd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 3 deletions

View File

@ -5,7 +5,7 @@ import { Value } from 'slate';
import { dateTime, LanguageProvider, HistoryItem } from '@grafana/data';
import { CompletionItem, TypeaheadInput, TypeaheadOutput, CompletionItemGroup } from '@grafana/ui';
import { parseSelector, processLabels, processHistogramLabels } from './language_utils';
import { parseSelector, processLabels, processHistogramLabels, fixSummariesMetadata } from './language_utils';
import PromqlSyntax, { FUNCTIONS, RATE_RANGES } from './promql';
import { PrometheusDatasource } from './datasource';
@ -118,7 +118,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
this.metrics = await this.request('/api/v1/label/__name__/values', []);
this.lookupsDisabled = this.metrics.length > this.lookupMetricsThreshold;
this.metricsMetadata = await this.request('/api/v1/metadata', {});
this.metricsMetadata = fixSummariesMetadata(await this.request('/api/v1/metadata', {}));
this.processHistogramMetrics(this.metrics);
return [];

View File

@ -1,4 +1,4 @@
import { expandRecordingRules, parseSelector } from './language_utils';
import { expandRecordingRules, fixSummariesMetadata, parseSelector } from './language_utils';
describe('parseSelector()', () => {
let parsed;
@ -70,6 +70,33 @@ describe('parseSelector()', () => {
});
});
describe('fixSummariesMetadata', () => {
it('returns empty metadata', () => {
expect(fixSummariesMetadata({})).toEqual({});
});
it('returns unchanged metadata if no summary is present', () => {
const metadata = {
foo: [{ type: 'not_a_summary', help: 'foo help' }],
};
expect(fixSummariesMetadata(metadata)).toEqual(metadata);
});
it('returns metadata with added count and sum for a summary', () => {
const metadata = {
foo: [{ type: 'not_a_summary', help: 'foo help' }],
bar: [{ type: 'summary', help: 'bar help' }],
};
const expected = {
foo: [{ type: 'not_a_summary', help: 'foo help' }],
bar: [{ type: 'summary', help: 'bar help' }],
bar_count: [{ type: 'counter', help: 'Count of events that have been observed for the base metric (bar help)' }],
bar_sum: [{ type: 'counter', help: 'Total sum of all observed values for the base metric (bar help)' }],
};
expect(fixSummariesMetadata(metadata)).toEqual(expected);
});
});
describe('expandRecordingRules()', () => {
it('returns query w/o recording rules as is', () => {
expect(expandRecordingRules('metric', {})).toBe('metric');

View File

@ -1,3 +1,5 @@
import { PromMetricsMetadata } from './types';
export const RATE_RANGES = ['1m', '5m', '10m', '30m', '1h'];
export const processHistogramLabels = (labels: string[]) => {
@ -111,3 +113,34 @@ export function expandRecordingRules(query: string, mapping: { [name: string]: s
const rulesRegex = new RegExp(`(\\s|^)(${ruleNames.join('|')})(\\s|$|\\(|\\[|\\{)`, 'ig');
return query.replace(rulesRegex, (match, pre, name, post) => `${pre}${mapping[name]}${post}`);
}
/**
* Adds metadata for synthetic metrics for which the API does not provide metadata.
* See https://github.com/grafana/grafana/issues/22337 for details.
*
* @param metadata HELP and TYPE metadata from /api/v1/metadata
*/
export function fixSummariesMetadata(metadata: PromMetricsMetadata): PromMetricsMetadata {
if (!metadata) {
return metadata;
}
const summaryMetadata: PromMetricsMetadata = {};
for (const metric in metadata) {
const item = metadata[metric][0];
if (item.type === 'summary') {
summaryMetadata[`${metric}_count`] = [
{
type: 'counter',
help: `Count of events that have been observed for the base metric (${item.help})`,
},
];
summaryMetadata[`${metric}_sum`] = [
{
type: 'counter',
help: `Total sum of all observed values for the base metric (${item.help})`,
},
];
}
}
return { ...metadata, ...summaryMetadata };
}