import { chain } from 'lodash'; import { HistoryItem } from '@grafana/data'; import { escapeLabelValueInExactSelector } from 'app/plugins/datasource/prometheus/language_utils'; import LanguageProvider from '../../../LanguageProvider'; import { LokiQuery } from '../../../types'; import { Label } from './situation'; export class CompletionDataProvider { private history: string[] = []; constructor(private languageProvider: LanguageProvider, history: Array> = []) { this.setHistory(history); } private buildSelector(labels: Label[]): string { const allLabelTexts = labels.map( (label) => `${label.name}${label.op}"${escapeLabelValueInExactSelector(label.value)}"` ); return `{${allLabelTexts.join(',')}}`; } setHistory(history: Array> = []) { this.history = chain(history) .map((history: HistoryItem) => history.query.expr) .filter() .uniq() .value(); } getHistory() { return this.history; } async getLabelNames(otherLabels: Label[] = []) { if (otherLabels.length === 0) { // if there is no filtering, we have to use a special endpoint return this.languageProvider.getLabelKeys(); } const data = await this.getSeriesLabels(otherLabels); const possibleLabelNames = Object.keys(data); // all names from datasource const usedLabelNames = new Set(otherLabels.map((l) => l.name)); // names used in the query return possibleLabelNames.filter((label) => !usedLabelNames.has(label)); } async getLabelValues(labelName: string, otherLabels: Label[]) { if (otherLabels.length === 0) { // if there is no filtering, we have to use a special endpoint return await this.languageProvider.getLabelValues(labelName); } const data = await this.getSeriesLabels(otherLabels); return data[labelName] ?? []; } async getParserAndLabelKeys(logQuery: string) { return await this.languageProvider.getParserAndLabelKeys(logQuery); } async getSeriesLabels(labels: Label[]) { return await this.languageProvider.getSeriesLabels(this.buildSelector(labels)).then((data) => data ?? {}); } }