123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import { chain, map as _map, uniq } from 'lodash';
- import { lastValueFrom } from 'rxjs';
- import { map } from 'rxjs/operators';
- import { MetricFindValue, TimeRange } from '@grafana/data';
- import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
- import { PrometheusDatasource } from './datasource';
- import { PromQueryRequest } from './types';
- export default class PrometheusMetricFindQuery {
- range: TimeRange;
- constructor(private datasource: PrometheusDatasource, private query: string) {
- this.datasource = datasource;
- this.query = query;
- this.range = getTimeSrv().timeRange();
- }
- process(): Promise<MetricFindValue[]> {
- const labelNamesRegex = /^label_names\(\)\s*$/;
- const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]*)\)\s*$/;
- const metricNamesRegex = /^metrics\((.+)\)\s*$/;
- const queryResultRegex = /^query_result\((.+)\)\s*$/;
- const labelNamesQuery = this.query.match(labelNamesRegex);
- if (labelNamesQuery) {
- return this.labelNamesQuery();
- }
- const labelValuesQuery = this.query.match(labelValuesRegex);
- if (labelValuesQuery) {
- if (labelValuesQuery[1]) {
- return this.labelValuesQuery(labelValuesQuery[2], labelValuesQuery[1]);
- } else {
- return this.labelValuesQuery(labelValuesQuery[2]);
- }
- }
- const metricNamesQuery = this.query.match(metricNamesRegex);
- if (metricNamesQuery) {
- return this.metricNameQuery(metricNamesQuery[1]);
- }
- const queryResultQuery = this.query.match(queryResultRegex);
- if (queryResultQuery) {
- return lastValueFrom(this.queryResultQuery(queryResultQuery[1]));
- }
- // if query contains full metric name, return metric name and label list
- return this.metricNameAndLabelsQuery(this.query);
- }
- labelNamesQuery() {
- const start = this.datasource.getPrometheusTime(this.range.from, false);
- const end = this.datasource.getPrometheusTime(this.range.to, true);
- const params = {
- start: start.toString(),
- end: end.toString(),
- };
- const url = `/api/v1/labels`;
- return this.datasource.metadataRequest(url, params).then((result: any) => {
- return _map(result.data.data, (value) => {
- return { text: value };
- });
- });
- }
- labelValuesQuery(label: string, metric?: string) {
- const start = this.datasource.getPrometheusTime(this.range.from, false);
- const end = this.datasource.getPrometheusTime(this.range.to, true);
- let url: string;
- if (!metric) {
- const params = {
- start: start.toString(),
- end: end.toString(),
- };
- // return label values globally
- url = `/api/v1/label/${label}/values`;
- return this.datasource.metadataRequest(url, params).then((result: any) => {
- return _map(result.data.data, (value) => {
- return { text: value };
- });
- });
- } else {
- const params = {
- 'match[]': metric,
- start: start.toString(),
- end: end.toString(),
- };
- url = `/api/v1/series`;
- return this.datasource.metadataRequest(url, params).then((result: any) => {
- const _labels = _map(result.data.data, (metric) => {
- return metric[label] || '';
- }).filter((label) => {
- return label !== '';
- });
- return uniq(_labels).map((metric) => {
- return {
- text: metric,
- expandable: true,
- };
- });
- });
- }
- }
- metricNameQuery(metricFilterPattern: string) {
- const start = this.datasource.getPrometheusTime(this.range.from, false);
- const end = this.datasource.getPrometheusTime(this.range.to, true);
- const params = {
- start: start.toString(),
- end: end.toString(),
- };
- const url = `/api/v1/label/__name__/values`;
- return this.datasource.metadataRequest(url, params).then((result: any) => {
- return chain(result.data.data)
- .filter((metricName) => {
- const r = new RegExp(metricFilterPattern);
- return r.test(metricName);
- })
- .map((matchedMetricName) => {
- return {
- text: matchedMetricName,
- expandable: true,
- };
- })
- .value();
- });
- }
- queryResultQuery(query: string) {
- const end = this.datasource.getPrometheusTime(this.range.to, true);
- const instantQuery: PromQueryRequest = { expr: query } as PromQueryRequest;
- return this.datasource.performInstantQuery(instantQuery, end).pipe(
- map((result) => {
- return _map(result.data.data.result, (metricData) => {
- let text = metricData.metric.__name__ || '';
- delete metricData.metric.__name__;
- text +=
- '{' +
- _map(metricData.metric, (v, k) => {
- return k + '="' + v + '"';
- }).join(',') +
- '}';
- text += ' ' + metricData.value[1] + ' ' + metricData.value[0] * 1000;
- return {
- text: text,
- expandable: true,
- };
- });
- })
- );
- }
- metricNameAndLabelsQuery(query: string): Promise<MetricFindValue[]> {
- const start = this.datasource.getPrometheusTime(this.range.from, false);
- const end = this.datasource.getPrometheusTime(this.range.to, true);
- const params = {
- 'match[]': query,
- start: start.toString(),
- end: end.toString(),
- };
- const url = `/api/v1/series`;
- const self = this;
- return this.datasource.metadataRequest(url, params).then((result: any) => {
- return _map(result.data.data, (metric: { [key: string]: string }) => {
- return {
- text: self.datasource.getOriginalMetricName(metric),
- expandable: true,
- };
- });
- });
- }
- }
|