mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* chore: AzureMonitor typescript typings Removes some types and using @grafana/ui types instead. Adds some typing for the AzureMonitor query. Also adds a getSubscriptions function that will used in the query editor. * fix: AzureMonitor adds back editor for annotation queries This must have been broken for a month or more. Now possible to edit annotation queries again. * feat: Azure Monitor - support for multiple subscriptions Adds a new dropdown for subscriptions in the query editor. Defaults to the subscription id in jsonData for queries that have no subscription id. * feat: adds Azure Logs multi subscriptions support The subscription id is needed for fetching the list of workspaces. Adds support to the Log Analytics datasource and to the annotations for Log Analytics to be able to choose between multiple subscriptions. * feat: AzureMonitor config page with multiple subs Adds support for multiple subscriptions for the different variations of configuring Azure Monitor and Azure Logs. To be able to show a list of subscriptions, the config has to be saved first - the plugin route fetches the tenant id, client id and client secret from the database so a call to get subscriptions requires that those fields are saved first. If the page has not saved then the use can manually paste in a subscription id. * feat: support for multi subs in Azure Monitor variables Adds an optional subscription parameter to the template variable macros. Also adds a Subscriptions macro. * fix: remove some implicit anys from tests
454 lines
14 KiB
TypeScript
454 lines
14 KiB
TypeScript
import _ from 'lodash';
|
||
import { QueryCtrl } from 'app/plugins/sdk';
|
||
// import './css/query_editor.css';
|
||
import TimegrainConverter from './time_grain_converter';
|
||
import './editor/editor_component';
|
||
|
||
export interface ResultFormat {
|
||
text: string;
|
||
value: string;
|
||
}
|
||
|
||
export class AzureMonitorQueryCtrl extends QueryCtrl {
|
||
static templateUrl = 'partials/query.editor.html';
|
||
|
||
defaultDropdownValue = 'select';
|
||
|
||
target: {
|
||
refId: string;
|
||
queryType: string;
|
||
subscription: string;
|
||
azureMonitor: {
|
||
resourceGroup: string;
|
||
resourceName: string;
|
||
metricDefinition: string;
|
||
metricName: string;
|
||
dimensionFilter: string;
|
||
timeGrain: string;
|
||
timeGrainUnit: string;
|
||
timeGrains: any[];
|
||
dimensions: any[];
|
||
dimension: any;
|
||
aggregation: string;
|
||
aggOptions: string[];
|
||
};
|
||
azureLogAnalytics: {
|
||
query: string;
|
||
resultFormat: string;
|
||
workspace: string;
|
||
};
|
||
appInsights: {
|
||
metricName: string;
|
||
rawQuery: boolean;
|
||
rawQueryString: string;
|
||
groupBy: string;
|
||
timeGrainType: string;
|
||
xaxis: string;
|
||
yaxis: string;
|
||
spliton: string;
|
||
aggOptions: string[];
|
||
aggregation: string;
|
||
groupByOptions: string[];
|
||
timeGrainUnit: string;
|
||
timeGrain: string;
|
||
};
|
||
};
|
||
|
||
defaults = {
|
||
queryType: 'Azure Monitor',
|
||
azureMonitor: {
|
||
resourceGroup: this.defaultDropdownValue,
|
||
metricDefinition: this.defaultDropdownValue,
|
||
resourceName: this.defaultDropdownValue,
|
||
metricName: this.defaultDropdownValue,
|
||
dimensionFilter: '*',
|
||
timeGrain: 'auto',
|
||
},
|
||
azureLogAnalytics: {
|
||
query: [
|
||
'//change this example to create your own time series query',
|
||
'<table name> ' +
|
||
'//the table to query (e.g. Usage, Heartbeat, Perf)',
|
||
'| where $__timeFilter(TimeGenerated) ' +
|
||
'//this is a macro used to show the full chart’s time range, choose the datetime column here',
|
||
'| summarize count() by <group by column>, bin(TimeGenerated, $__interval) ' +
|
||
'//change “group by column” to a column in your table, such as “Computer”. ' +
|
||
'The $__interval macro is used to auto-select the time grain. Can also use 1h, 5m etc.',
|
||
'| order by TimeGenerated asc',
|
||
].join('\n'),
|
||
resultFormat: 'time_series',
|
||
workspace:
|
||
this.datasource && this.datasource.azureLogAnalyticsDatasource
|
||
? this.datasource.azureLogAnalyticsDatasource.defaultOrFirstWorkspace
|
||
: '',
|
||
},
|
||
appInsights: {
|
||
metricName: this.defaultDropdownValue,
|
||
rawQuery: false,
|
||
rawQueryString: '',
|
||
groupBy: 'none',
|
||
timeGrainType: 'auto',
|
||
xaxis: 'timestamp',
|
||
yaxis: '',
|
||
spliton: '',
|
||
},
|
||
};
|
||
|
||
resultFormats: ResultFormat[];
|
||
workspaces: any[];
|
||
showHelp: boolean;
|
||
showLastQuery: boolean;
|
||
lastQuery: string;
|
||
lastQueryError?: string;
|
||
subscriptions: Array<{ text: string; value: string }>;
|
||
|
||
/** @ngInject */
|
||
constructor($scope, $injector, private templateSrv) {
|
||
super($scope, $injector);
|
||
|
||
_.defaultsDeep(this.target, this.defaults);
|
||
|
||
this.migrateTimeGrains();
|
||
|
||
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
|
||
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
|
||
this.resultFormats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
|
||
this.getSubscriptions();
|
||
if (this.target.queryType === 'Azure Log Analytics') {
|
||
this.getWorkspaces();
|
||
}
|
||
}
|
||
|
||
onDataReceived(dataList) {
|
||
this.lastQueryError = undefined;
|
||
this.lastQuery = '';
|
||
|
||
const anySeriesFromQuery: any = _.find(dataList, { refId: this.target.refId });
|
||
if (anySeriesFromQuery && anySeriesFromQuery.meta) {
|
||
this.lastQuery = anySeriesFromQuery.meta.query;
|
||
}
|
||
}
|
||
|
||
onDataError(err) {
|
||
this.handleQueryCtrlError(err);
|
||
}
|
||
|
||
handleQueryCtrlError(err) {
|
||
if (err.query && err.query.refId && err.query.refId !== this.target.refId) {
|
||
return;
|
||
}
|
||
|
||
if (err.error && err.error.data && err.error.data.error && err.error.data.error.innererror) {
|
||
if (err.error.data.error.innererror.innererror) {
|
||
this.lastQueryError = err.error.data.error.innererror.innererror.message;
|
||
} else {
|
||
this.lastQueryError = err.error.data.error.innererror.message;
|
||
}
|
||
} else if (err.error && err.error.data && err.error.data.error) {
|
||
this.lastQueryError = err.error.data.error.message;
|
||
} else if (err.error && err.error.data) {
|
||
this.lastQueryError = err.error.data.message;
|
||
} else if (err.data && err.data.error) {
|
||
this.lastQueryError = err.data.error.message;
|
||
} else if (err.data && err.data.message) {
|
||
this.lastQueryError = err.data.message;
|
||
} else {
|
||
this.lastQueryError = err;
|
||
}
|
||
}
|
||
|
||
migrateTimeGrains() {
|
||
if (this.target.azureMonitor.timeGrainUnit) {
|
||
if (this.target.azureMonitor.timeGrain !== 'auto') {
|
||
this.target.azureMonitor.timeGrain = TimegrainConverter.createISO8601Duration(
|
||
this.target.azureMonitor.timeGrain,
|
||
this.target.azureMonitor.timeGrainUnit
|
||
);
|
||
}
|
||
|
||
delete this.target.azureMonitor.timeGrainUnit;
|
||
this.onMetricNameChange();
|
||
}
|
||
}
|
||
|
||
replace(variable: string) {
|
||
return this.templateSrv.replace(variable, this.panelCtrl.panel.scopedVars);
|
||
}
|
||
|
||
onQueryTypeChange() {
|
||
if (this.target.queryType === 'Azure Log Analytics') {
|
||
return this.getWorkspaces();
|
||
}
|
||
}
|
||
|
||
getSubscriptions() {
|
||
if (!this.datasource.azureMonitorDatasource.isConfigured()) {
|
||
return;
|
||
}
|
||
|
||
return this.datasource.azureMonitorDatasource.getSubscriptions().then(subs => {
|
||
this.subscriptions = subs;
|
||
if (!this.target.subscription && this.target.queryType === 'Azure Monitor') {
|
||
this.target.subscription = this.datasource.azureMonitorDatasource.subscriptionId;
|
||
} else if (!this.target.subscription && this.target.queryType === 'Azure Log Analytics') {
|
||
this.target.subscription = this.datasource.azureLogAnalyticsDatasource.logAnalyticsSubscriptionId;
|
||
}
|
||
|
||
if (!this.target.subscription && this.subscriptions.length > 0) {
|
||
this.target.subscription = this.subscriptions[0].value;
|
||
}
|
||
});
|
||
}
|
||
|
||
onSubscriptionChange() {
|
||
if (this.target.queryType === 'Azure Log Analytics') {
|
||
return this.getWorkspaces();
|
||
}
|
||
}
|
||
|
||
/* Azure Monitor Section */
|
||
getResourceGroups(query) {
|
||
if (this.target.queryType !== 'Azure Monitor' || !this.datasource.azureMonitorDatasource.isConfigured()) {
|
||
return;
|
||
}
|
||
|
||
return this.datasource
|
||
.getResourceGroups(
|
||
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId)
|
||
)
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
}
|
||
|
||
getMetricDefinitions(query) {
|
||
if (
|
||
this.target.queryType !== 'Azure Monitor' ||
|
||
!this.target.azureMonitor.resourceGroup ||
|
||
this.target.azureMonitor.resourceGroup === this.defaultDropdownValue
|
||
) {
|
||
return;
|
||
}
|
||
return this.datasource
|
||
.getMetricDefinitions(
|
||
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId),
|
||
this.replace(this.target.azureMonitor.resourceGroup)
|
||
)
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
}
|
||
|
||
getResourceNames(query) {
|
||
if (
|
||
this.target.queryType !== 'Azure Monitor' ||
|
||
!this.target.azureMonitor.resourceGroup ||
|
||
this.target.azureMonitor.resourceGroup === this.defaultDropdownValue ||
|
||
!this.target.azureMonitor.metricDefinition ||
|
||
this.target.azureMonitor.metricDefinition === this.defaultDropdownValue
|
||
) {
|
||
return;
|
||
}
|
||
|
||
return this.datasource
|
||
.getResourceNames(
|
||
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId),
|
||
this.replace(this.target.azureMonitor.resourceGroup),
|
||
this.replace(this.target.azureMonitor.metricDefinition)
|
||
)
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
}
|
||
|
||
getMetricNames(query) {
|
||
if (
|
||
this.target.queryType !== 'Azure Monitor' ||
|
||
!this.target.azureMonitor.resourceGroup ||
|
||
this.target.azureMonitor.resourceGroup === this.defaultDropdownValue ||
|
||
!this.target.azureMonitor.metricDefinition ||
|
||
this.target.azureMonitor.metricDefinition === this.defaultDropdownValue ||
|
||
!this.target.azureMonitor.resourceName ||
|
||
this.target.azureMonitor.resourceName === this.defaultDropdownValue
|
||
) {
|
||
return;
|
||
}
|
||
|
||
return this.datasource
|
||
.getMetricNames(
|
||
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId),
|
||
this.replace(this.target.azureMonitor.resourceGroup),
|
||
this.replace(this.target.azureMonitor.metricDefinition),
|
||
this.replace(this.target.azureMonitor.resourceName)
|
||
)
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
}
|
||
|
||
onResourceGroupChange() {
|
||
this.target.azureMonitor.metricDefinition = this.defaultDropdownValue;
|
||
this.target.azureMonitor.resourceName = this.defaultDropdownValue;
|
||
this.target.azureMonitor.metricName = this.defaultDropdownValue;
|
||
this.target.azureMonitor.dimensions = [];
|
||
this.target.azureMonitor.dimension = '';
|
||
}
|
||
|
||
onMetricDefinitionChange() {
|
||
this.target.azureMonitor.resourceName = this.defaultDropdownValue;
|
||
this.target.azureMonitor.metricName = this.defaultDropdownValue;
|
||
this.target.azureMonitor.dimensions = [];
|
||
this.target.azureMonitor.dimension = '';
|
||
}
|
||
|
||
onResourceNameChange() {
|
||
this.target.azureMonitor.metricName = this.defaultDropdownValue;
|
||
this.target.azureMonitor.dimensions = [];
|
||
this.target.azureMonitor.dimension = '';
|
||
}
|
||
|
||
onMetricNameChange() {
|
||
if (!this.target.azureMonitor.metricName || this.target.azureMonitor.metricName === this.defaultDropdownValue) {
|
||
return;
|
||
}
|
||
|
||
return this.datasource
|
||
.getMetricMetadata(
|
||
this.replace(this.target.azureMonitor.resourceGroup),
|
||
this.replace(this.target.azureMonitor.metricDefinition),
|
||
this.replace(this.target.azureMonitor.resourceName),
|
||
this.replace(this.target.azureMonitor.metricName)
|
||
)
|
||
.then(metadata => {
|
||
this.target.azureMonitor.aggOptions = metadata.supportedAggTypes || [metadata.primaryAggType];
|
||
this.target.azureMonitor.aggregation = metadata.primaryAggType;
|
||
this.target.azureMonitor.timeGrains = [{ text: 'auto', value: 'auto' }].concat(metadata.supportedTimeGrains);
|
||
|
||
this.target.azureMonitor.dimensions = metadata.dimensions;
|
||
if (metadata.dimensions.length > 0) {
|
||
this.target.azureMonitor.dimension = metadata.dimensions[0].value;
|
||
}
|
||
return this.refresh();
|
||
})
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
}
|
||
|
||
getAutoInterval() {
|
||
if (this.target.azureMonitor.timeGrain === 'auto') {
|
||
return TimegrainConverter.findClosestTimeGrain(
|
||
this.templateSrv.builtIns.__interval.value,
|
||
_.map(this.target.azureMonitor.timeGrains, o =>
|
||
TimegrainConverter.createKbnUnitFromISO8601Duration(o.value)
|
||
) || ['1m', '5m', '15m', '30m', '1h', '6h', '12h', '1d']
|
||
);
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
/* Azure Log Analytics */
|
||
|
||
getWorkspaces = () => {
|
||
return this.datasource.azureLogAnalyticsDatasource
|
||
.getWorkspaces(this.target.subscription)
|
||
.then(list => {
|
||
this.workspaces = list;
|
||
if (list.length > 0 && !this.target.azureLogAnalytics.workspace) {
|
||
this.target.azureLogAnalytics.workspace = list[0].value;
|
||
}
|
||
})
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
};
|
||
|
||
getAzureLogAnalyticsSchema = () => {
|
||
return this.getWorkspaces()
|
||
.then(() => {
|
||
return this.datasource.azureLogAnalyticsDatasource.getSchema(this.target.azureLogAnalytics.workspace);
|
||
})
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
};
|
||
|
||
onLogAnalyticsQueryChange = (nextQuery: string) => {
|
||
this.target.azureLogAnalytics.query = nextQuery;
|
||
};
|
||
|
||
onLogAnalyticsQueryExecute = () => {
|
||
this.panelCtrl.refresh();
|
||
};
|
||
|
||
get templateVariables() {
|
||
return this.templateSrv.variables.map(t => '$' + t.name);
|
||
}
|
||
|
||
/* Application Insights Section */
|
||
|
||
getAppInsightsAutoInterval() {
|
||
const interval = this.templateSrv.builtIns.__interval.value;
|
||
if (interval[interval.length - 1] === 's') {
|
||
return '1m';
|
||
}
|
||
return interval;
|
||
}
|
||
|
||
getAppInsightsMetricNames() {
|
||
if (!this.datasource.appInsightsDatasource.isConfigured()) {
|
||
return;
|
||
}
|
||
|
||
return this.datasource.getAppInsightsMetricNames().catch(this.handleQueryCtrlError.bind(this));
|
||
}
|
||
|
||
getAppInsightsColumns() {
|
||
return this.datasource.getAppInsightsColumns(this.target.refId);
|
||
}
|
||
|
||
onAppInsightsColumnChange() {
|
||
return this.refresh();
|
||
}
|
||
|
||
onAppInsightsMetricNameChange() {
|
||
if (!this.target.appInsights.metricName || this.target.appInsights.metricName === this.defaultDropdownValue) {
|
||
return;
|
||
}
|
||
|
||
return this.datasource
|
||
.getAppInsightsMetricMetadata(this.replace(this.target.appInsights.metricName))
|
||
.then(aggData => {
|
||
this.target.appInsights.aggOptions = aggData.supportedAggTypes;
|
||
this.target.appInsights.groupByOptions = aggData.supportedGroupBy;
|
||
this.target.appInsights.aggregation = aggData.primaryAggType;
|
||
return this.refresh();
|
||
})
|
||
.catch(this.handleQueryCtrlError.bind(this));
|
||
}
|
||
|
||
onAppInsightsQueryChange = (nextQuery: string) => {
|
||
this.target.appInsights.rawQueryString = nextQuery;
|
||
};
|
||
|
||
onAppInsightsQueryExecute = () => {
|
||
return this.refresh();
|
||
};
|
||
|
||
getAppInsightsQuerySchema = () => {
|
||
return this.datasource.appInsightsDatasource.getQuerySchema().catch(this.handleQueryCtrlError.bind(this));
|
||
};
|
||
|
||
getAppInsightsGroupBySegments(query) {
|
||
return _.map(this.target.appInsights.groupByOptions, option => {
|
||
return { text: option, value: option };
|
||
});
|
||
}
|
||
|
||
resetAppInsightsGroupBy() {
|
||
this.target.appInsights.groupBy = 'none';
|
||
this.refresh();
|
||
}
|
||
|
||
updateTimeGrainType() {
|
||
if (this.target.appInsights.timeGrainType === 'specific') {
|
||
this.target.appInsights.timeGrain = '1';
|
||
this.target.appInsights.timeGrainUnit = 'minute';
|
||
} else {
|
||
this.target.appInsights.timeGrain = '';
|
||
}
|
||
this.refresh();
|
||
}
|
||
|
||
toggleEditorMode() {
|
||
this.target.appInsights.rawQuery = !this.target.appInsights.rawQuery;
|
||
}
|
||
}
|