1import { from, lastValueFrom, Observable } from 'rxjs';
2import {
3  CustomVariableSupport,
4  DataQueryRequest,
5  DataQueryResponse,
6  MetricFindValue,
7  toDataFrame,
8} from '@grafana/data';
9import VariableEditor from './components/VariableEditor/VariableEditor';
10import DataSource from './datasource';
11import { AzureQueryType, AzureMonitorQuery } from './types';
12import { getTemplateSrv } from '@grafana/runtime';
13import { migrateStringQueriesToObjectQueries } from './grafanaTemplateVariableFns';
14import { GrafanaTemplateVariableQuery } from './types/templateVariables';
15import messageFromError from './utils/messageFromError';
16export class VariableSupport extends CustomVariableSupport<DataSource, AzureMonitorQuery> {
17  constructor(private readonly datasource: DataSource) {
18    super();
19    this.datasource = datasource;
20    this.query = this.query.bind(this);
21  }
22
23  editor = VariableEditor;
24
25  query(request: DataQueryRequest<AzureMonitorQuery>): Observable<DataQueryResponse> {
26    const promisedResults = async () => {
27      const queryObj = await migrateStringQueriesToObjectQueries(request.targets[0], { datasource: this.datasource });
28
29      if (queryObj.queryType === AzureQueryType.GrafanaTemplateVariableFn && queryObj.grafanaTemplateVariableFn) {
30        try {
31          const templateVariablesResults = await this.callGrafanaTemplateVariableFn(queryObj.grafanaTemplateVariableFn);
32          return {
33            data: templateVariablesResults ? [toDataFrame(templateVariablesResults)] : [],
34          };
35        } catch (err) {
36          return { data: [], error: { message: messageFromError(err) } };
37        }
38      }
39      request.targets[0] = queryObj;
40      return lastValueFrom(this.datasource.query(request));
41    };
42
43    return from(promisedResults());
44  }
45
46  callGrafanaTemplateVariableFn(query: GrafanaTemplateVariableQuery): Promise<MetricFindValue[]> | null {
47    // deprecated app insights template variables (will most likely remove in grafana 9)
48    if (this.datasource.insightsAnalyticsDatasource) {
49      if (query.kind === 'AppInsightsMetricNameQuery') {
50        return this.datasource.insightsAnalyticsDatasource.getMetricNames();
51      }
52
53      if (query.kind === 'AppInsightsGroupByQuery') {
54        return this.datasource.insightsAnalyticsDatasource.getGroupBys(getTemplateSrv().replace(query.metricName));
55      }
56    }
57
58    if (query.kind === 'SubscriptionsQuery') {
59      return this.datasource.getSubscriptions();
60    }
61
62    if (query.kind === 'ResourceGroupsQuery') {
63      return this.datasource.getResourceGroups(this.replaceVariable(query.subscription));
64    }
65
66    if (query.kind === 'MetricDefinitionsQuery') {
67      return this.datasource.getMetricDefinitions(
68        this.replaceVariable(query.subscription),
69        this.replaceVariable(query.resourceGroup)
70      );
71    }
72
73    if (query.kind === 'ResourceNamesQuery') {
74      return this.datasource.getResourceNames(
75        this.replaceVariable(query.subscription),
76        this.replaceVariable(query.resourceGroup),
77        this.replaceVariable(query.metricDefinition)
78      );
79    }
80
81    if (query.kind === 'MetricNamespaceQuery') {
82      return this.datasource.getMetricNamespaces(
83        this.replaceVariable(query.subscription),
84        this.replaceVariable(query.resourceGroup),
85        this.replaceVariable(query.metricDefinition),
86        this.replaceVariable(query.resourceName)
87      );
88    }
89
90    if (query.kind === 'MetricNamesQuery') {
91      return this.datasource.getMetricNames(
92        this.replaceVariable(query.subscription),
93        this.replaceVariable(query.resourceGroup),
94        this.replaceVariable(query.metricDefinition),
95        this.replaceVariable(query.resourceName),
96        this.replaceVariable(query.metricNamespace)
97      );
98    }
99
100    if (query.kind === 'WorkspacesQuery') {
101      return this.datasource.azureLogAnalyticsDatasource.getWorkspaces(this.replaceVariable(query.subscription));
102    }
103
104    return null;
105  }
106
107  replaceVariable(metric: string) {
108    return getTemplateSrv().replace((metric || '').trim());
109  }
110}
111