From 85dbacafdb5aeba42b7efc1a3d311b436d97fada Mon Sep 17 00:00:00 2001 From: timkendrickmw <79589507+timkendrickmw@users.noreply.github.com> Date: Thu, 11 Aug 2022 14:47:07 +0100 Subject: [PATCH] GrafanaUI: improve Prometheus getQueryHints performance (#52148) --- .../datasource/prometheus/query_hints.ts | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/query_hints.ts b/public/app/plugins/datasource/prometheus/query_hints.ts index 08dd3495099..b635d625202 100644 --- a/public/app/plugins/datasource/prometheus/query_hints.ts +++ b/public/app/plugins/datasource/prometheus/query_hints.ts @@ -34,23 +34,28 @@ export function getQueryHints(query: string, series?: any[], datasource?: Promet // 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); + const metricsMetadata = datasource?.languageProvider?.metricsMetadata; let certain = false; - if (metricMetadataKeys.length > 0) { + if (metricsMetadata) { + // Tokenize the query into its identifiers (see https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels) + const queryTokens = Array.from(query.matchAll(/\$?[a-zA-Z_:][a-zA-Z0-9_:]*/g)) + .map(([match]) => match) + // Exclude variable identifiers + .filter((token) => !token.startsWith('$')) + // Split composite keys to match the tokens returned by the language provider + .flatMap((token) => token.split(':')); + // Determine whether any of the query identifier tokens refers to a counter metric counterNameMetric = - metricMetadataKeys.find((metricName) => { + queryTokens.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; - } + if (metadata && metadata.type.toLowerCase() === 'counter') { + certain = true; + return true; + } else { + return false; } - return false; }) ?? ''; }