diff --git a/public/app/plugins/datasource/prometheus/language_provider.ts b/public/app/plugins/datasource/prometheus/language_provider.ts index 77cb6df0d9f..581bd9ac1e6 100644 --- a/public/app/plugins/datasource/prometheus/language_provider.ts +++ b/public/app/plugins/datasource/prometheus/language_provider.ts @@ -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 []; diff --git a/public/app/plugins/datasource/prometheus/language_utils.test.ts b/public/app/plugins/datasource/prometheus/language_utils.test.ts index 978b3033eb8..303dec7ef49 100644 --- a/public/app/plugins/datasource/prometheus/language_utils.test.ts +++ b/public/app/plugins/datasource/prometheus/language_utils.test.ts @@ -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'); diff --git a/public/app/plugins/datasource/prometheus/language_utils.ts b/public/app/plugins/datasource/prometheus/language_utils.ts index a22f2b5c018..9d311db96ff 100644 --- a/public/app/plugins/datasource/prometheus/language_utils.ts +++ b/public/app/plugins/datasource/prometheus/language_utils.ts @@ -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 }; +}