mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Azure: Application Insights metrics to Frame and support multiple query dimensions (#25849)
- The Application Insights Service now returns a dataframe. This is a "wide" formatted dataframe with a single time index. - Multiple "group by" dimensions may now be selected instead of just one with Application Insights. - Some types are copied / slightly altered from the Azure Go SDK but that SDK is not imported at this time. Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
@@ -375,7 +375,7 @@ describe('AppInsightsDatasource', () => {
|
||||
expect(options.url).toContain('/api/ds/query');
|
||||
expect(options.data.queries[0].appInsights.rawQueryString).toBeUndefined();
|
||||
expect(options.data.queries[0].appInsights.metricName).toBe('exceptions/server');
|
||||
expect(options.data.queries[0].appInsights.dimension).toBe('client/city');
|
||||
expect([...options.data.queries[0].appInsights.dimension]).toMatchObject(['client/city']);
|
||||
return Promise.resolve({ data: response, status: 200 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ScopedVars } from '@grafana/data';
|
||||
import { DataQueryRequest, DataSourceInstanceSettings } from '@grafana/data';
|
||||
import { getBackendSrv, getTemplateSrv, DataSourceWithBackend } from '@grafana/runtime';
|
||||
import _ from 'lodash';
|
||||
import _, { isString } from 'lodash';
|
||||
|
||||
import TimegrainConverter from '../time_grain_converter';
|
||||
import { AzureDataSourceJsonData, AzureMonitorQuery, AzureQueryType } from '../types';
|
||||
@@ -84,12 +84,24 @@ export default class AppInsightsDatasource extends DataSourceWithBackend<AzureMo
|
||||
|
||||
// migration for non-standard names
|
||||
if (old.groupBy && !item.dimension) {
|
||||
item.dimension = old.groupBy;
|
||||
item.dimension = [old.groupBy];
|
||||
}
|
||||
if (old.filter && !item.dimensionFilter) {
|
||||
item.dimensionFilter = old.filter;
|
||||
}
|
||||
|
||||
// Migrate single dimension string to array
|
||||
if (isString(item.dimension)) {
|
||||
if (item.dimension === 'None') {
|
||||
item.dimension = [];
|
||||
} else {
|
||||
item.dimension = [item.dimension as string];
|
||||
}
|
||||
}
|
||||
if (!item.dimension) {
|
||||
item.dimension = [];
|
||||
}
|
||||
|
||||
const templateSrv = getTemplateSrv();
|
||||
|
||||
return {
|
||||
@@ -102,7 +114,7 @@ export default class AppInsightsDatasource extends DataSourceWithBackend<AzureMo
|
||||
allowedTimeGrainsMs: item.allowedTimeGrainsMs,
|
||||
metricName: templateSrv.replace(item.metricName, scopedVars),
|
||||
aggregation: templateSrv.replace(item.aggregation, scopedVars),
|
||||
dimension: templateSrv.replace(item.dimension, scopedVars),
|
||||
dimension: item.dimension.map(d => templateSrv.replace(d, scopedVars)),
|
||||
dimensionFilter: templateSrv.replace(item.dimensionFilter, scopedVars),
|
||||
alias: item.alias,
|
||||
format: target.format,
|
||||
|
||||
@@ -363,27 +363,30 @@
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword width-9">Group By</label>
|
||||
</div>
|
||||
<div ng-repeat="d in ctrl.target.appInsights.dimension track by $index"
|
||||
class="gf-form"
|
||||
ng-click="ctrl.removeGroupBy($index);"
|
||||
onmouseover="this.style['text-decoration'] = 'line-through';"
|
||||
onmouseout="this.style['text-decoration'] = '';">
|
||||
<label class="gf-form-label"
|
||||
style="cursor: pointer;">{{d}} <icon name="'times'"></icon></label>
|
||||
</div>
|
||||
<div>
|
||||
<gf-form-dropdown
|
||||
allow-custom="true"
|
||||
ng-hide="ctrl.target.appInsights.dimension !== 'none'"
|
||||
model="ctrl.target.appInsights.dimension"
|
||||
lookup-text="true"
|
||||
placeholder="Add"
|
||||
model="ctrl.dummyDiminsionString"
|
||||
get-options="ctrl.getAppInsightsGroupBySegments($query)"
|
||||
on-change="ctrl.refresh()"
|
||||
css-class="min-width-20"
|
||||
on-change="ctrl.getAppInsightsGroupBySegments"
|
||||
css-class="min-width-5"
|
||||
>
|
||||
</gf-form-dropdown>
|
||||
<label
|
||||
class="gf-form-label min-width-20 pointer"
|
||||
ng-hide="ctrl.target.appInsights.dimension === 'none'"
|
||||
ng-click="ctrl.resetAppInsightsGroupBy()"
|
||||
>{{ctrl.target.appInsights.dimension}}
|
||||
<icon name="'times'"></icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword width-9">Filter</label>
|
||||
<label class="gf-form-label query-keyword">Filter</label>
|
||||
<input
|
||||
type="text"
|
||||
class="gf-form-input width-17"
|
||||
|
||||
@@ -40,7 +40,7 @@ describe('AzureMonitorQueryCtrl', () => {
|
||||
expect(queryCtrl.target.azureMonitor.resourceName).toBe('select');
|
||||
expect(queryCtrl.target.azureMonitor.metricNamespace).toBe('select');
|
||||
expect(queryCtrl.target.azureMonitor.metricName).toBe('select');
|
||||
expect(queryCtrl.target.appInsights.dimension).toBe('none');
|
||||
expect(queryCtrl.target.appInsights.dimension).toMatchObject([]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
|
||||
|
||||
defaultDropdownValue = 'select';
|
||||
|
||||
dummyDiminsionString = '+';
|
||||
|
||||
target: {
|
||||
// should be: AzureMonitorQuery
|
||||
refId: string;
|
||||
@@ -104,7 +106,7 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
|
||||
},
|
||||
appInsights: {
|
||||
metricName: this.defaultDropdownValue,
|
||||
dimension: 'none',
|
||||
// dimension: [],
|
||||
timeGrain: 'auto',
|
||||
},
|
||||
insightsAnalytics: {
|
||||
@@ -135,6 +137,8 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
|
||||
|
||||
this.migrateApplicationInsightsKeys();
|
||||
|
||||
this.migrateApplicationInsightsDimensions();
|
||||
|
||||
this.panelCtrl.events.on(PanelEvents.dataReceived, this.onDataReceived.bind(this), $scope);
|
||||
this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope);
|
||||
this.resultFormats = [
|
||||
@@ -270,6 +274,18 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
migrateApplicationInsightsDimensions() {
|
||||
const { appInsights } = this.target;
|
||||
|
||||
if (!appInsights.dimension) {
|
||||
appInsights.dimension = [];
|
||||
}
|
||||
|
||||
if (_.isString(appInsights.dimension)) {
|
||||
appInsights.dimension = [appInsights.dimension as string];
|
||||
}
|
||||
}
|
||||
|
||||
replace(variable: string) {
|
||||
return this.templateSrv.replace(variable, this.panelCtrl.panel.scopedVars);
|
||||
}
|
||||
@@ -625,8 +641,27 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
|
||||
return this.datasource.appInsightsDatasource.getQuerySchema().catch(this.handleQueryCtrlError.bind(this));
|
||||
};
|
||||
|
||||
removeGroupBy = (index: number) => {
|
||||
const { appInsights } = this.target;
|
||||
appInsights.dimension.splice(index, 1);
|
||||
this.refresh();
|
||||
};
|
||||
|
||||
getAppInsightsGroupBySegments(query: any) {
|
||||
return _.map(this.target.appInsights.dimensions, (option: string) => {
|
||||
const { appInsights } = this.target;
|
||||
|
||||
// HACK alert... there must be a better way!
|
||||
if (this.dummyDiminsionString && this.dummyDiminsionString.length && '+' !== this.dummyDiminsionString) {
|
||||
if (!appInsights.dimension) {
|
||||
appInsights.dimension = [];
|
||||
}
|
||||
appInsights.dimension.push(this.dummyDiminsionString);
|
||||
this.dummyDiminsionString = '+';
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
// Return the list of dimensions stored on the query object from the last request :(
|
||||
return _.map(appInsights.dimensions, (option: string) => {
|
||||
return { text: option, value: option };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ export interface ApplicationInsightsQuery {
|
||||
timeGrain: string;
|
||||
allowedTimeGrainsMs: number[];
|
||||
aggregation: string;
|
||||
dimension: string;
|
||||
dimension: string[]; // Was string before 7.1
|
||||
// dimensions: string[]; why is this metadata stored on the object!
|
||||
dimensionFilter: string;
|
||||
alias: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user