mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Azure Monitor: Log Analytics response to data frames (#25297)
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
@@ -3,17 +3,18 @@ import { DataFrame, toUtc, getFrameDisplayName } from '@grafana/data';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
|
||||
|
||||
const templateSrv = new TemplateSrv();
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getBackendSrv: () => backendSrv,
|
||||
getTemplateSrv: () => templateSrv,
|
||||
}));
|
||||
|
||||
describe('AppInsightsDatasource', () => {
|
||||
const datasourceRequestMock = jest.spyOn(backendSrv, 'datasourceRequest');
|
||||
|
||||
const ctx: any = {
|
||||
templateSrv: new TemplateSrv(),
|
||||
};
|
||||
const ctx: any = {};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
@@ -22,7 +23,7 @@ describe('AppInsightsDatasource', () => {
|
||||
url: 'http://appinsightsapi',
|
||||
};
|
||||
|
||||
ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv);
|
||||
ctx.ds = new Datasource(ctx.instanceSettings);
|
||||
});
|
||||
|
||||
describe('When performing testDatasource', () => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { TimeSeries, toDataFrame } from '@grafana/data';
|
||||
import { DataQueryRequest, DataQueryResponseData, DataSourceInstanceSettings } from '@grafana/data';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { getBackendSrv, getTemplateSrv } from '@grafana/runtime';
|
||||
import _ from 'lodash';
|
||||
|
||||
import TimegrainConverter from '../time_grain_converter';
|
||||
@@ -20,8 +19,7 @@ export default class AppInsightsDatasource {
|
||||
applicationId: string;
|
||||
logAnalyticsColumns: { [key: string]: LogAnalyticsColumn[] } = {};
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>, private templateSrv: TemplateSrv) {
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>) {
|
||||
this.id = instanceSettings.id;
|
||||
this.applicationId = instanceSettings.jsonData.appInsightsAppId || '';
|
||||
|
||||
@@ -66,7 +64,7 @@ export default class AppInsightsDatasource {
|
||||
raw: false,
|
||||
appInsights: {
|
||||
rawQuery: true,
|
||||
rawQueryString: this.templateSrv.replace(item.rawQueryString, options.scopedVars),
|
||||
rawQueryString: getTemplateSrv().replace(item.rawQueryString, options.scopedVars),
|
||||
timeColumn: item.timeColumn,
|
||||
valueColumn: item.valueColumn,
|
||||
segmentColumn: item.segmentColumn,
|
||||
@@ -91,17 +89,19 @@ export default class AppInsightsDatasource {
|
||||
item.dimensionFilter = item.filter;
|
||||
}
|
||||
|
||||
const templateSrv = getTemplateSrv();
|
||||
|
||||
return {
|
||||
type: 'timeSeriesQuery',
|
||||
raw: false,
|
||||
appInsights: {
|
||||
rawQuery: false,
|
||||
timeGrain: this.templateSrv.replace((item.timeGrain || '').toString(), options.scopedVars),
|
||||
timeGrain: templateSrv.replace((item.timeGrain || '').toString(), options.scopedVars),
|
||||
allowedTimeGrainsMs: item.allowedTimeGrainsMs,
|
||||
metricName: this.templateSrv.replace(item.metricName, options.scopedVars),
|
||||
aggregation: this.templateSrv.replace(item.aggregation, options.scopedVars),
|
||||
dimension: this.templateSrv.replace(item.dimension, options.scopedVars),
|
||||
dimensionFilter: this.templateSrv.replace(item.dimensionFilter, options.scopedVars),
|
||||
metricName: templateSrv.replace(item.metricName, options.scopedVars),
|
||||
aggregation: templateSrv.replace(item.aggregation, options.scopedVars),
|
||||
dimension: templateSrv.replace(item.dimension, options.scopedVars),
|
||||
dimensionFilter: templateSrv.replace(item.dimensionFilter, options.scopedVars),
|
||||
alias: item.alias,
|
||||
format: target.format,
|
||||
},
|
||||
@@ -198,7 +198,7 @@ export default class AppInsightsDatasource {
|
||||
const appInsightsGroupByQuery = query.match(/^AppInsightsGroupBys\(([^\)]+?)(,\s?([^,]+?))?\)/i);
|
||||
if (appInsightsGroupByQuery) {
|
||||
const metricName = appInsightsGroupByQuery[1];
|
||||
return this.getGroupBys(this.templateSrv.replace(metricName));
|
||||
return this.getGroupBys(getTemplateSrv().replace(metricName));
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -2,12 +2,15 @@ import AzureMonitorDatasource from '../datasource';
|
||||
import FakeSchemaData from './__mocks__/schema';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { KustoSchema, AzureLogsVariable } from '../types';
|
||||
import { toUtc, getFrameDisplayName } from '@grafana/data';
|
||||
import { toUtc } from '@grafana/data';
|
||||
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
|
||||
|
||||
const templateSrv = new TemplateSrv();
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getBackendSrv: () => backendSrv,
|
||||
getTemplateSrv: () => templateSrv,
|
||||
}));
|
||||
|
||||
describe('AzureLogAnalyticsDatasource', () => {
|
||||
@@ -18,9 +21,7 @@ describe('AzureLogAnalyticsDatasource', () => {
|
||||
datasourceRequestMock.mockImplementation(jest.fn());
|
||||
});
|
||||
|
||||
const ctx: any = {
|
||||
templateSrv: new TemplateSrv(),
|
||||
};
|
||||
const ctx: any = {};
|
||||
|
||||
beforeEach(() => {
|
||||
ctx.instanceSettings = {
|
||||
@@ -28,7 +29,7 @@ describe('AzureLogAnalyticsDatasource', () => {
|
||||
url: 'http://azureloganalyticsapi',
|
||||
};
|
||||
|
||||
ctx.ds = new AzureMonitorDatasource(ctx.instanceSettings, ctx.templateSrv);
|
||||
ctx.ds = new AzureMonitorDatasource(ctx.instanceSettings);
|
||||
});
|
||||
|
||||
describe('When the config option "Same as Azure Monitor" has been chosen', () => {
|
||||
@@ -67,7 +68,7 @@ describe('AzureLogAnalyticsDatasource', () => {
|
||||
ctx.instanceSettings.jsonData.tenantId = 'xxx';
|
||||
ctx.instanceSettings.jsonData.clientId = 'xxx';
|
||||
ctx.instanceSettings.jsonData.azureLogAnalyticsSameAs = true;
|
||||
ctx.ds = new AzureMonitorDatasource(ctx.instanceSettings, ctx.templateSrv);
|
||||
ctx.ds = new AzureMonitorDatasource(ctx.instanceSettings);
|
||||
|
||||
datasourceRequestMock.mockImplementation((options: { url: string }) => {
|
||||
if (options.url.indexOf('Microsoft.OperationalInsights/workspaces') > -1) {
|
||||
@@ -119,112 +120,6 @@ describe('AzureLogAnalyticsDatasource', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('When performing query', () => {
|
||||
const options = {
|
||||
range: {
|
||||
from: toUtc('2017-08-22T20:00:00Z'),
|
||||
to: toUtc('2017-08-22T23:59:00Z'),
|
||||
},
|
||||
rangeRaw: {
|
||||
from: 'now-4h',
|
||||
to: 'now',
|
||||
},
|
||||
targets: [
|
||||
{
|
||||
apiVersion: '2016-09-01',
|
||||
refId: 'A',
|
||||
queryType: 'Azure Log Analytics',
|
||||
azureLogAnalytics: {
|
||||
resultFormat: 'time_series',
|
||||
query:
|
||||
'AzureActivity | where TimeGenerated > ago(2h) ' +
|
||||
'| summarize count() by Category, bin(TimeGenerated, 5min) ' +
|
||||
'| project TimeGenerated, Category, count_ | order by TimeGenerated asc',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = {
|
||||
results: {
|
||||
A: {
|
||||
refId: 'A',
|
||||
meta: {
|
||||
columns: ['TimeGenerated', 'Computer', 'avg_CounterValue'],
|
||||
subscription: 'xxx',
|
||||
workspace: 'aaaa-1111-bbbb-2222',
|
||||
query:
|
||||
'Perf\r\n| where ObjectName == "Memory" and CounterName == "Available MBytes Memory"\n| where TimeGenerated >= datetime(\'2020-04-23T09:15:20Z\') and TimeGenerated <= datetime(\'2020-04-23T09:20:20Z\')\n| where 1 == 1\n| summarize avg(CounterValue) by bin(TimeGenerated, 1m), Computer \n| order by TimeGenerated asc',
|
||||
encodedQuery: 'gzipped_base64_encoded_query',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'grafana-vm',
|
||||
points: [
|
||||
[2017.25, 1587633300000],
|
||||
[2048, 1587633360000],
|
||||
[2048.3333333333335, 1587633420000],
|
||||
[2049, 1587633480000],
|
||||
[2049, 1587633540000],
|
||||
[2049, 1587633600000],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const workspacesResponse = {
|
||||
value: [
|
||||
{
|
||||
properties: {
|
||||
customerId: 'aaaa-1111-bbbb-2222',
|
||||
},
|
||||
id:
|
||||
'/subscriptions/44693801-6ee6-49de-9b2d-9106972f9572/resourcegroups/defaultresourcegroup/providers/microsoft.operationalinsights/workspaces/aworkspace',
|
||||
name: 'aworkspace',
|
||||
type: 'Microsoft.OperationalInsights/workspaces',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe('in time series format', () => {
|
||||
describe('and the data is valid (has time, metric and value columns)', () => {
|
||||
beforeEach(() => {
|
||||
datasourceRequestMock.mockImplementation((options: { url: string }) => {
|
||||
if (options.url.indexOf('Microsoft.OperationalInsights/workspaces') > 0) {
|
||||
return Promise.resolve({ data: workspacesResponse, status: 200 });
|
||||
} else {
|
||||
expect(options.url).toContain('/api/tsdb/query');
|
||||
return Promise.resolve({ data: response, status: 200 });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a list of datapoints', () => {
|
||||
return ctx.ds.query(options).then((results: any) => {
|
||||
expect(results.data.length).toBe(1);
|
||||
expect(getFrameDisplayName(results.data[0])).toEqual('grafana-vm');
|
||||
expect(results.data[0].fields.length).toBe(2);
|
||||
expect(results.data[0].name).toBe('grafana-vm');
|
||||
expect(results.data[0].fields[0].name).toBe('Time');
|
||||
expect(results.data[0].fields[1].name).toBe('Value');
|
||||
expect(results.data[0].fields[0].values.toArray().length).toBe(6);
|
||||
expect(results.data[0].fields[0].values.get(0)).toEqual(1587633300000);
|
||||
expect(results.data[0].fields[1].values.get(0)).toEqual(2017.25);
|
||||
expect(results.data[0].fields[0].values.get(1)).toEqual(1587633360000);
|
||||
expect(results.data[0].fields[1].values.get(1)).toEqual(2048);
|
||||
expect(results.data[0].fields[0].config.links[0].title).toEqual('View in Azure Portal');
|
||||
expect(results.data[0].fields[0].config.links[0].targetBlank).toBe(true);
|
||||
expect(results.data[0].fields[0].config.links[0].url).toEqual(
|
||||
'https://portal.azure.com/#blade/Microsoft_OperationsManagementSuite_Workspace/AnalyticsBlade/initiator/AnalyticsShareLinkToQuery/isQueryEditorVisible/true/scope/%7B%22resources%22%3A%5B%7B%22resourceId%22%3A%22%2Fsubscriptions%2Fxxx%2Fresourcegroups%2Fdefaultresourcegroup%2Fproviders%2Fmicrosoft.operationalinsights%2Fworkspaces%2Faworkspace%22%7D%5D%7D/query/gzipped_base64_encoded_query/isQueryBase64Compressed/true/timespanInIsoFormat/P1D'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When performing getSchema', () => {
|
||||
beforeEach(() => {
|
||||
datasourceRequestMock.mockImplementation((options: { url: string }) => {
|
||||
|
||||
@@ -2,13 +2,19 @@ import _ from 'lodash';
|
||||
import LogAnalyticsQuerystringBuilder from '../log_analytics/querystring_builder';
|
||||
import ResponseParser from './response_parser';
|
||||
import { AzureMonitorQuery, AzureDataSourceJsonData, AzureLogsVariable } from '../types';
|
||||
import { TimeSeries, toDataFrame } from '@grafana/data';
|
||||
import { DataQueryRequest, DataQueryResponseData, DataSourceInstanceSettings } from '@grafana/data';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import {
|
||||
DataQueryResponse,
|
||||
ScopedVars,
|
||||
DataSourceInstanceSettings,
|
||||
QueryResultMeta,
|
||||
MetricFindValue,
|
||||
} from '@grafana/data';
|
||||
import { getBackendSrv, getTemplateSrv, DataSourceWithBackend } from '@grafana/runtime';
|
||||
|
||||
export default class AzureLogAnalyticsDatasource {
|
||||
id: number;
|
||||
export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
||||
AzureMonitorQuery,
|
||||
AzureDataSourceJsonData
|
||||
> {
|
||||
url: string;
|
||||
baseUrl: string;
|
||||
applicationId: string;
|
||||
@@ -17,12 +23,8 @@ export default class AzureLogAnalyticsDatasource {
|
||||
subscriptionId: string;
|
||||
cache: Map<string, any>;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(
|
||||
private instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>,
|
||||
private templateSrv: TemplateSrv
|
||||
) {
|
||||
this.id = instanceSettings.id;
|
||||
constructor(private instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>) {
|
||||
super(instanceSettings);
|
||||
this.cache = new Map();
|
||||
|
||||
switch (this.instanceSettings.jsonData.cloudName) {
|
||||
@@ -88,7 +90,7 @@ export default class AzureLogAnalyticsDatasource {
|
||||
}
|
||||
|
||||
getWorkspaceList(subscription: string): Promise<any> {
|
||||
const subscriptionId = this.templateSrv.replace(subscription || this.subscriptionId);
|
||||
const subscriptionId = getTemplateSrv().replace(subscription || this.subscriptionId);
|
||||
|
||||
const workspaceListUrl =
|
||||
this.azureMonitorUrl +
|
||||
@@ -100,103 +102,70 @@ export default class AzureLogAnalyticsDatasource {
|
||||
if (!workspace) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const url = `${this.baseUrl}/${this.templateSrv.replace(workspace, {})}/metadata`;
|
||||
const url = `${this.baseUrl}/${getTemplateSrv().replace(workspace, {})}/metadata`;
|
||||
|
||||
return this.doRequest(url).then((response: any) => {
|
||||
return new ResponseParser(response.data).parseSchemaResult();
|
||||
});
|
||||
}
|
||||
|
||||
async query(options: DataQueryRequest<AzureMonitorQuery>) {
|
||||
const queries = _.filter(options.targets, item => {
|
||||
return item.hide !== true;
|
||||
}).map(target => {
|
||||
const item = target.azureLogAnalytics;
|
||||
|
||||
let workspace = this.templateSrv.replace(item.workspace, options.scopedVars);
|
||||
|
||||
if (!workspace && this.defaultOrFirstWorkspace) {
|
||||
workspace = this.defaultOrFirstWorkspace;
|
||||
}
|
||||
|
||||
const subscriptionId = this.templateSrv.replace(target.subscription || this.subscriptionId, options.scopedVars);
|
||||
const query = this.templateSrv.replace(item.query, options.scopedVars, this.interpolateVariable);
|
||||
|
||||
return {
|
||||
refId: target.refId,
|
||||
intervalMs: options.intervalMs,
|
||||
maxDataPoints: options.maxDataPoints,
|
||||
datasourceId: this.id,
|
||||
format: target.format,
|
||||
queryType: 'Azure Log Analytics',
|
||||
subscriptionId: subscriptionId,
|
||||
azureLogAnalytics: {
|
||||
resultFormat: item.resultFormat,
|
||||
query: query,
|
||||
workspace: workspace,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
if (!queries || queries.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { data } = await getBackendSrv().datasourceRequest({
|
||||
url: '/api/tsdb/query',
|
||||
method: 'POST',
|
||||
data: {
|
||||
from: options.range.from.valueOf().toString(),
|
||||
to: options.range.to.valueOf().toString(),
|
||||
queries,
|
||||
},
|
||||
});
|
||||
|
||||
const result: DataQueryResponseData[] = [];
|
||||
if (data.results) {
|
||||
const results: any[] = Object.values(data.results);
|
||||
for (let queryRes of results) {
|
||||
for (let series of queryRes.series || []) {
|
||||
const timeSeries: TimeSeries = {
|
||||
target: series.name,
|
||||
datapoints: series.points,
|
||||
refId: queryRes.refId,
|
||||
meta: queryRes.meta,
|
||||
};
|
||||
const df = toDataFrame(timeSeries);
|
||||
|
||||
if (queryRes.meta.encodedQuery && queryRes.meta.encodedQuery.length > 0) {
|
||||
const url = await this.buildDeepLink(queryRes);
|
||||
|
||||
if (url.length > 0) {
|
||||
for (const field of df.fields) {
|
||||
field.config.links = [
|
||||
{
|
||||
url: url,
|
||||
title: 'View in Azure Portal',
|
||||
targetBlank: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push(df);
|
||||
}
|
||||
|
||||
for (let table of queryRes.tables || []) {
|
||||
result.push(toDataFrame(table));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
filterQuery(item: AzureMonitorQuery): boolean {
|
||||
return item.hide !== true && !!item.azureLogAnalytics;
|
||||
}
|
||||
|
||||
private async buildDeepLink(queryRes: any) {
|
||||
const base64Enc = encodeURIComponent(queryRes.meta.encodedQuery);
|
||||
const workspaceId = queryRes.meta.workspace;
|
||||
const subscription = queryRes.meta.subscription;
|
||||
applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): Record<string, any> {
|
||||
const item = target.azureLogAnalytics;
|
||||
|
||||
const templateSrv = getTemplateSrv();
|
||||
let workspace = templateSrv.replace(item.workspace, scopedVars);
|
||||
|
||||
if (!workspace && this.defaultOrFirstWorkspace) {
|
||||
workspace = this.defaultOrFirstWorkspace;
|
||||
}
|
||||
|
||||
const subscriptionId = templateSrv.replace(target.subscription || this.subscriptionId, scopedVars);
|
||||
const query = templateSrv.replace(item.query, scopedVars, this.interpolateVariable);
|
||||
|
||||
return {
|
||||
refId: target.refId,
|
||||
format: target.format,
|
||||
queryType: 'Azure Log Analytics',
|
||||
subscriptionId: subscriptionId,
|
||||
azureLogAnalytics: {
|
||||
resultFormat: item.resultFormat,
|
||||
query: query,
|
||||
workspace: workspace,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async processResponse(res: DataQueryResponse): Promise<DataQueryResponse> {
|
||||
if (res.data) {
|
||||
for (const df of res.data) {
|
||||
const encodedQuery = df.meta?.custom?.encodedQuery;
|
||||
if (encodedQuery && encodedQuery.length > 0) {
|
||||
const url = await this.buildDeepLink(df.meta);
|
||||
if (url?.length) {
|
||||
for (const field of df.fields) {
|
||||
field.config.links = [
|
||||
{
|
||||
url: url,
|
||||
title: 'View in Azure Portal',
|
||||
targetBlank: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private async buildDeepLink(meta: QueryResultMeta) {
|
||||
const base64Enc = encodeURIComponent(meta.custom.encodedQuery);
|
||||
const workspaceId = meta.custom.workspace;
|
||||
const subscription = meta.custom.subscription;
|
||||
|
||||
const details = await this.getWorkspaceDetails(workspaceId);
|
||||
if (!details.workspace || !details.resourceGroup) {
|
||||
@@ -235,7 +204,7 @@ export default class AzureLogAnalyticsDatasource {
|
||||
};
|
||||
}
|
||||
|
||||
metricFindQuery(query: string) {
|
||||
metricFindQuery(query: string): Promise<MetricFindValue[]> {
|
||||
const workspacesQuery = query.match(/^workspaces\(\)/i);
|
||||
if (workspacesQuery) {
|
||||
return this.getWorkspaces(this.subscriptionId);
|
||||
@@ -268,12 +237,12 @@ export default class AzureLogAnalyticsDatasource {
|
||||
throw { message: err.error.data.error.message };
|
||||
}
|
||||
});
|
||||
});
|
||||
}) as Promise<MetricFindValue[]>; // ??
|
||||
}
|
||||
|
||||
private buildQuery(query: string, options: any, workspace: any) {
|
||||
const querystringBuilder = new LogAnalyticsQuerystringBuilder(
|
||||
this.templateSrv.replace(query, {}, this.interpolateVariable),
|
||||
getTemplateSrv().replace(query, {}, this.interpolateVariable),
|
||||
options,
|
||||
'TimeGenerated'
|
||||
);
|
||||
@@ -382,10 +351,10 @@ export default class AzureLogAnalyticsDatasource {
|
||||
}
|
||||
}
|
||||
|
||||
testDatasource() {
|
||||
testDatasource(): Promise<any> {
|
||||
const validationError = this.isValidConfig();
|
||||
if (validationError) {
|
||||
return validationError;
|
||||
return Promise.resolve(validationError);
|
||||
}
|
||||
|
||||
return this.getDefaultOrFirstWorkspace()
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('AzureMonitorDatasource', () => {
|
||||
jsonData: { subscriptionId: '9935389e-9122-4ef9-95f9-1513dd24753f' },
|
||||
cloudName: 'azuremonitor',
|
||||
} as unknown) as DataSourceInstanceSettings<AzureDataSourceJsonData>;
|
||||
ctx.ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
ctx.ds = new AzureMonitorDatasource(ctx.instanceSettings);
|
||||
});
|
||||
|
||||
describe('When performing testDatasource', () => {
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
DataQueryResponse,
|
||||
DataQueryResponseData,
|
||||
} from '@grafana/data';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDataSourceJsonData> {
|
||||
@@ -18,12 +17,11 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
|
||||
appInsightsDatasource: AppInsightsDatasource;
|
||||
azureLogAnalyticsDatasource: AzureLogAnalyticsDatasource;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>, private templateSrv: TemplateSrv) {
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>) {
|
||||
super(instanceSettings);
|
||||
this.azureMonitorDatasource = new AzureMonitorDatasource(instanceSettings);
|
||||
this.appInsightsDatasource = new AppInsightsDatasource(instanceSettings, this.templateSrv);
|
||||
this.azureLogAnalyticsDatasource = new AzureLogAnalyticsDatasource(instanceSettings, this.templateSrv);
|
||||
this.appInsightsDatasource = new AppInsightsDatasource(instanceSettings);
|
||||
this.azureLogAnalyticsDatasource = new AzureLogAnalyticsDatasource(instanceSettings);
|
||||
}
|
||||
|
||||
query(options: DataQueryRequest<AzureMonitorQuery>): Promise<DataQueryResponse> | Observable<DataQueryResponseData> {
|
||||
@@ -44,10 +42,13 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
|
||||
}
|
||||
|
||||
if (azureLogAnalyticsOptions.targets.length > 0) {
|
||||
const alaPromise = this.azureLogAnalyticsDatasource.query(azureLogAnalyticsOptions);
|
||||
if (alaPromise) {
|
||||
promises.push(alaPromise);
|
||||
const obs = this.azureLogAnalyticsDatasource.query(azureLogAnalyticsOptions);
|
||||
if (!promises.length) {
|
||||
return obs; // return the observable directly
|
||||
}
|
||||
// NOTE: this only includes the data!
|
||||
// When all three query types are ready to be observale, they should all use observable
|
||||
promises.push(obs.toPromise().then(r => r.data));
|
||||
}
|
||||
|
||||
if (azureMonitorOptions.targets.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user