diff --git a/docs/sources/whatsnew/whats-new-in-v9-2.md b/docs/sources/whatsnew/whats-new-in-v9-2.md index 5ecf3788999..df46a65e4f9 100644 --- a/docs/sources/whatsnew/whats-new-in-v9-2.md +++ b/docs/sources/whatsnew/whats-new-in-v9-2.md @@ -219,3 +219,10 @@ For more information, see the [SAML configuration documentation](https://grafana You can now map OAuth groups and roles to Server Admin for the GitLab, GitHub, AzureAD, Okta, and Generic OAuth integrations. To enable this functionality, set the `allow_assign_grafana_admin` configuration option to `true` in the desired OAuth integration section. For more information, see the [authentication configuration documentation](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/) for each OAuth client. + +## Match parameter support in prometheus labels API + +Prometheus users running Prometheus v2.24 and higher can use the [labels endpoint](https://prometheus.io/docs/prometheus/latest/querying/api/#querying-label-values) instead of the [series endpoint](https://prometheus.io/docs/prometheus/latest/querying/api/#finding-series-by-label-matchers) for the [`label_values` function]({{< relref "../datasources/prometheus/#query-variable" >}}). +This decreases load times for templated high-cardinality Prometheus instances. + +If you want to benefit from this endpoint you must first configure the Prometheus type and version in any Prometheus data sources' [configuration]({{< relref "../datasources/prometheus/" >}}). diff --git a/public/app/plugins/datasource/prometheus/datasource.tsx b/public/app/plugins/datasource/prometheus/datasource.tsx index 72593c513cd..f739c898052 100644 --- a/public/app/plugins/datasource/prometheus/datasource.tsx +++ b/public/app/plugins/datasource/prometheus/datasource.tsx @@ -3,6 +3,7 @@ import LRU from 'lru-cache'; import React from 'react'; import { forkJoin, lastValueFrom, merge, Observable, of, OperatorFunction, pipe, throwError } from 'rxjs'; import { catchError, filter, map, tap } from 'rxjs/operators'; +import semver from 'semver/preload'; import { AnnotationEvent, @@ -146,6 +147,33 @@ export class PrometheusDatasource return query.expr; } + hasLabelsMatchAPISupport(): boolean { + return ( + // https://github.com/prometheus/prometheus/releases/tag/v2.24.0 + this._isDatasourceVersionGreaterOrEqualTo('2.24.0', PromApplication.Prometheus) || + // All versions of Mimir support matchers for labels API + this._isDatasourceVersionGreaterOrEqualTo('2.0.0', PromApplication.Mimir) || + // https://github.com/cortexproject/cortex/discussions/4542 + this._isDatasourceVersionGreaterOrEqualTo('1.11.0', PromApplication.Cortex) || + // https://github.com/thanos-io/thanos/pull/3566 + //https://github.com/thanos-io/thanos/releases/tag/v0.18.0 + this._isDatasourceVersionGreaterOrEqualTo('0.18', PromApplication.Thanos) + ); + } + + _isDatasourceVersionGreaterOrEqualTo(targetVersion: string, targetFlavor: PromApplication): boolean { + // User hasn't configured flavor/version yet, default behavior is to not support features that require version configuration when not provided + if (!this.datasourceConfigurationPrometheusVersion || !this.datasourceConfigurationPrometheusFlavor) { + return false; + } + + if (targetFlavor !== this.datasourceConfigurationPrometheusFlavor) { + return false; + } + + return semver.gte(this.datasourceConfigurationPrometheusVersion, targetVersion); + } + _addTracingHeaders(httpOptions: PromQueryRequest, options: DataQueryRequest) { httpOptions.headers = {}; if (this.access === 'proxy') { diff --git a/public/app/plugins/datasource/prometheus/metric_find_query.ts b/public/app/plugins/datasource/prometheus/metric_find_query.ts index 738982a7184..f3f678d1d2a 100644 --- a/public/app/plugins/datasource/prometheus/metric_find_query.ts +++ b/public/app/plugins/datasource/prometheus/metric_find_query.ts @@ -70,16 +70,10 @@ export default class PrometheusMetricFindQuery { labelValuesQuery(label: string, metric?: string) { const start = this.datasource.getPrometheusTime(this.range.from, false); const end = this.datasource.getPrometheusTime(this.range.to, true); + const params = { ...(metric && { 'match[]': metric }), start: start.toString(), end: end.toString() }; - let url: string; - - if (!metric) { - const params = { - start: start.toString(), - end: end.toString(), - }; - // return label values globally - url = `/api/v1/label/${label}/values`; + if (!metric || this.datasource.hasLabelsMatchAPISupport()) { + const url = `/api/v1/label/${label}/values`; return this.datasource.metadataRequest(url, params).then((result: any) => { return _map(result.data.data, (value) => { @@ -87,12 +81,7 @@ export default class PrometheusMetricFindQuery { }); }); } else { - const params = { - 'match[]': metric, - start: start.toString(), - end: end.toString(), - }; - url = `/api/v1/series`; + const url = `/api/v1/series`; return this.datasource.metadataRequest(url, params).then((result: any) => { const _labels = _map(result.data.data, (metric) => {