2018-12-18 07:54:41 -06:00
|
|
|
|
import _ from 'lodash';
|
|
|
|
|
import { QueryCtrl } from 'app/plugins/sdk';
|
|
|
|
|
// import './css/query_editor.css';
|
|
|
|
|
import TimegrainConverter from './time_grain_converter';
|
2019-01-29 05:19:31 -06:00
|
|
|
|
// import './monaco/kusto_monaco_editor';
|
|
|
|
|
import './editor/editor_component';
|
2018-12-18 07:54:41 -06:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
/** @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' }];
|
|
|
|
|
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) {
|
|
|
|
|
this.lastQuery = anySeriesFromQuery.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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Azure Monitor Section */
|
|
|
|
|
getResourceGroups(query) {
|
|
|
|
|
if (this.target.queryType !== 'Azure Monitor' || !this.datasource.azureMonitorDatasource.isConfigured()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.datasource.getResourceGroups().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.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.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.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()
|
|
|
|
|
.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));
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-29 05:19:31 -06:00
|
|
|
|
onLogAnalyticsQueryChange = (nextQuery: string) => {
|
|
|
|
|
this.target.azureLogAnalytics.query = nextQuery;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onLogAnalyticsQueryExecute = () => {
|
|
|
|
|
this.panelCtrl.refresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get templateVariables() {
|
|
|
|
|
return this.templateSrv.variables.map(t => '$' + t.name);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-18 07:54:41 -06:00
|
|
|
|
/* 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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|