import { promQueryModeller } from '../querybuilder/PromQueryModeller'; import { buildVisualQueryFromString } from '../querybuilder/parsing'; import { PromVariableQuery, PromVariableQueryType as QueryType } from '../types'; export const PrometheusLabelNamesRegex = /^label_names\(\)\s*$/; // Note that this regex is different from the one in metric_find_query.ts because this is used pre-interpolation export const PrometheusLabelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_$][a-zA-Z0-9_]*)\)\s*$/; export const PrometheusMetricNamesRegex = /^metrics\((.+)\)\s*$/; export const PrometheusQueryResultRegex = /^query_result\((.+)\)\s*$/; export const PrometheusLabelNamesRegexWithMatch = /^label_names\((.+)\)\s*$/; export function migrateVariableQueryToEditor(rawQuery: string | PromVariableQuery): PromVariableQuery { // If not string, we assume PromVariableQuery if (typeof rawQuery !== 'string') { return rawQuery; } const queryBase = { refId: 'PrometheusDatasource-VariableQuery', qryType: QueryType.LabelNames, }; const labelNamesMatchQuery = rawQuery.match(PrometheusLabelNamesRegexWithMatch); if (labelNamesMatchQuery) { return { ...queryBase, qryType: QueryType.LabelNames, match: labelNamesMatchQuery[1], }; } const labelNames = rawQuery.match(PrometheusLabelNamesRegex); if (labelNames) { return { ...queryBase, qryType: QueryType.LabelNames, }; } const labelValuesCheck = rawQuery.match(/^label_values\(/); if (labelValuesCheck) { const labelValues = rawQuery.match(PrometheusLabelValuesRegex); const label = labelValues ? labelValues[2] : ''; const metric = labelValues ? labelValues[1] : ''; if (metric) { const visQuery = buildVisualQueryFromString(metric); return { ...queryBase, qryType: QueryType.LabelValues, label, metric: visQuery.query.metric, labelFilters: visQuery.query.labels, }; } else { return { ...queryBase, qryType: QueryType.LabelValues, label, }; } } const metricNamesCheck = rawQuery.match(/^metrics\(/); if (metricNamesCheck) { const metricNames = rawQuery.match(PrometheusMetricNamesRegex); const metric = metricNames ? metricNames[1] : ''; return { ...queryBase, qryType: QueryType.MetricNames, metric, }; } const queryResultCheck = rawQuery.match(/^query_result\(/); if (queryResultCheck) { const queryResult = rawQuery.match(PrometheusQueryResultRegex); const varQuery = queryResult ? queryResult[1] : ''; return { ...queryBase, qryType: QueryType.VarQueryResult, varQuery, }; } // seriesQuery does not have a function and no regex above if (!labelNames && !labelValuesCheck && !metricNamesCheck && !queryResultCheck) { return { ...queryBase, qryType: QueryType.SeriesQuery, seriesQuery: rawQuery, }; } return queryBase; } // migrate it back to a string with the correct varialbes in place export function migrateVariableEditorBackToVariableSupport(QueryVariable: PromVariableQuery): string { switch (QueryVariable.qryType) { case QueryType.LabelNames: if (QueryVariable.match) { return `label_names(${QueryVariable.match})`; } return 'label_names()'; case QueryType.LabelValues: if (QueryVariable.metric || (QueryVariable.labelFilters && QueryVariable.labelFilters.length !== 0)) { const visualQueryQuery = { metric: QueryVariable.metric, labels: QueryVariable.labelFilters ?? [], operations: [], }; const metric = promQueryModeller.renderQuery(visualQueryQuery); return `label_values(${metric},${QueryVariable.label})`; } else { return `label_values(${QueryVariable.label})`; } case QueryType.MetricNames: return `metrics(${QueryVariable.metric})`; case QueryType.VarQueryResult: const varQuery = removeLineBreaks(QueryVariable.varQuery); return `query_result(${varQuery})`; case QueryType.SeriesQuery: return QueryVariable.seriesQuery ?? ''; case QueryType.ClassicQuery: return QueryVariable.classicQuery ?? ''; } return ''; } // allow line breaks in query result textarea function removeLineBreaks(input?: string) { return input ? input.replace(/[\r\n]+/gm, '') : ''; }