123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- import { size } from 'lodash';
- import { QueryHint, QueryFix } from '@grafana/data';
- import { PrometheusDatasource } from './datasource';
- /**
- * Number of time series results needed before starting to suggest sum aggregation hints
- */
- export const SUM_HINT_THRESHOLD_COUNT = 20;
- export function getQueryHints(query: string, series?: any[], datasource?: PrometheusDatasource): QueryHint[] {
- const hints = [];
- // ..._bucket metric needs a histogram_quantile()
- const histogramMetric = query.trim().match(/^\w+_bucket$|^\w+_bucket{.*}$/);
- if (histogramMetric) {
- const label = 'Selected metric has buckets.';
- hints.push({
- type: 'HISTOGRAM_QUANTILE',
- label,
- fix: {
- label: 'Consider calculating aggregated quantile by adding histogram_quantile().',
- action: {
- type: 'ADD_HISTOGRAM_QUANTILE',
- query,
- },
- } as QueryFix,
- });
- }
- // Check for need of rate()
- if (query.indexOf('rate(') === -1 && query.indexOf('increase(') === -1) {
- // Use metric metadata for exact types
- const nameMatch = query.match(/\b(\w+_(total|sum|count))\b/);
- let counterNameMetric = nameMatch ? nameMatch[1] : '';
- const metricsMetadata = datasource?.languageProvider?.metricsMetadata ?? {};
- const metricMetadataKeys = Object.keys(metricsMetadata);
- let certain = false;
- if (metricMetadataKeys.length > 0) {
- counterNameMetric =
- metricMetadataKeys.find((metricName) => {
- // Only considering first type information, could be non-deterministic
- const metadata = metricsMetadata[metricName];
- if (metadata.type.toLowerCase() === 'counter') {
- const metricRegex = new RegExp(`\\b${metricName}\\b`);
- if (query.match(metricRegex)) {
- certain = true;
- return true;
- }
- }
- return false;
- }) ?? '';
- }
- if (counterNameMetric) {
- // FixableQuery consists of metric name and optionally label-value pairs. We are not offering fix for complex queries yet.
- const fixableQuery = query.trim().match(/^\w+$|^\w+{.*}$/);
- const verb = certain ? 'is' : 'looks like';
- let label = `Selected metric ${verb} a counter.`;
- let fix: QueryFix | undefined;
- if (fixableQuery) {
- fix = {
- label: 'Consider calculating rate of counter by adding rate().',
- action: {
- type: 'ADD_RATE',
- query,
- },
- };
- } else {
- label = `${label} Consider calculating rate of counter by adding rate().`;
- }
- hints.push({
- type: 'APPLY_RATE',
- label,
- fix,
- });
- }
- }
- // Check for recording rules expansion
- if (datasource && datasource.ruleMappings) {
- const mapping = datasource.ruleMappings;
- const mappingForQuery = Object.keys(mapping).reduce((acc, ruleName) => {
- if (query.search(ruleName) > -1) {
- return {
- ...acc,
- [ruleName]: mapping[ruleName],
- };
- }
- return acc;
- }, {});
- if (size(mappingForQuery) > 0) {
- const label = 'Query contains recording rules.';
- hints.push({
- type: 'EXPAND_RULES',
- label,
- fix: {
- label: 'Expand rules',
- action: {
- type: 'EXPAND_RULES',
- query,
- mapping: mappingForQuery,
- },
- } as any as QueryFix,
- });
- }
- }
- if (series && series.length >= SUM_HINT_THRESHOLD_COUNT) {
- const simpleMetric = query.trim().match(/^\w+$/);
- if (simpleMetric) {
- hints.push({
- type: 'ADD_SUM',
- label: 'Many time series results returned.',
- fix: {
- label: 'Consider aggregating with sum().',
- action: {
- type: 'ADD_SUM',
- query: query,
- preventSubmit: true,
- },
- } as QueryFix,
- });
- }
- }
- return hints;
- }
- export function getInitHints(datasource: PrometheusDatasource): QueryHint[] {
- const hints = [];
- // Hint if using Loki as Prometheus data source
- if (datasource.directUrl.includes('/loki') && !datasource.languageProvider.metrics.length) {
- hints.push({
- label: `Using Loki as a Prometheus data source is no longer supported. You must use the Loki data source for your Loki instance.`,
- type: 'INFO',
- });
- }
- // Hint for big disabled lookups
- if (datasource.lookupsDisabled) {
- hints.push({
- label: `Labels and metrics lookup was disabled in data source settings.`,
- type: 'INFO',
- });
- }
- return hints;
- }
|