Prechádzať zdrojové kódy

noImplicitAny: Azure Monitor (#17966)

Tobias Skarhed 6 rokov pred
rodič
commit
baed5d7bd9
17 zmenil súbory, kde vykonal 138 pridanie a 122 odobranie
  1. 4 4
      public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_querystring_builder.ts
  2. 17 17
      public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/response_parser.ts
  3. 9 8
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts
  4. 16 15
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts
  5. 5 5
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/response_parser.ts
  6. 8 7
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.test.ts
  7. 10 10
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts
  8. 4 1
      public/app/plugins/datasource/grafana-azure-monitor-datasource/config_ctrl.ts
  9. 5 4
      public/app/plugins/datasource/grafana-azure-monitor-datasource/datasource.ts
  10. 6 5
      public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/KustoQueryField.tsx
  11. 3 2
      public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/editor_component.tsx
  12. 16 14
      public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/query_field.tsx
  13. 5 5
      public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/typeahead.tsx
  14. 4 4
      public/app/plugins/datasource/grafana-azure-monitor-datasource/log_analytics/querystring_builder.ts
  15. 23 18
      public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.test.ts
  16. 2 2
      public/app/plugins/datasource/grafana-azure-monitor-datasource/time_grain_converter.ts
  17. 1 1
      scripts/ci-frontend-metrics.sh

+ 4 - 4
public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_querystring_builder.ts

@@ -8,17 +8,17 @@ export default class AppInsightsQuerystringBuilder {
   timeGrainUnit = '';
   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;
   }
 
-  setGroupBy(groupBy) {
+  setGroupBy(groupBy: string) {
     this.groupBy = groupBy;
   }
 
-  setInterval(timeGrainType, timeGrain, timeGrainUnit) {
+  setInterval(timeGrainType: string, timeGrain: any, timeGrainUnit: string) {
     this.timeGrainType = timeGrainType;
     this.timeGrain = timeGrain;
     this.timeGrainUnit = timeGrainUnit;

+ 17 - 17
public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/response_parser.ts

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

+ 9 - 8
public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts

@@ -1,5 +1,6 @@
 import AzureMonitorDatasource from '../datasource';
 import FakeSchemaData from './__mocks__/schema';
+// @ts-ignore
 import Q from 'q';
 import { TemplateSrv } from 'app/features/templating/template_srv';
 import { KustoSchema } from '../types';
@@ -49,8 +50,8 @@ describe('AzureLogAnalyticsDatasource', () => {
       ],
     };
 
-    let workspacesUrl;
-    let azureLogAnalyticsUrl;
+    let workspacesUrl: string;
+    let azureLogAnalyticsUrl: string;
 
     beforeEach(async () => {
       ctx.instanceSettings.jsonData.subscriptionId = 'xxx';
@@ -101,7 +102,7 @@ describe('AzureLogAnalyticsDatasource', () => {
       });
 
       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.message).toEqual(
             '1. Azure Log Analytics: Bad Request: InvalidApiVersionParameter. An error message. '
@@ -174,7 +175,7 @@ describe('AzureLogAnalyticsDatasource', () => {
         });
 
         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[0].datapoints.length).toBe(2);
             expect(results.data[0].target).toEqual('Administrative');
@@ -213,7 +214,7 @@ describe('AzureLogAnalyticsDatasource', () => {
         });
 
         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.');
           });
         });
@@ -230,7 +231,7 @@ describe('AzureLogAnalyticsDatasource', () => {
       });
 
       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].columns.length).toBe(3);
           expect(results.data[0].rows.length).toBe(3);
@@ -300,7 +301,7 @@ describe('AzureLogAnalyticsDatasource', () => {
       ],
     };
 
-    let queryResults;
+    let queryResults: any[];
 
     beforeEach(async () => {
       ctx.backendSrv.datasourceRequest = (options: { url: string }) => {
@@ -359,7 +360,7 @@ describe('AzureLogAnalyticsDatasource', () => {
       ],
     };
 
-    let annotationResults;
+    let annotationResults: any[];
 
     beforeEach(async () => {
       ctx.backendSrv.datasourceRequest = (options: { url: string }) => {

+ 16 - 15
public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts

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

+ 5 - 5
public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/response_parser.ts

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

+ 8 - 7
public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.test.ts

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

+ 10 - 10
public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts

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

+ 4 - 1
public/app/plugins/datasource/grafana-azure-monitor-datasource/config_ctrl.ts

@@ -2,6 +2,9 @@ import AzureLogAnalyticsDatasource from './azure_log_analytics/azure_log_analyti
 import config from 'app/core/config';
 import { isVersionGtOrEq } from 'app/core/utils/version';
 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 {
   key: string;
@@ -22,7 +25,7 @@ export class AzureMonitorConfigCtrl {
   token: string;
 
   /** @ngInject */
-  constructor(private backendSrv, private $q, private templateSrv) {
+  constructor(private backendSrv: BackendSrv, private $q: IQService, private templateSrv: TemplateSrv) {
     this.hasRequiredGrafanaVersion = this.hasMinVersion();
     this.current.jsonData.cloudName = this.current.jsonData.cloudName || 'azuremonitor';
     this.current.jsonData.azureLogAnalyticsSameAs = this.current.jsonData.azureLogAnalyticsSameAs || false;

+ 5 - 4
public/app/plugins/datasource/grafana-azure-monitor-datasource/datasource.ts

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

+ 6 - 5
public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/KustoQueryField.tsx

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

+ 3 - 2
public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/editor_component.tsx

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

+ 16 - 14
public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/query_field.tsx

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

+ 5 - 5
public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/typeahead.tsx

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

+ 4 - 4
public/app/plugins/datasource/grafana-azure-monitor-datasource/log_analytics/querystring_builder.ts

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

+ 23 - 18
public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.test.ts

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

+ 2 - 2
public/app/plugins/datasource/grafana-azure-monitor-datasource/time_grain_converter.ts

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

+ 1 - 1
scripts/ci-frontend-metrics.sh

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