2017-12-21 08:39:31 +01:00
|
|
|
import _ from 'lodash';
|
2019-07-05 23:05:53 -07:00
|
|
|
import { TimeRange } from '@grafana/data';
|
2019-06-18 11:01:12 +02:00
|
|
|
import { PrometheusDatasource, PromDataQueryResponse } from './datasource';
|
|
|
|
|
import { PromQueryRequest } from './types';
|
2019-11-21 15:36:56 +00:00
|
|
|
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
2017-11-22 10:11:50 +01:00
|
|
|
|
|
|
|
|
export default class PrometheusMetricFindQuery {
|
2019-06-18 11:01:12 +02:00
|
|
|
range: TimeRange;
|
2017-11-22 10:11:50 +01:00
|
|
|
|
2019-11-21 15:36:56 +00:00
|
|
|
constructor(private datasource: PrometheusDatasource, private query: string) {
|
2017-11-22 10:11:50 +01:00
|
|
|
this.datasource = datasource;
|
|
|
|
|
this.query = query;
|
2019-11-21 15:36:56 +00:00
|
|
|
this.range = getTimeSrv().timeRange();
|
2017-11-22 10:11:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
process() {
|
2019-02-07 13:54:25 +09:00
|
|
|
const labelNamesRegex = /^label_names\(\)\s*$/;
|
2018-10-12 23:13:11 +03:00
|
|
|
const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]*)\)\s*$/;
|
2018-09-03 11:00:46 +02:00
|
|
|
const metricNamesRegex = /^metrics\((.+)\)\s*$/;
|
|
|
|
|
const queryResultRegex = /^query_result\((.+)\)\s*$/;
|
2019-02-07 13:54:25 +09:00
|
|
|
const labelNamesQuery = this.query.match(labelNamesRegex);
|
|
|
|
|
if (labelNamesQuery) {
|
|
|
|
|
return this.labelNamesQuery();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-03 11:00:46 +02:00
|
|
|
const labelValuesQuery = this.query.match(labelValuesRegex);
|
|
|
|
|
if (labelValuesQuery) {
|
|
|
|
|
if (labelValuesQuery[1]) {
|
|
|
|
|
return this.labelValuesQuery(labelValuesQuery[2], labelValuesQuery[1]);
|
2017-11-22 10:11:50 +01:00
|
|
|
} else {
|
2018-09-03 11:00:46 +02:00
|
|
|
return this.labelValuesQuery(labelValuesQuery[2], null);
|
2017-11-22 10:11:50 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-03 11:00:46 +02:00
|
|
|
const metricNamesQuery = this.query.match(metricNamesRegex);
|
|
|
|
|
if (metricNamesQuery) {
|
|
|
|
|
return this.metricNameQuery(metricNamesQuery[1]);
|
2017-11-22 10:11:50 +01:00
|
|
|
}
|
|
|
|
|
|
2018-09-03 11:00:46 +02:00
|
|
|
const queryResultQuery = this.query.match(queryResultRegex);
|
|
|
|
|
if (queryResultQuery) {
|
|
|
|
|
return this.queryResultQuery(queryResultQuery[1]);
|
2017-11-22 10:11:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if query contains full metric name, return metric name and label list
|
|
|
|
|
return this.metricNameAndLabelsQuery(this.query);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-07 13:54:25 +09:00
|
|
|
labelNamesQuery() {
|
|
|
|
|
const url = '/api/v1/labels';
|
2019-06-18 11:01:12 +02:00
|
|
|
return this.datasource.metadataRequest(url).then((result: any) => {
|
2019-02-07 13:54:25 +09:00
|
|
|
return _.map(result.data.data, value => {
|
|
|
|
|
return { text: value };
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-18 11:01:12 +02:00
|
|
|
labelValuesQuery(label: string, metric?: string) {
|
|
|
|
|
let url: string;
|
2017-11-22 10:11:50 +01:00
|
|
|
|
|
|
|
|
if (!metric) {
|
|
|
|
|
// return label values globally
|
2017-12-21 08:39:31 +01:00
|
|
|
url = '/api/v1/label/' + label + '/values';
|
2017-11-22 10:11:50 +01:00
|
|
|
|
2019-06-18 11:01:12 +02:00
|
|
|
return this.datasource.metadataRequest(url).then((result: any) => {
|
2018-09-04 14:27:03 +02:00
|
|
|
return _.map(result.data.data, value => {
|
2017-11-22 10:11:50 +01:00
|
|
|
return { text: value };
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
} else {
|
2018-08-29 14:27:29 +02:00
|
|
|
const start = this.datasource.getPrometheusTime(this.range.from, false);
|
|
|
|
|
const end = this.datasource.getPrometheusTime(this.range.to, true);
|
2017-12-21 08:39:31 +01:00
|
|
|
url = '/api/v1/series?match[]=' + encodeURIComponent(metric) + '&start=' + start + '&end=' + end;
|
|
|
|
|
|
2019-06-18 11:01:12 +02:00
|
|
|
return this.datasource.metadataRequest(url).then((result: any) => {
|
2018-09-04 14:27:03 +02:00
|
|
|
const _labels = _.map(result.data.data, metric => {
|
2017-12-21 08:39:31 +01:00
|
|
|
return metric[label] || '';
|
2018-09-04 14:27:03 +02:00
|
|
|
}).filter(label => {
|
2017-12-21 08:39:31 +01:00
|
|
|
return label !== '';
|
2017-12-19 16:06:54 +01:00
|
|
|
});
|
2017-11-22 10:11:50 +01:00
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
return _.uniq(_labels).map(metric => {
|
2017-11-22 10:11:50 +01:00
|
|
|
return {
|
|
|
|
|
text: metric,
|
2017-12-21 08:39:31 +01:00
|
|
|
expandable: true,
|
2017-11-22 10:11:50 +01:00
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-18 11:01:12 +02:00
|
|
|
metricNameQuery(metricFilterPattern: string) {
|
2018-08-29 14:27:29 +02:00
|
|
|
const url = '/api/v1/label/__name__/values';
|
2017-11-22 10:11:50 +01:00
|
|
|
|
2019-06-18 11:01:12 +02:00
|
|
|
return this.datasource.metadataRequest(url).then((result: any) => {
|
2017-11-22 10:11:50 +01:00
|
|
|
return _.chain(result.data.data)
|
2018-09-04 14:27:03 +02:00
|
|
|
.filter(metricName => {
|
2018-08-29 14:27:29 +02:00
|
|
|
const r = new RegExp(metricFilterPattern);
|
2017-11-22 10:11:50 +01:00
|
|
|
return r.test(metricName);
|
|
|
|
|
})
|
2018-09-04 14:27:03 +02:00
|
|
|
.map(matchedMetricName => {
|
2017-11-22 10:11:50 +01:00
|
|
|
return {
|
|
|
|
|
text: matchedMetricName,
|
2017-12-21 08:39:31 +01:00
|
|
|
expandable: true,
|
2017-11-22 10:11:50 +01:00
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
.value();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-18 11:01:12 +02:00
|
|
|
queryResultQuery(query: string) {
|
2018-08-29 14:27:29 +02:00
|
|
|
const end = this.datasource.getPrometheusTime(this.range.to, true);
|
2019-06-18 11:01:12 +02:00
|
|
|
const instantQuery: PromQueryRequest = { expr: query } as PromQueryRequest;
|
|
|
|
|
return this.datasource.performInstantQuery(instantQuery, end).then((result: PromDataQueryResponse) => {
|
2018-09-04 14:27:03 +02:00
|
|
|
return _.map(result.data.data.result, metricData => {
|
2018-08-30 09:03:11 +02:00
|
|
|
let text = metricData.metric.__name__ || '';
|
2017-12-21 08:39:31 +01:00
|
|
|
delete metricData.metric.__name__;
|
|
|
|
|
text +=
|
|
|
|
|
'{' +
|
2018-09-04 14:27:03 +02:00
|
|
|
_.map(metricData.metric, (v, k) => {
|
2017-12-21 08:39:31 +01:00
|
|
|
return k + '="' + v + '"';
|
|
|
|
|
}).join(',') +
|
|
|
|
|
'}';
|
|
|
|
|
text += ' ' + metricData.value[1] + ' ' + metricData.value[0] * 1000;
|
2017-11-22 10:11:50 +01:00
|
|
|
|
2017-12-21 08:39:31 +01:00
|
|
|
return {
|
|
|
|
|
text: text,
|
|
|
|
|
expandable: true,
|
|
|
|
|
};
|
2017-11-22 10:11:50 +01:00
|
|
|
});
|
2017-12-21 08:39:31 +01:00
|
|
|
});
|
2017-11-22 10:11:50 +01:00
|
|
|
}
|
|
|
|
|
|
2019-06-18 11:01:12 +02:00
|
|
|
metricNameAndLabelsQuery(query: string) {
|
2018-08-29 14:27:29 +02:00
|
|
|
const start = this.datasource.getPrometheusTime(this.range.from, false);
|
|
|
|
|
const end = this.datasource.getPrometheusTime(this.range.to, true);
|
|
|
|
|
const url = '/api/v1/series?match[]=' + encodeURIComponent(query) + '&start=' + start + '&end=' + end;
|
2017-11-22 10:11:50 +01:00
|
|
|
|
2018-08-29 14:27:29 +02:00
|
|
|
const self = this;
|
2019-06-18 11:01:12 +02:00
|
|
|
return this.datasource.metadataRequest(url).then((result: PromDataQueryResponse) => {
|
|
|
|
|
return _.map(result.data.data, (metric: { [key: string]: string }) => {
|
2017-11-22 10:11:50 +01:00
|
|
|
return {
|
|
|
|
|
text: self.datasource.getOriginalMetricName(metric),
|
2017-12-21 08:39:31 +01:00
|
|
|
expandable: true,
|
2017-11-22 10:11:50 +01:00
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|