noImplicitAny: Azure Monitor (#17966)

This commit is contained in:
Tobias Skarhed 2019-07-06 07:01:22 +02:00 committed by Torkel Ödegaard
parent 83366b91de
commit baed5d7bd9
17 changed files with 138 additions and 122 deletions

View File

@ -8,17 +8,17 @@ export default class AppInsightsQuerystringBuilder {
timeGrainUnit = ''; timeGrainUnit = '';
filter = ''; filter = '';
constructor(private from, private to, public grafanaInterval) {} constructor(private from: any, private to: any, public grafanaInterval: any) {}
setAggregation(aggregation) { setAggregation(aggregation: string) {
this.aggregation = aggregation; this.aggregation = aggregation;
} }
setGroupBy(groupBy) { setGroupBy(groupBy: string) {
this.groupBy = groupBy; this.groupBy = groupBy;
} }
setInterval(timeGrainType, timeGrain, timeGrainUnit) { setInterval(timeGrainType: string, timeGrain: any, timeGrainUnit: string) {
this.timeGrainType = timeGrainType; this.timeGrainType = timeGrainType;
this.timeGrain = timeGrain; this.timeGrain = timeGrain;
this.timeGrainUnit = timeGrainUnit; this.timeGrainUnit = timeGrainUnit;

View File

@ -2,7 +2,7 @@ import _ from 'lodash';
import { dateTime } from '@grafana/ui/src/utils/moment_wrapper'; import { dateTime } from '@grafana/ui/src/utils/moment_wrapper';
export default class ResponseParser { export default class ResponseParser {
constructor(private results) {} constructor(private results: any) {}
parseQueryResult() { parseQueryResult() {
let data: any = []; let data: any = [];
@ -27,17 +27,17 @@ export default class ResponseParser {
return data; return data;
} }
parseRawQueryResultRow(query: any, columns, rows, xaxis: string, yaxises: string, spliton: string) { parseRawQueryResultRow(query: any, columns: any, rows: any, xaxis: string, yaxises: string, spliton: string) {
const data: any[] = []; const data: any[] = [];
const columnsForDropdown = _.map(columns, column => ({ text: column.ColumnName, value: column.ColumnName })); const columnsForDropdown = _.map(columns, column => ({ text: column.ColumnName, value: column.ColumnName }));
const xaxisColumn = columns.findIndex(column => column.ColumnName === xaxis); const xaxisColumn = columns.findIndex((column: any) => column.ColumnName === xaxis);
const yaxisesSplit = yaxises.split(','); const yaxisesSplit = yaxises.split(',');
const yaxisColumns = {}; const yaxisColumns: any = {};
_.forEach(yaxisesSplit, yaxis => { _.forEach(yaxisesSplit, yaxis => {
yaxisColumns[yaxis] = columns.findIndex(column => column.ColumnName === yaxis); yaxisColumns[yaxis] = columns.findIndex((column: any) => column.ColumnName === yaxis);
}); });
const splitonColumn = columns.findIndex(column => column.ColumnName === spliton); const splitonColumn = columns.findIndex((column: any) => column.ColumnName === spliton);
const convertTimestamp = xaxis === 'timestamp'; const convertTimestamp = xaxis === 'timestamp';
_.forEach(rows, row => { _.forEach(rows, row => {
@ -57,7 +57,7 @@ export default class ResponseParser {
return data; return data;
} }
parseQueryResultRow(query: any, value, alias: string) { parseQueryResultRow(query: any, value: any, alias: string) {
const data: any[] = []; const data: any[] = [];
if (ResponseParser.isSingleValue(value)) { if (ResponseParser.isSingleValue(value)) {
@ -108,7 +108,7 @@ export default class ResponseParser {
return data; return data;
} }
getTargetName(segment, alias: string) { getTargetName(segment: { [x: string]: string }, alias: string) {
let metric = ''; let metric = '';
let segmentName = ''; let segmentName = '';
let segmentValue = ''; let segmentValue = '';
@ -141,11 +141,11 @@ export default class ResponseParser {
return metric + `{${segmentName}="${segmentValue}"}`; return metric + `{${segmentName}="${segmentValue}"}`;
} }
static isSingleValue(value) { static isSingleValue(value: any) {
return !ResponseParser.hasSegmentsField(value); return !ResponseParser.hasSegmentsField(value);
} }
static findOrCreateBucket(data, target) { static findOrCreateBucket(data: any[], target: string) {
let dataTarget: any = _.find(data, ['target', target]); let dataTarget: any = _.find(data, ['target', target]);
if (!dataTarget) { if (!dataTarget) {
dataTarget = { target: target, datapoints: [] }; dataTarget = { target: target, datapoints: [] };
@ -155,12 +155,12 @@ export default class ResponseParser {
return dataTarget; return dataTarget;
} }
static hasSegmentsField(obj) { static hasSegmentsField(obj: any) {
const keys = _.keys(obj); const keys = _.keys(obj);
return _.indexOf(keys, 'segments') > -1; return _.indexOf(keys, 'segments') > -1;
} }
static getMetricFieldKey(segment) { static getMetricFieldKey(segment: { [x: string]: any }) {
const keys = _.keys(segment); const keys = _.keys(segment);
return _.filter(_.without(keys, 'start', 'end'), key => { return _.filter(_.without(keys, 'start', 'end'), key => {
@ -168,16 +168,16 @@ export default class ResponseParser {
})[0]; })[0];
} }
static getKeyForAggregationField(dataObj): string { static getKeyForAggregationField(dataObj: any): string {
const keys = _.keys(dataObj); const keys = _.keys(dataObj);
return _.intersection(keys, ['sum', 'avg', 'min', 'max', 'count', 'unique'])[0]; return _.intersection(keys, ['sum', 'avg', 'min', 'max', 'count', 'unique'])[0];
} }
static dateTimeToEpoch(dateTimeValue) { static dateTimeToEpoch(dateTimeValue: any) {
return dateTime(dateTimeValue).valueOf(); return dateTime(dateTimeValue).valueOf();
} }
static parseMetricNames(result) { static parseMetricNames(result: { data: { metrics: any } }) {
const keys = _.keys(result.data.metrics); const keys = _.keys(result.data.metrics);
return ResponseParser.toTextValueList(keys); return ResponseParser.toTextValueList(keys);
@ -202,7 +202,7 @@ export default class ResponseParser {
} }
parseQuerySchema() { parseQuerySchema() {
const result = { const result: any = {
Type: 'AppInsights', Type: 'AppInsights',
Tables: {}, Tables: {},
}; };
@ -225,7 +225,7 @@ export default class ResponseParser {
return result; return result;
} }
static toTextValueList(values) { static toTextValueList(values: any) {
const list: any[] = []; const list: any[] = [];
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
list.push({ list.push({

View File

@ -1,5 +1,6 @@
import AzureMonitorDatasource from '../datasource'; import AzureMonitorDatasource from '../datasource';
import FakeSchemaData from './__mocks__/schema'; import FakeSchemaData from './__mocks__/schema';
// @ts-ignore
import Q from 'q'; import Q from 'q';
import { TemplateSrv } from 'app/features/templating/template_srv'; import { TemplateSrv } from 'app/features/templating/template_srv';
import { KustoSchema } from '../types'; import { KustoSchema } from '../types';
@ -49,8 +50,8 @@ describe('AzureLogAnalyticsDatasource', () => {
], ],
}; };
let workspacesUrl; let workspacesUrl: string;
let azureLogAnalyticsUrl; let azureLogAnalyticsUrl: string;
beforeEach(async () => { beforeEach(async () => {
ctx.instanceSettings.jsonData.subscriptionId = 'xxx'; ctx.instanceSettings.jsonData.subscriptionId = 'xxx';
@ -101,7 +102,7 @@ describe('AzureLogAnalyticsDatasource', () => {
}); });
it('should return error status and a detailed error message', () => { it('should return error status and a detailed error message', () => {
return ctx.ds.testDatasource().then(results => { return ctx.ds.testDatasource().then((results: any) => {
expect(results.status).toEqual('error'); expect(results.status).toEqual('error');
expect(results.message).toEqual( expect(results.message).toEqual(
'1. Azure Log Analytics: Bad Request: InvalidApiVersionParameter. An error message. ' '1. Azure Log Analytics: Bad Request: InvalidApiVersionParameter. An error message. '
@ -174,7 +175,7 @@ describe('AzureLogAnalyticsDatasource', () => {
}); });
it('should return a list of datapoints', () => { it('should return a list of datapoints', () => {
return ctx.ds.query(options).then(results => { return ctx.ds.query(options).then((results: any) => {
expect(results.data.length).toBe(2); expect(results.data.length).toBe(2);
expect(results.data[0].datapoints.length).toBe(2); expect(results.data[0].datapoints.length).toBe(2);
expect(results.data[0].target).toEqual('Administrative'); expect(results.data[0].target).toEqual('Administrative');
@ -213,7 +214,7 @@ describe('AzureLogAnalyticsDatasource', () => {
}); });
it('should throw an exception', () => { it('should throw an exception', () => {
ctx.ds.query(options).catch(err => { ctx.ds.query(options).catch((err: any) => {
expect(err.message).toContain('The Time Series format requires a time column.'); expect(err.message).toContain('The Time Series format requires a time column.');
}); });
}); });
@ -230,7 +231,7 @@ describe('AzureLogAnalyticsDatasource', () => {
}); });
it('should return a list of columns and rows', () => { it('should return a list of columns and rows', () => {
return ctx.ds.query(options).then(results => { return ctx.ds.query(options).then((results: any) => {
expect(results.data[0].type).toBe('table'); expect(results.data[0].type).toBe('table');
expect(results.data[0].columns.length).toBe(3); expect(results.data[0].columns.length).toBe(3);
expect(results.data[0].rows.length).toBe(3); expect(results.data[0].rows.length).toBe(3);
@ -300,7 +301,7 @@ describe('AzureLogAnalyticsDatasource', () => {
], ],
}; };
let queryResults; let queryResults: any[];
beforeEach(async () => { beforeEach(async () => {
ctx.backendSrv.datasourceRequest = (options: { url: string }) => { ctx.backendSrv.datasourceRequest = (options: { url: string }) => {
@ -359,7 +360,7 @@ describe('AzureLogAnalyticsDatasource', () => {
], ],
}; };
let annotationResults; let annotationResults: any[];
beforeEach(async () => { beforeEach(async () => {
ctx.backendSrv.datasourceRequest = (options: { url: string }) => { ctx.backendSrv.datasourceRequest = (options: { url: string }) => {

View File

@ -5,6 +5,7 @@ import { AzureMonitorQuery, AzureDataSourceJsonData } from '../types';
import { DataQueryRequest, DataSourceInstanceSettings } from '@grafana/ui/src/types'; import { DataQueryRequest, DataSourceInstanceSettings } from '@grafana/ui/src/types';
import { BackendSrv } from 'app/core/services/backend_srv'; import { BackendSrv } from 'app/core/services/backend_srv';
import { TemplateSrv } from 'app/features/templating/template_srv'; import { TemplateSrv } from 'app/features/templating/template_srv';
import { IQService } from 'angular';
export default class AzureLogAnalyticsDatasource { export default class AzureLogAnalyticsDatasource {
id: number; id: number;
@ -20,7 +21,7 @@ export default class AzureLogAnalyticsDatasource {
private instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>, private instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>,
private backendSrv: BackendSrv, private backendSrv: BackendSrv,
private templateSrv: TemplateSrv, private templateSrv: TemplateSrv,
private $q private $q: IQService
) { ) {
this.id = instanceSettings.id; this.id = instanceSettings.id;
this.baseUrl = this.instanceSettings.jsonData.azureLogAnalyticsSameAs this.baseUrl = this.instanceSettings.jsonData.azureLogAnalyticsSameAs
@ -57,7 +58,7 @@ export default class AzureLogAnalyticsDatasource {
const workspaceListUrl = const workspaceListUrl =
this.azureMonitorUrl + this.azureMonitorUrl +
`/${subscriptionId}/providers/Microsoft.OperationalInsights/workspaces?api-version=2017-04-26-preview`; `/${subscriptionId}/providers/Microsoft.OperationalInsights/workspaces?api-version=2017-04-26-preview`;
return this.doRequest(workspaceListUrl).then(response => { return this.doRequest(workspaceListUrl).then((response: any) => {
return ( return (
_.map(response.data.value, val => { _.map(response.data.value, val => {
return { text: val.name, value: val.properties.customerId }; return { text: val.name, value: val.properties.customerId };
@ -72,7 +73,7 @@ export default class AzureLogAnalyticsDatasource {
} }
const url = `${this.baseUrl}/${workspace}/metadata`; const url = `${this.baseUrl}/${workspace}/metadata`;
return this.doRequest(url).then(response => { return this.doRequest(url).then((response: any) => {
return new ResponseParser(response.data).parseSchemaResult(); return new ResponseParser(response.data).parseSchemaResult();
}); });
} }
@ -118,7 +119,7 @@ export default class AzureLogAnalyticsDatasource {
} }
metricFindQuery(query: string) { metricFindQuery(query: string) {
return this.getDefaultOrFirstWorkspace().then(workspace => { return this.getDefaultOrFirstWorkspace().then((workspace: any) => {
const queries: any[] = this.buildQuery(query, null, workspace); const queries: any[] = this.buildQuery(query, null, workspace);
const promises = this.doQueries(queries); const promises = this.doQueries(queries);
@ -161,7 +162,7 @@ export default class AzureLogAnalyticsDatasource {
return queries; return queries;
} }
interpolateVariable(value, variable) { interpolateVariable(value: string, variable: { multi: any; includeAll: any }) {
if (typeof value === 'string') { if (typeof value === 'string') {
if (variable.multi || variable.includeAll) { if (variable.multi || variable.includeAll) {
return "'" + value + "'"; return "'" + value + "'";
@ -189,13 +190,13 @@ export default class AzureLogAnalyticsDatasource {
return Promise.resolve(this.defaultOrFirstWorkspace); return Promise.resolve(this.defaultOrFirstWorkspace);
} }
return this.getWorkspaces(this.subscriptionId).then(workspaces => { return this.getWorkspaces(this.subscriptionId).then((workspaces: any[]) => {
this.defaultOrFirstWorkspace = workspaces[0].value; this.defaultOrFirstWorkspace = workspaces[0].value;
return this.defaultOrFirstWorkspace; return this.defaultOrFirstWorkspace;
}); });
} }
annotationQuery(options) { annotationQuery(options: any) {
if (!options.annotation.rawQuery) { if (!options.annotation.rawQuery) {
return this.$q.reject({ return this.$q.reject({
message: 'Query missing in annotation definition', message: 'Query missing in annotation definition',
@ -212,16 +213,16 @@ export default class AzureLogAnalyticsDatasource {
}); });
} }
doQueries(queries) { doQueries(queries: any[]) {
return _.map(queries, query => { return _.map(queries, query => {
return this.doRequest(query.url) return this.doRequest(query.url)
.then(result => { .then((result: any) => {
return { return {
result: result, result: result,
query: query, query: query,
}; };
}) })
.catch(err => { .catch((err: any) => {
throw { throw {
error: err, error: err,
query: query, query: query,
@ -230,13 +231,13 @@ export default class AzureLogAnalyticsDatasource {
}); });
} }
doRequest(url, maxRetries = 1) { doRequest(url: string, maxRetries = 1) {
return this.backendSrv return this.backendSrv
.datasourceRequest({ .datasourceRequest({
url: this.url + url, url: this.url + url,
method: 'GET', method: 'GET',
}) })
.catch(error => { .catch((error: any) => {
if (maxRetries > 0) { if (maxRetries > 0) {
return this.doRequest(url, maxRetries - 1); return this.doRequest(url, maxRetries - 1);
} }
@ -252,12 +253,12 @@ export default class AzureLogAnalyticsDatasource {
} }
return this.getDefaultOrFirstWorkspace() return this.getDefaultOrFirstWorkspace()
.then(ws => { .then((ws: any) => {
const url = `${this.baseUrl}/${ws}/metadata`; const url = `${this.baseUrl}/${ws}/metadata`;
return this.doRequest(url); return this.doRequest(url);
}) })
.then(response => { .then((response: any) => {
if (response.status === 200) { if (response.status === 200) {
return { return {
status: 'success', status: 'success',
@ -271,7 +272,7 @@ export default class AzureLogAnalyticsDatasource {
message: 'Returned http status code ' + response.status, message: 'Returned http status code ' + response.status,
}; };
}) })
.catch(error => { .catch((error: any) => {
let message = 'Azure Log Analytics: '; let message = 'Azure Log Analytics: ';
if (error.config && error.config.url && error.config.url.indexOf('workspacesloganalytics') > -1) { if (error.config && error.config.url && error.config.url.indexOf('workspacesloganalytics') > -1) {
message = 'Azure Log Analytics requires access to Azure Monitor but had the following error: '; message = 'Azure Log Analytics requires access to Azure Monitor but had the following error: ';

View File

@ -13,7 +13,7 @@ import { TimeSeries, AnnotationEvent } from '@grafana/ui/src/types';
export default class ResponseParser { export default class ResponseParser {
columns: string[]; columns: string[];
constructor(private results) {} constructor(private results: any) {}
parseQueryResult(): any { parseQueryResult(): any {
let data: any[] = []; let data: any[] = [];
@ -35,7 +35,7 @@ export default class ResponseParser {
return data; return data;
} }
parseTimeSeriesResult(query, columns, rows): TimeSeries[] { parseTimeSeriesResult(query: { refId: string; query: any }, columns: any[], rows: any): TimeSeries[] {
const data: TimeSeries[] = []; const data: TimeSeries[] = [];
let timeIndex = -1; let timeIndex = -1;
let metricIndex = -1; let metricIndex = -1;
@ -73,7 +73,7 @@ export default class ResponseParser {
return data; return data;
} }
parseTableResult(query, columns, rows): AzureLogsTableData { parseTableResult(query: { refId: string; query: string }, columns: any[], rows: any[]): AzureLogsTableData {
const tableResult: AzureLogsTableData = { const tableResult: AzureLogsTableData = {
type: 'table', type: 'table',
columns: _.map(columns, col => { columns: _.map(columns, col => {
@ -206,7 +206,7 @@ export default class ResponseParser {
return functions; return functions;
} }
static findOrCreateBucket(data, target): TimeSeries { static findOrCreateBucket(data: TimeSeries[], target: any): TimeSeries {
let dataTarget: any = _.find(data, ['target', target]); let dataTarget: any = _.find(data, ['target', target]);
if (!dataTarget) { if (!dataTarget) {
dataTarget = { target: target, datapoints: [], refId: '', query: '' }; dataTarget = { target: target, datapoints: [], refId: '', query: '' };
@ -216,7 +216,7 @@ export default class ResponseParser {
return dataTarget; return dataTarget;
} }
static dateTimeToEpoch(dateTimeValue) { static dateTimeToEpoch(dateTimeValue: any) {
return dateTime(dateTimeValue).valueOf(); return dateTime(dateTimeValue).valueOf();
} }
} }

View File

@ -1,4 +1,5 @@
import AzureMonitorDatasource from '../datasource'; import AzureMonitorDatasource from '../datasource';
// @ts-ignore
import Q from 'q'; import Q from 'q';
import { TemplateSrv } from 'app/features/templating/template_srv'; import { TemplateSrv } from 'app/features/templating/template_srv';
import { toUtc } from '@grafana/ui/src/utils/moment_wrapper'; import { toUtc } from '@grafana/ui/src/utils/moment_wrapper';
@ -42,7 +43,7 @@ describe('AzureMonitorDatasource', () => {
}); });
it('should return error status and a detailed error message', () => { it('should return error status and a detailed error message', () => {
return ctx.ds.testDatasource().then(results => { return ctx.ds.testDatasource().then((results: any) => {
expect(results.status).toEqual('error'); expect(results.status).toEqual('error');
expect(results.message).toEqual( expect(results.message).toEqual(
'1. Azure Monitor: Bad Request: InvalidApiVersionParameter. An error message. ' '1. Azure Monitor: Bad Request: InvalidApiVersionParameter. An error message. '
@ -69,7 +70,7 @@ describe('AzureMonitorDatasource', () => {
}); });
it('should return success status', () => { it('should return success status', () => {
return ctx.ds.testDatasource().then(results => { return ctx.ds.testDatasource().then((results: any) => {
expect(results.status).toEqual('success'); expect(results.status).toEqual('success');
}); });
}); });
@ -99,7 +100,7 @@ describe('AzureMonitorDatasource', () => {
], ],
}; };
const response = { const response: any = {
results: { results: {
A: { A: {
refId: 'A', refId: 'A',
@ -128,7 +129,7 @@ describe('AzureMonitorDatasource', () => {
}); });
it('should return a list of datapoints', () => { it('should return a list of datapoints', () => {
return ctx.ds.query(options).then(results => { return ctx.ds.query(options).then((results: any) => {
expect(results.data.length).toBe(1); expect(results.data.length).toBe(1);
expect(results.data[0].name).toEqual('Percentage CPU'); expect(results.data[0].name).toEqual('Percentage CPU');
expect(results.data[0].rows[0][1]).toEqual(1558278660000); expect(results.data[0].rows[0][1]).toEqual(1558278660000);
@ -362,7 +363,7 @@ describe('AzureMonitorDatasource', () => {
.metricFindQuery( .metricFindQuery(
'resourceNames(11112222-eeee-4949-9b2d-9106972f9123, nodeapp, microsoft.insights/components )' 'resourceNames(11112222-eeee-4949-9b2d-9106972f9123, nodeapp, microsoft.insights/components )'
) )
.then(results => { .then((results: any) => {
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
expect(results[0].text).toEqual('nodeapp'); expect(results[0].text).toEqual('nodeapp');
expect(results[0].value).toEqual('nodeapp'); expect(results[0].value).toEqual('nodeapp');
@ -886,7 +887,7 @@ describe('AzureMonitorDatasource', () => {
'resource1', 'resource1',
'Transactions' 'Transactions'
) )
.then(results => { .then((results: any) => {
expect(results.dimensions.length).toEqual(4); expect(results.dimensions.length).toEqual(4);
expect(results.dimensions[0].text).toEqual('None'); expect(results.dimensions[0].text).toEqual('None');
expect(results.dimensions[0].value).toEqual('None'); expect(results.dimensions[0].value).toEqual('None');
@ -904,7 +905,7 @@ describe('AzureMonitorDatasource', () => {
'resource1', 'resource1',
'FreeCapacity' 'FreeCapacity'
) )
.then(results => { .then((results: any) => {
expect(results.dimensions.length).toEqual(0); expect(results.dimensions.length).toEqual(0);
}); });
}); });

View File

@ -138,7 +138,7 @@ export default class AzureMonitorDatasource {
return Promise.resolve([]); return Promise.resolve([]);
} }
annotationQuery(options) {} annotationQuery(options: any) {}
metricFindQuery(query: string) { metricFindQuery(query: string) {
const subscriptionsQuery = query.match(/^Subscriptions\(\)/i); const subscriptionsQuery = query.match(/^Subscriptions\(\)/i);
@ -236,7 +236,7 @@ export default class AzureMonitorDatasource {
.then((result: AzureMonitorMetricDefinitionsResponse) => { .then((result: AzureMonitorMetricDefinitionsResponse) => {
return ResponseParser.parseResponseValues(result, 'type', 'type'); return ResponseParser.parseResponseValues(result, 'type', 'type');
}) })
.then(result => { .then((result: any) => {
return _.filter(result, t => { return _.filter(result, t => {
for (let i = 0; i < this.supportedMetricNamespaces.length; i++) { for (let i = 0; i < this.supportedMetricNamespaces.length; i++) {
if (t.value.toLowerCase() === this.supportedMetricNamespaces[i].toLowerCase()) { if (t.value.toLowerCase() === this.supportedMetricNamespaces[i].toLowerCase()) {
@ -247,7 +247,7 @@ export default class AzureMonitorDatasource {
return false; return false;
}); });
}) })
.then(result => { .then((result: any) => {
let shouldHardcodeBlobStorage = false; let shouldHardcodeBlobStorage = false;
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
if (result[i].value === 'Microsoft.Storage/storageAccounts') { if (result[i].value === 'Microsoft.Storage/storageAccounts') {
@ -284,7 +284,7 @@ export default class AzureMonitorDatasource {
this.apiVersion this.apiVersion
}`; }`;
return this.doRequest(url).then(result => { return this.doRequest(url).then((result: any) => {
if (!_.startsWith(metricDefinition, 'Microsoft.Storage/storageAccounts/')) { if (!_.startsWith(metricDefinition, 'Microsoft.Storage/storageAccounts/')) {
return ResponseParser.parseResourceNames(result, metricDefinition); return ResponseParser.parseResourceNames(result, metricDefinition);
} }
@ -309,7 +309,7 @@ export default class AzureMonitorDatasource {
this.apiVersion this.apiVersion
); );
return this.doRequest(url).then(result => { return this.doRequest(url).then((result: any) => {
return ResponseParser.parseResponseValues(result, 'name.localizedValue', 'name.value'); return ResponseParser.parseResponseValues(result, 'name.localizedValue', 'name.value');
}); });
} }
@ -330,7 +330,7 @@ export default class AzureMonitorDatasource {
this.apiVersion this.apiVersion
); );
return this.doRequest(url).then(result => { return this.doRequest(url).then((result: any) => {
return ResponseParser.parseMetadata(result, metricName); return ResponseParser.parseMetadata(result, metricName);
}); });
} }
@ -352,7 +352,7 @@ export default class AzureMonitorDatasource {
const url = `/${this.cloudName}/subscriptions?api-version=2019-03-01`; const url = `/${this.cloudName}/subscriptions?api-version=2019-03-01`;
return this.doRequest(url) return this.doRequest(url)
.then(response => { .then((response: any) => {
if (response.status === 200) { if (response.status === 200) {
return { return {
status: 'success', status: 'success',
@ -366,7 +366,7 @@ export default class AzureMonitorDatasource {
message: 'Returned http status code ' + response.status, message: 'Returned http status code ' + response.status,
}; };
}) })
.catch(error => { .catch((error: any) => {
let message = 'Azure Monitor: '; let message = 'Azure Monitor: ';
message += error.statusText ? error.statusText + ': ' : ''; message += error.statusText ? error.statusText + ': ' : '';
@ -390,13 +390,13 @@ export default class AzureMonitorDatasource {
return field && field.length > 0; return field && field.length > 0;
} }
doRequest(url, maxRetries = 1) { doRequest(url: string, maxRetries = 1) {
return this.backendSrv return this.backendSrv
.datasourceRequest({ .datasourceRequest({
url: this.url + url, url: this.url + url,
method: 'GET', method: 'GET',
}) })
.catch(error => { .catch((error: any) => {
if (maxRetries > 0) { if (maxRetries > 0) {
return this.doRequest(url, maxRetries - 1); return this.doRequest(url, maxRetries - 1);
} }

View File

@ -2,6 +2,9 @@ import AzureLogAnalyticsDatasource from './azure_log_analytics/azure_log_analyti
import config from 'app/core/config'; import config from 'app/core/config';
import { isVersionGtOrEq } from 'app/core/utils/version'; import { isVersionGtOrEq } from 'app/core/utils/version';
import AzureMonitorDatasource from './azure_monitor/azure_monitor_datasource'; import AzureMonitorDatasource from './azure_monitor/azure_monitor_datasource';
import { BackendSrv } from 'app/core/services/backend_srv';
import { IQService } from 'angular';
import { TemplateSrv } from 'app/features/templating/template_srv';
interface AzureCloud { interface AzureCloud {
key: string; key: string;
@ -22,7 +25,7 @@ export class AzureMonitorConfigCtrl {
token: string; token: string;
/** @ngInject */ /** @ngInject */
constructor(private backendSrv, private $q, private templateSrv) { constructor(private backendSrv: BackendSrv, private $q: IQService, private templateSrv: TemplateSrv) {
this.hasRequiredGrafanaVersion = this.hasMinVersion(); this.hasRequiredGrafanaVersion = this.hasMinVersion();
this.current.jsonData.cloudName = this.current.jsonData.cloudName || 'azuremonitor'; this.current.jsonData.cloudName = this.current.jsonData.cloudName || 'azuremonitor';
this.current.jsonData.azureLogAnalyticsSameAs = this.current.jsonData.azureLogAnalyticsSameAs || false; this.current.jsonData.azureLogAnalyticsSameAs = this.current.jsonData.azureLogAnalyticsSameAs || false;

View File

@ -6,6 +6,7 @@ import { AzureMonitorQuery, AzureDataSourceJsonData } from './types';
import { DataSourceApi, DataQueryRequest, DataSourceInstanceSettings } from '@grafana/ui/src/types'; import { DataSourceApi, DataQueryRequest, DataSourceInstanceSettings } from '@grafana/ui/src/types';
import { BackendSrv } from 'app/core/services/backend_srv'; import { BackendSrv } from 'app/core/services/backend_srv';
import { TemplateSrv } from 'app/features/templating/template_srv'; import { TemplateSrv } from 'app/features/templating/template_srv';
import { IQService } from 'angular';
export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDataSourceJsonData> { export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDataSourceJsonData> {
azureMonitorDatasource: AzureMonitorDatasource; azureMonitorDatasource: AzureMonitorDatasource;
@ -17,7 +18,7 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>, instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>,
private backendSrv: BackendSrv, private backendSrv: BackendSrv,
private templateSrv: TemplateSrv, private templateSrv: TemplateSrv,
private $q private $q: IQService
) { ) {
super(instanceSettings); super(instanceSettings);
this.azureMonitorDatasource = new AzureMonitorDatasource(instanceSettings, this.backendSrv, this.templateSrv); this.azureMonitorDatasource = new AzureMonitorDatasource(instanceSettings, this.backendSrv, this.templateSrv);
@ -76,7 +77,7 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
}); });
} }
async annotationQuery(options) { async annotationQuery(options: any) {
return this.azureLogAnalyticsDatasource.annotationQuery(options); return this.azureLogAnalyticsDatasource.annotationQuery(options);
} }
@ -183,11 +184,11 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
return this.appInsightsDatasource.getMetricNames(); return this.appInsightsDatasource.getMetricNames();
} }
getAppInsightsMetricMetadata(metricName) { getAppInsightsMetricMetadata(metricName: string) {
return this.appInsightsDatasource.getMetricMetadata(metricName); return this.appInsightsDatasource.getMetricMetadata(metricName);
} }
getAppInsightsColumns(refId) { getAppInsightsColumns(refId: string | number) {
return this.appInsightsDatasource.logAnalyticsColumns[refId]; return this.appInsightsDatasource.logAnalyticsColumns[refId];
} }

View File

@ -1,4 +1,5 @@
import _ from 'lodash'; import _ from 'lodash';
// @ts-ignore
import Plain from 'slate-plain-serializer'; import Plain from 'slate-plain-serializer';
import QueryField from './query_field'; import QueryField from './query_field';
@ -38,21 +39,21 @@ interface KustoDBSchema {
Tables?: any; Tables?: any;
} }
const defaultSchema = () => ({ const defaultSchema: any = () => ({
Databases: { Databases: {
Default: {}, Default: {},
}, },
}); });
const cleanText = s => s.replace(/[{}[\]="(),!~+\-*/^%]/g, '').trim(); const cleanText = s => s.replace(/[{}[\]="(),!~+\-*/^%]/g, '').trim();
const wrapText = text => ({ text }); const wrapText = (text: string) => ({ text });
export default class KustoQueryField extends QueryField { export default class KustoQueryField extends QueryField {
fields: any; fields: any;
events: any; events: any;
schema: KustoSchema; schema: KustoSchema;
constructor(props, context) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.schema = defaultSchema(); this.schema = defaultSchema();
@ -197,7 +198,7 @@ export default class KustoQueryField extends QueryField {
} }
}; };
applyTypeahead(change, suggestion) { applyTypeahead(change: any, suggestion: { text: any; type: string; deleteBackwards: any }) {
const { typeaheadPrefix, typeaheadContext, typeaheadText } = this.state; const { typeaheadPrefix, typeaheadContext, typeaheadText } = this.state;
let suggestionText = suggestion.text || suggestion; let suggestionText = suggestion.text || suggestion;
const move = 0; const move = 0;
@ -425,7 +426,7 @@ export default class KustoQueryField extends QueryField {
/** /**
* Cast schema from App Insights to default Kusto schema * Cast schema from App Insights to default Kusto schema
*/ */
function castSchema(schema) { function castSchema(schema: any) {
const defaultSchemaTemplate = defaultSchema(); const defaultSchemaTemplate = defaultSchema();
defaultSchemaTemplate.Databases.Default = schema; defaultSchemaTemplate.Databases.Default = schema;
return defaultSchemaTemplate; return defaultSchemaTemplate;

View File

@ -11,6 +11,7 @@ interface EditorProps {
variables: () => string[] | string[]; variables: () => string[] | string[];
getSchema?: () => Promise<any>; getSchema?: () => Promise<any>;
execute?: () => void; execute?: () => void;
query?: string;
} }
class Editor extends Component<EditorProps, any> { class Editor extends Component<EditorProps, any> {
@ -18,7 +19,7 @@ class Editor extends Component<EditorProps, any> {
placeholder: 'Enter a query', placeholder: 'Enter a query',
}; };
constructor(props) { constructor(props: EditorProps) {
super(props); super(props);
this.state = { this.state = {
edited: false, edited: false,
@ -26,7 +27,7 @@ class Editor extends Component<EditorProps, any> {
}; };
} }
onChangeQuery = value => { onChangeQuery = (value: any) => {
const { index, change } = this.props; const { index, change } = this.props;
const { query } = this.state; const { query } = this.state;
const edited = query !== value; const edited = query !== value;

View File

@ -8,18 +8,20 @@ import Typeahead from './typeahead';
import { getKeybindingSrv, KeybindingSrv } from 'app/core/services/keybindingSrv'; import { getKeybindingSrv, KeybindingSrv } from 'app/core/services/keybindingSrv';
import { Block, Document, Text, Value } from 'slate'; import { Block, Document, Text, Value } from 'slate';
// @ts-ignore
import { Editor } from 'slate-react'; import { Editor } from 'slate-react';
// @ts-ignore
import Plain from 'slate-plain-serializer'; import Plain from 'slate-plain-serializer';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
function flattenSuggestions(s) { function flattenSuggestions(s: any) {
return s ? s.reduce((acc, g) => acc.concat(g.items), []) : []; return s ? s.reduce((acc: any, g: any) => acc.concat(g.items), []) : [];
} }
export const makeFragment = text => { export const makeFragment = (text: string) => {
const lines = text.split('\n').map(line => const lines = text.split('\n').map((line: any) =>
Block.create({ Block.create({
type: 'paragraph', type: 'paragraph',
nodes: [Text.create(line)], nodes: [Text.create(line)],
@ -32,12 +34,12 @@ export const makeFragment = text => {
return fragment; return fragment;
}; };
export const getInitialValue = query => Value.create({ document: makeFragment(query) }); export const getInitialValue = (query: string) => Value.create({ document: makeFragment(query) });
class Portal extends React.Component<any, any> { class Portal extends React.Component<any, any> {
node: any; node: any;
constructor(props) { constructor(props: any) {
super(props); super(props);
const { index = 0, prefix = 'query' } = props; const { index = 0, prefix = 'query' } = props;
this.node = document.createElement('div'); this.node = document.createElement('div');
@ -60,7 +62,7 @@ class QueryField extends React.Component<any, any> {
resetTimer: any; resetTimer: any;
keybindingSrv: KeybindingSrv = getKeybindingSrv(); keybindingSrv: KeybindingSrv = getKeybindingSrv();
constructor(props, context) { constructor(props: any, context: any) {
super(props, context); super(props, context);
const { prismDefinition = {}, prismLanguage = 'kusto' } = props; const { prismDefinition = {}, prismLanguage = 'kusto' } = props;
@ -96,7 +98,7 @@ class QueryField extends React.Component<any, any> {
this.updateMenu(); this.updateMenu();
} }
onChange = ({ value }) => { onChange = ({ value }: any) => {
const changed = value.document !== this.state.value.document; const changed = value.document !== this.state.value.document;
this.setState({ value }, () => { this.setState({ value }, () => {
if (changed) { if (changed) {
@ -107,7 +109,7 @@ class QueryField extends React.Component<any, any> {
}); });
}; };
request = (url?) => { request = (url?: string) => {
if (this.props.request) { if (this.props.request) {
return this.props.request(url); return this.props.request(url);
} }
@ -122,7 +124,7 @@ class QueryField extends React.Component<any, any> {
} }
}; };
onKeyDown = (event, change) => { onKeyDown = (event: any, change: any) => {
const { typeaheadIndex, suggestions } = this.state; const { typeaheadIndex, suggestions } = this.state;
switch (event.key) { switch (event.key) {
@ -192,11 +194,11 @@ class QueryField extends React.Component<any, any> {
return undefined; return undefined;
}; };
onTypeahead = (change?, item?) => { onTypeahead = (change?: boolean, item?: any) => {
return change || this.state.value.change(); return change || this.state.value.change();
}; };
applyTypeahead(change?, suggestion?): { value: object } { applyTypeahead(change?: boolean, suggestion?: any): { value: object } {
return { value: {} }; return { value: {} };
} }
@ -237,7 +239,7 @@ class QueryField extends React.Component<any, any> {
this.keybindingSrv.setupGlobal(); this.keybindingSrv.setupGlobal();
} }
onClickItem = item => { onClickItem = (item: any) => {
const { suggestions } = this.state; const { suggestions } = this.state;
if (!suggestions || suggestions.length === 0) { if (!suggestions || suggestions.length === 0) {
return; return;
@ -295,7 +297,7 @@ class QueryField extends React.Component<any, any> {
} }
}; };
menuRef = el => { menuRef = (el: any) => {
this.menuEl = el; this.menuEl = el;
}; };

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
function scrollIntoView(el) { function scrollIntoView(el: any) {
if (!el || !el.offsetParent) { if (!el || !el.offsetParent) {
return; return;
} }
@ -12,13 +12,13 @@ function scrollIntoView(el) {
class TypeaheadItem extends React.PureComponent<any, any> { class TypeaheadItem extends React.PureComponent<any, any> {
el: any; el: any;
componentDidUpdate(prevProps) { componentDidUpdate(prevProps: any) {
if (this.props.isSelected && !prevProps.isSelected) { if (this.props.isSelected && !prevProps.isSelected) {
scrollIntoView(this.el); scrollIntoView(this.el);
} }
} }
getRef = el => { getRef = (el: any) => {
this.el = el; this.el = el;
}; };
@ -42,7 +42,7 @@ class TypeaheadGroup extends React.PureComponent<any, any> {
<li className="typeahead-group"> <li className="typeahead-group">
<div className="typeahead-group__title">{label}</div> <div className="typeahead-group__title">{label}</div>
<ul className="typeahead-group__list"> <ul className="typeahead-group__list">
{items.map(item => { {items.map((item: any) => {
const text = typeof item === 'object' ? item.text : item; const text = typeof item === 'object' ? item.text : item;
const label = typeof item === 'object' ? item.display || item.text : item; const label = typeof item === 'object' ? item.display || item.text : item;
return ( return (
@ -66,7 +66,7 @@ class Typeahead extends React.PureComponent<any, any> {
const { groupedItems, menuRef, selectedItems, onClickItem } = this.props; const { groupedItems, menuRef, selectedItems, onClickItem } = this.props;
return ( return (
<ul className="typeahead" ref={menuRef}> <ul className="typeahead" ref={menuRef}>
{groupedItems.map(g => ( {groupedItems.map((g: any) => (
<TypeaheadGroup key={g.label} onClickItem={onClickItem} selected={selectedItems} {...g} /> <TypeaheadGroup key={g.label} onClickItem={onClickItem} selected={selectedItems} {...g} />
))} ))}
</ul> </ul>

View File

@ -1,7 +1,7 @@
import { dateTime } from '@grafana/ui/src/utils/moment_wrapper'; import { dateTime } from '@grafana/ui/src/utils/moment_wrapper';
export default class LogAnalyticsQuerystringBuilder { export default class LogAnalyticsQuerystringBuilder {
constructor(public rawQueryString, public options, public defaultTimeField) {} constructor(public rawQueryString: string, public options: any, public defaultTimeField: any) {}
generate() { generate() {
let queryString = this.rawQueryString; let queryString = this.rawQueryString;
@ -39,14 +39,14 @@ export default class LogAnalyticsQuerystringBuilder {
return { uriString, rawQuery }; return { uriString, rawQuery };
} }
getFrom(options) { getFrom(options: any) {
const from = options.range.from; const from = options.range.from;
return `datetime(${dateTime(from) return `datetime(${dateTime(from)
.startOf('minute') .startOf('minute')
.toISOString()})`; .toISOString()})`;
} }
getUntil(options) { getUntil(options: any) {
if (options.rangeRaw.to === 'now') { if (options.rangeRaw.to === 'now') {
const now = Date.now(); const now = Date.now();
return `datetime(${dateTime(now) return `datetime(${dateTime(now)
@ -60,7 +60,7 @@ export default class LogAnalyticsQuerystringBuilder {
} }
} }
getTimeFilter(timeFieldArg, options) { getTimeFilter(timeFieldArg: any, options: any) {
const timeField = timeFieldArg || this.defaultTimeField; const timeField = timeFieldArg || this.defaultTimeField;
if (options.rangeRaw.to === 'now') { if (options.rangeRaw.to === 'now') {
return `${timeField} >= ${this.getFrom(options)}`; return `${timeField} >= ${this.getFrom(options)}`;

View File

@ -3,6 +3,7 @@ jest.mock('./css/query_editor.css', () => {
}); });
import { AzureMonitorQueryCtrl } from './query_ctrl'; import { AzureMonitorQueryCtrl } from './query_ctrl';
// @ts-ignore
import Q from 'q'; import Q from 'q';
import { TemplateSrv } from 'app/features/templating/template_srv'; import { TemplateSrv } from 'app/features/templating/template_srv';
import { auto } from 'angular'; import { auto } from 'angular';
@ -59,7 +60,7 @@ describe('AzureMonitorQueryCtrl', () => {
}); });
it('should return a list of Resource Groups', () => { it('should return a list of Resource Groups', () => {
return queryCtrl.getResourceGroups('').then(result => { return queryCtrl.getResourceGroups('').then((result: any) => {
expect(result[0].text).toBe('nodeapp'); expect(result[0].text).toBe('nodeapp');
}); });
}); });
@ -75,7 +76,7 @@ describe('AzureMonitorQueryCtrl', () => {
beforeEach(() => { beforeEach(() => {
queryCtrl.target.subscription = 'sub1'; queryCtrl.target.subscription = 'sub1';
queryCtrl.target.azureMonitor.resourceGroup = 'test'; queryCtrl.target.azureMonitor.resourceGroup = 'test';
queryCtrl.datasource.getMetricDefinitions = function(subscriptionId, query) { queryCtrl.datasource.getMetricDefinitions = function(subscriptionId: any, query: any) {
expect(subscriptionId).toBe('sub1'); expect(subscriptionId).toBe('sub1');
expect(query).toBe('test'); expect(query).toBe('test');
return this.$q.when(response); return this.$q.when(response);
@ -83,7 +84,7 @@ describe('AzureMonitorQueryCtrl', () => {
}); });
it('should return a list of Metric Definitions', () => { it('should return a list of Metric Definitions', () => {
return queryCtrl.getMetricDefinitions('').then(result => { return queryCtrl.getMetricDefinitions('').then((result: any) => {
expect(result[0].text).toBe('Microsoft.Compute/virtualMachines'); expect(result[0].text).toBe('Microsoft.Compute/virtualMachines');
expect(result[1].text).toBe('Microsoft.Network/publicIPAddresses'); expect(result[1].text).toBe('Microsoft.Network/publicIPAddresses');
}); });
@ -109,7 +110,11 @@ describe('AzureMonitorQueryCtrl', () => {
queryCtrl.target.subscription = 'sub1'; queryCtrl.target.subscription = 'sub1';
queryCtrl.target.azureMonitor.resourceGroup = 'test'; queryCtrl.target.azureMonitor.resourceGroup = 'test';
queryCtrl.target.azureMonitor.metricDefinition = 'Microsoft.Compute/virtualMachines'; queryCtrl.target.azureMonitor.metricDefinition = 'Microsoft.Compute/virtualMachines';
queryCtrl.datasource.getResourceNames = function(subscriptionId, resourceGroup, metricDefinition) { queryCtrl.datasource.getResourceNames = function(
subscriptionId: any,
resourceGroup: any,
metricDefinition: any
) {
expect(subscriptionId).toBe('sub1'); expect(subscriptionId).toBe('sub1');
expect(resourceGroup).toBe('test'); expect(resourceGroup).toBe('test');
expect(metricDefinition).toBe('Microsoft.Compute/virtualMachines'); expect(metricDefinition).toBe('Microsoft.Compute/virtualMachines');
@ -118,7 +123,7 @@ describe('AzureMonitorQueryCtrl', () => {
}); });
it('should return a list of Resource Names', () => { it('should return a list of Resource Names', () => {
return queryCtrl.getResourceNames('').then(result => { return queryCtrl.getResourceNames('').then((result: any) => {
expect(result[0].text).toBe('test1'); expect(result[0].text).toBe('test1');
expect(result[1].text).toBe('test2'); expect(result[1].text).toBe('test2');
}); });
@ -147,10 +152,10 @@ describe('AzureMonitorQueryCtrl', () => {
queryCtrl.target.azureMonitor.metricDefinition = 'Microsoft.Compute/virtualMachines'; queryCtrl.target.azureMonitor.metricDefinition = 'Microsoft.Compute/virtualMachines';
queryCtrl.target.azureMonitor.resourceName = 'test'; queryCtrl.target.azureMonitor.resourceName = 'test';
queryCtrl.datasource.getMetricNames = function( queryCtrl.datasource.getMetricNames = function(
subscriptionId, subscriptionId: any,
resourceGroup, resourceGroup: any,
metricDefinition, metricDefinition: any,
resourceName resourceName: any
) { ) {
expect(subscriptionId).toBe('sub1'); expect(subscriptionId).toBe('sub1');
expect(resourceGroup).toBe('test'); expect(resourceGroup).toBe('test');
@ -161,7 +166,7 @@ describe('AzureMonitorQueryCtrl', () => {
}); });
it('should return a list of Metric Names', () => { it('should return a list of Metric Names', () => {
return queryCtrl.getMetricNames('').then(result => { return queryCtrl.getMetricNames('').then((result: any) => {
expect(result[0].text).toBe('metric1'); expect(result[0].text).toBe('metric1');
expect(result[1].text).toBe('metric2'); expect(result[1].text).toBe('metric2');
}); });
@ -182,7 +187,7 @@ describe('AzureMonitorQueryCtrl', () => {
}); });
describe('when onMetricNameChange is triggered for the Metric Names dropdown', () => { describe('when onMetricNameChange is triggered for the Metric Names dropdown', () => {
const response = { const response: any = {
primaryAggType: 'Average', primaryAggType: 'Average',
supportAggOptions: ['Average', 'Total'], supportAggOptions: ['Average', 'Total'],
supportedTimeGrains: ['PT1M', 'P1D'], supportedTimeGrains: ['PT1M', 'P1D'],
@ -196,11 +201,11 @@ describe('AzureMonitorQueryCtrl', () => {
queryCtrl.target.azureMonitor.resourceName = 'test'; queryCtrl.target.azureMonitor.resourceName = 'test';
queryCtrl.target.azureMonitor.metricName = 'Percentage CPU'; queryCtrl.target.azureMonitor.metricName = 'Percentage CPU';
queryCtrl.datasource.getMetricMetadata = function( queryCtrl.datasource.getMetricMetadata = function(
subscription, subscription: any,
resourceGroup, resourceGroup: any,
metricDefinition, metricDefinition: any,
resourceName, resourceName: any,
metricName metricName: any
) { ) {
expect(subscription).toBe('sub1'); expect(subscription).toBe('sub1');
expect(resourceGroup).toBe('test'); expect(resourceGroup).toBe('test');
@ -233,7 +238,7 @@ describe('AzureMonitorQueryCtrl', () => {
}); });
it('should return a list of Metric Names', () => { it('should return a list of Metric Names', () => {
return queryCtrl.getAppInsightsMetricNames().then(result => { return queryCtrl.getAppInsightsMetricNames().then((result: any) => {
expect(result[0].text).toBe('metric1'); expect(result[0].text).toBe('metric1');
expect(result[1].text).toBe('metric2'); expect(result[1].text).toBe('metric2');
}); });
@ -263,7 +268,7 @@ describe('AzureMonitorQueryCtrl', () => {
beforeEach(() => { beforeEach(() => {
queryCtrl.target.appInsights.metricName = 'requests/failed'; queryCtrl.target.appInsights.metricName = 'requests/failed';
queryCtrl.datasource.getAppInsightsMetricMetadata = function(metricName) { queryCtrl.datasource.getAppInsightsMetricMetadata = function(metricName: string) {
expect(metricName).toBe('requests/failed'); expect(metricName).toBe('requests/failed');
return this.$q.when(response); return this.$q.when(response);
}; };

View File

@ -2,7 +2,7 @@ import _ from 'lodash';
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
export default class TimeGrainConverter { export default class TimeGrainConverter {
static createISO8601Duration(timeGrain, timeGrainUnit) { static createISO8601Duration(timeGrain: string | number, timeGrainUnit: any) {
const timeIntervals = ['hour', 'minute', 'h', 'm']; const timeIntervals = ['hour', 'minute', 'h', 'm'];
if (_.includes(timeIntervals, timeGrainUnit)) { if (_.includes(timeIntervals, timeGrainUnit)) {
return `PT${timeGrain}${timeGrainUnit[0].toUpperCase()}`; return `PT${timeGrain}${timeGrainUnit[0].toUpperCase()}`;
@ -32,7 +32,7 @@ export default class TimeGrainConverter {
return TimeGrainConverter.createISO8601Duration(timeGrain, unit); return TimeGrainConverter.createISO8601Duration(timeGrain, unit);
} }
static findClosestTimeGrain(interval, allowedTimeGrains) { static findClosestTimeGrain(interval: any, allowedTimeGrains: string[]) {
const timeGrains = _.filter(allowedTimeGrains, o => o !== 'auto'); const timeGrains = _.filter(allowedTimeGrains, o => o !== 'auto');
let closest = timeGrains[0]; let closest = timeGrains[0];

View File

@ -3,7 +3,7 @@
echo -e "Collecting code stats (typescript errors & more)" echo -e "Collecting code stats (typescript errors & more)"
ERROR_COUNT_LIMIT=2945 ERROR_COUNT_LIMIT=2350
DIRECTIVES_LIMIT=172 DIRECTIVES_LIMIT=172
CONTROLLERS_LIMIT=139 CONTROLLERS_LIMIT=139