mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AzureMonitor: remove requirement for default subscription (#34787)
* Do not require default subscription for Azure Monitor * Fix explore URLs when default subscription not set * Test datasource fixes * Added comment * Fix first or default subscription/workspace * SubscriptionField doesn't depend on Log Analytics * Tests fixed * Select default subscription only when user clicked
This commit is contained in:
parent
48dc78fd48
commit
179eb0898e
@ -1,7 +1,7 @@
|
|||||||
import AzureMonitorDatasource from '../datasource';
|
import AzureMonitorDatasource from '../datasource';
|
||||||
import FakeSchemaData from './__mocks__/schema';
|
import FakeSchemaData from './__mocks__/schema';
|
||||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||||
import { AzureLogsVariable } from '../types';
|
import { AzureLogsVariable, DatasourceValidationResult } from '../types';
|
||||||
import { toUtc } from '@grafana/data';
|
import { toUtc } from '@grafana/data';
|
||||||
import { backendSrv } from 'app/core/services/backend_srv';
|
import { backendSrv } from 'app/core/services/backend_srv';
|
||||||
|
|
||||||
@ -112,17 +112,15 @@ describe('AzureLogAnalyticsDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.instanceSettings.jsonData.logAnalyticsSubscriptionId = 'xxx';
|
ctx.instanceSettings.jsonData.azureAuthType = 'msi';
|
||||||
ctx.instanceSettings.jsonData.logAnalyticsTenantId = 'xxx';
|
|
||||||
ctx.instanceSettings.jsonData.logAnalyticsClientId = 'xxx';
|
|
||||||
datasourceRequestMock.mockImplementation(() => Promise.reject(error));
|
datasourceRequestMock.mockImplementation(() => Promise.reject(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
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: any) => {
|
return ctx.ds.azureLogAnalyticsDatasource.testDatasource().then((result: DatasourceValidationResult) => {
|
||||||
expect(results.status).toEqual('error');
|
expect(result.status).toEqual('error');
|
||||||
expect(results.message).toEqual(
|
expect(result.message).toEqual(
|
||||||
'1. Azure Log Analytics: Bad Request: InvalidApiVersionParameter. An error message. '
|
'Azure Log Analytics requires access to Azure Monitor but had the following error: Bad Request: InvalidApiVersionParameter. An error message.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -37,7 +37,7 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
applicationId: string;
|
applicationId: string;
|
||||||
|
|
||||||
subscriptionId: string;
|
defaultSubscriptionId?: string;
|
||||||
|
|
||||||
azureMonitorUrl: string;
|
azureMonitorUrl: string;
|
||||||
defaultOrFirstWorkspace: string;
|
defaultOrFirstWorkspace: string;
|
||||||
@ -55,12 +55,24 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
this.azureMonitorUrl = `/${managementRoute}/subscriptions`;
|
this.azureMonitorUrl = `/${managementRoute}/subscriptions`;
|
||||||
|
|
||||||
this.url = instanceSettings.url || '';
|
this.url = instanceSettings.url || '';
|
||||||
this.subscriptionId = this.instanceSettings.jsonData.logAnalyticsSubscriptionId || '';
|
this.defaultSubscriptionId = this.instanceSettings.jsonData.logAnalyticsSubscriptionId || '';
|
||||||
this.defaultOrFirstWorkspace = this.instanceSettings.jsonData.logAnalyticsDefaultWorkspace || '';
|
this.defaultOrFirstWorkspace = this.instanceSettings.jsonData.logAnalyticsDefaultWorkspace || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
isConfigured(): boolean {
|
isConfigured(): boolean {
|
||||||
return !!this.subscriptionId && this.subscriptionId.length > 0;
|
// If validation didn't return any error then the data source is properly configured
|
||||||
|
return !this.validateDatasource();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSubscriptions(): Promise<Array<{ text: string; value: string }>> {
|
||||||
|
if (!this.isConfigured()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${this.azureMonitorUrl}?api-version=2019-03-01`;
|
||||||
|
return await this.doRequest(url).then((result: any) => {
|
||||||
|
return ResponseParser.parseSubscriptions(result);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getWorkspaces(subscription: string): Promise<AzureLogsVariable[]> {
|
async getWorkspaces(subscription: string): Promise<AzureLogsVariable[]> {
|
||||||
@ -73,8 +85,8 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getWorkspaceList(subscription: string): Promise<any> {
|
private getWorkspaceList(subscription: string): Promise<any> {
|
||||||
const subscriptionId = getTemplateSrv().replace(subscription || this.subscriptionId);
|
const subscriptionId = getTemplateSrv().replace(subscription || this.defaultSubscriptionId);
|
||||||
|
|
||||||
const workspaceListUrl =
|
const workspaceListUrl =
|
||||||
this.azureMonitorUrl +
|
this.azureMonitorUrl +
|
||||||
@ -109,7 +121,7 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
workspace = this.defaultOrFirstWorkspace;
|
workspace = this.defaultOrFirstWorkspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subscriptionId = templateSrv.replace(target.subscription || this.subscriptionId, scopedVars);
|
const subscriptionId = templateSrv.replace(target.subscription || this.defaultSubscriptionId, scopedVars);
|
||||||
const query = templateSrv.replace(item.query, scopedVars, this.interpolateVariable);
|
const query = templateSrv.replace(item.query, scopedVars, this.interpolateVariable);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -182,10 +194,10 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getWorkspaceDetails(workspaceId: string) {
|
async getWorkspaceDetails(workspaceId: string) {
|
||||||
if (!this.subscriptionId) {
|
if (!this.defaultSubscriptionId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const response = await this.getWorkspaceList(this.subscriptionId);
|
const response = await this.getWorkspaceList(this.defaultSubscriptionId);
|
||||||
|
|
||||||
const details = response.data.value.find((o: any) => {
|
const details = response.data.value.find((o: any) => {
|
||||||
return o.properties.customerId === workspaceId;
|
return o.properties.customerId === workspaceId;
|
||||||
@ -216,8 +228,8 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
metricFindQueryInternal(query: string): Promise<MetricFindValue[]> {
|
metricFindQueryInternal(query: string): Promise<MetricFindValue[]> {
|
||||||
// workspaces() - Get workspaces in the default subscription
|
// workspaces() - Get workspaces in the default subscription
|
||||||
const workspacesQuery = query.match(/^workspaces\(\)/i);
|
const workspacesQuery = query.match(/^workspaces\(\)/i);
|
||||||
if (workspacesQuery) {
|
if (workspacesQuery && this.defaultSubscriptionId) {
|
||||||
return this.getWorkspaces(this.subscriptionId);
|
return this.getWorkspaces(this.defaultSubscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// workspaces("abc-def-etc") - Get workspaces a specified subscription
|
// workspaces("abc-def-etc") - Get workspaces a specified subscription
|
||||||
@ -228,6 +240,10 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
|
|
||||||
// Execute the query as KQL to the default or first workspace
|
// Execute the query as KQL to the default or first workspace
|
||||||
return this.getDefaultOrFirstWorkspace().then((resourceURI) => {
|
return this.getDefaultOrFirstWorkspace().then((resourceURI) => {
|
||||||
|
if (!resourceURI) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const queries = this.buildQuery(query, null, resourceURI);
|
const queries = this.buildQuery(query, null, resourceURI);
|
||||||
const promises = this.doQueries(queries);
|
const promises = this.doQueries(queries);
|
||||||
|
|
||||||
@ -299,16 +315,32 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
return quotedValues.join(',');
|
return quotedValues.join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultOrFirstWorkspace() {
|
async getDefaultOrFirstSubscription(): Promise<string | undefined> {
|
||||||
|
if (this.defaultSubscriptionId) {
|
||||||
|
return this.defaultSubscriptionId;
|
||||||
|
}
|
||||||
|
const subscriptions = await this.getSubscriptions();
|
||||||
|
return subscriptions[0]?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDefaultOrFirstWorkspace(): Promise<string | undefined> {
|
||||||
if (this.defaultOrFirstWorkspace) {
|
if (this.defaultOrFirstWorkspace) {
|
||||||
return Promise.resolve(this.defaultOrFirstWorkspace);
|
return this.defaultOrFirstWorkspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getWorkspaces(this.subscriptionId).then((workspaces) => {
|
const subscriptionId = await this.getDefaultOrFirstSubscription();
|
||||||
this.defaultOrFirstWorkspace = workspaces[0].value;
|
if (!subscriptionId) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return this.defaultOrFirstWorkspace;
|
const workspaces = await this.getWorkspaces(subscriptionId);
|
||||||
});
|
const workspace = workspaces[0]?.value;
|
||||||
|
|
||||||
|
if (workspace) {
|
||||||
|
this.defaultOrFirstWorkspace = workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
annotationQuery(options: any) {
|
annotationQuery(options: any) {
|
||||||
@ -371,21 +403,36 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update to be completely resource-centric
|
// TODO: update to be completely resource-centric
|
||||||
testDatasource(): Promise<DatasourceValidationResult> {
|
async testDatasource(): Promise<DatasourceValidationResult> {
|
||||||
const validationError = this.validateDatasource();
|
const validationError = this.validateDatasource();
|
||||||
if (validationError) {
|
if (validationError) {
|
||||||
return Promise.resolve(validationError);
|
return validationError;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getDefaultOrFirstWorkspace()
|
let resourceOrWorkspace: string;
|
||||||
.then((resourceOrWorkspace) => {
|
try {
|
||||||
const url = isGUIDish(resourceOrWorkspace)
|
const result = await this.getDefaultOrFirstWorkspace();
|
||||||
? `${this.baseUrl}/v1/workspaces/${resourceOrWorkspace}/metadata`
|
if (!result) {
|
||||||
: `${this.baseUrl}/v1${resourceOrWorkspace}/metadata`;
|
return {
|
||||||
|
status: 'error',
|
||||||
|
message: 'Workspace not found.',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
resourceOrWorkspace = result;
|
||||||
|
} catch (e) {
|
||||||
|
let message = 'Azure Log Analytics requires access to Azure Monitor but had the following error: ';
|
||||||
|
return {
|
||||||
|
status: 'error',
|
||||||
|
message: this.getErrorMessage(message, e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return this.doRequest(url);
|
try {
|
||||||
})
|
const url = isGUIDish(resourceOrWorkspace)
|
||||||
.then<DatasourceValidationResult>((response: any) => {
|
? `${this.baseUrl}/v1/workspaces/${resourceOrWorkspace}/metadata`
|
||||||
|
: `${this.baseUrl}/v1${resourceOrWorkspace}/metadata`;
|
||||||
|
|
||||||
|
return await this.doRequest(url).then<DatasourceValidationResult>((response: any) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
return {
|
return {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@ -398,20 +445,14 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
status: 'error',
|
status: 'error',
|
||||||
message: 'Returned http status code ' + response.status,
|
message: 'Returned http status code ' + response.status,
|
||||||
};
|
};
|
||||||
})
|
|
||||||
.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: ';
|
|
||||||
}
|
|
||||||
|
|
||||||
message = this.getErrorMessage(message, error);
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: 'error',
|
|
||||||
message: message,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
let message = 'Azure Log Analytics: ';
|
||||||
|
return {
|
||||||
|
status: 'error',
|
||||||
|
message: this.getErrorMessage(message, e),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getErrorMessage(message: string, error: any) {
|
private getErrorMessage(message: string, error: any) {
|
||||||
@ -447,13 +488,6 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isValidConfigField(this.subscriptionId)) {
|
|
||||||
return {
|
|
||||||
status: 'error',
|
|
||||||
message: 'The Subscription Id field is required.',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { concat, find, flattenDeep, forEach, map } from 'lodash';
|
import { concat, find, flattenDeep, forEach, get, map } from 'lodash';
|
||||||
import { AnnotationEvent, dateTime, TimeSeries } from '@grafana/data';
|
import { AnnotationEvent, dateTime, TimeSeries } from '@grafana/data';
|
||||||
import { AzureLogsTableData, AzureLogsVariable } from '../types';
|
import { AzureLogsTableData, AzureLogsVariable } from '../types';
|
||||||
import { AzureLogAnalyticsMetadata } from '../types/logAnalyticsMetadata';
|
import { AzureLogAnalyticsMetadata } from '../types/logAnalyticsMetadata';
|
||||||
@ -147,6 +147,27 @@ export default class ResponseParser {
|
|||||||
static dateTimeToEpoch(dateTimeValue: any) {
|
static dateTimeToEpoch(dateTimeValue: any) {
|
||||||
return dateTime(dateTimeValue).valueOf();
|
return dateTime(dateTimeValue).valueOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static parseSubscriptions(result: any): Array<{ text: string; value: string }> {
|
||||||
|
const list: Array<{ text: string; value: string }> = [];
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueFieldName = 'subscriptionId';
|
||||||
|
const textFieldName = 'displayName';
|
||||||
|
for (let i = 0; i < result.data.value.length; i++) {
|
||||||
|
if (!find(list, ['value', get(result.data.value[i], valueFieldName)])) {
|
||||||
|
list.push({
|
||||||
|
text: `${get(result.data.value[i], textFieldName)}`,
|
||||||
|
value: get(result.data.value[i], valueFieldName),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// matches (name):(type) = (defaultValue)
|
// matches (name):(type) = (defaultValue)
|
||||||
|
@ -3,7 +3,7 @@ import AzureMonitorDatasource from '../datasource';
|
|||||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||||
import { DataSourceInstanceSettings } from '@grafana/data';
|
import { DataSourceInstanceSettings } from '@grafana/data';
|
||||||
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
|
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
|
||||||
import { AzureDataSourceJsonData } from '../types';
|
import { AzureDataSourceJsonData, DatasourceValidationResult } from '../types';
|
||||||
|
|
||||||
const templateSrv = new TemplateSrv();
|
const templateSrv = new TemplateSrv();
|
||||||
|
|
||||||
@ -47,17 +47,14 @@ describe('AzureMonitorDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.instanceSettings.jsonData.tenantId = 'xxx';
|
ctx.instanceSettings.jsonData.azureAuthType = 'msi';
|
||||||
ctx.instanceSettings.jsonData.clientId = 'xxx';
|
|
||||||
datasourceRequestMock.mockImplementation(() => Promise.reject(error));
|
datasourceRequestMock.mockImplementation(() => Promise.reject(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
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: any) => {
|
return ctx.ds.azureMonitorDatasource.testDatasource().then((result: DatasourceValidationResult) => {
|
||||||
expect(results.status).toEqual('error');
|
expect(result.status).toEqual('error');
|
||||||
expect(results.message).toEqual(
|
expect(result.message).toEqual('Azure Monitor: Bad Request: InvalidApiVersionParameter. An error message.');
|
||||||
'1. Azure Monitor: Bad Request: InvalidApiVersionParameter. An error message. '
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -78,8 +75,8 @@ describe('AzureMonitorDatasource', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return success status', () => {
|
it('should return success status', () => {
|
||||||
return ctx.ds.testDatasource().then((results: any) => {
|
return ctx.ds.azureMonitorDatasource.testDatasource().then((result: DatasourceValidationResult) => {
|
||||||
expect(results.status).toEqual('success');
|
expect(result.status).toEqual('success');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -99,6 +96,7 @@ describe('AzureMonitorDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
ctx.instanceSettings.jsonData.azureAuthType = 'msi';
|
||||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -515,10 +513,11 @@ describe('AzureMonitorDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
ctx.instanceSettings.jsonData.azureAuthType = 'msi';
|
||||||
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return list of Resource Groups', () => {
|
it('should return list of subscriptions', () => {
|
||||||
return ctx.ds.getSubscriptions().then((results: Array<{ text: string; value: string }>) => {
|
return ctx.ds.getSubscriptions().then((results: Array<{ text: string; value: string }>) => {
|
||||||
expect(results.length).toEqual(1);
|
expect(results.length).toEqual(1);
|
||||||
expect(results[0].text).toEqual('Primary Subscription');
|
expect(results[0].text).toEqual('Primary Subscription');
|
||||||
|
@ -44,7 +44,7 @@ const aggregationTypeMap: Record<string, number> = {
|
|||||||
export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureMonitorQuery, AzureDataSourceJsonData> {
|
export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureMonitorQuery, AzureDataSourceJsonData> {
|
||||||
apiVersion = '2018-01-01';
|
apiVersion = '2018-01-01';
|
||||||
apiPreviewVersion = '2017-12-01-preview';
|
apiPreviewVersion = '2017-12-01-preview';
|
||||||
subscriptionId: string;
|
defaultSubscriptionId?: string;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
resourceGroup: string;
|
resourceGroup: string;
|
||||||
resourceName: string;
|
resourceName: string;
|
||||||
@ -56,7 +56,7 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
super(instanceSettings);
|
super(instanceSettings);
|
||||||
|
|
||||||
this.timeSrv = getTimeSrv();
|
this.timeSrv = getTimeSrv();
|
||||||
this.subscriptionId = instanceSettings.jsonData.subscriptionId!;
|
this.defaultSubscriptionId = instanceSettings.jsonData.subscriptionId;
|
||||||
|
|
||||||
const cloud = getAzureCloud(instanceSettings);
|
const cloud = getAzureCloud(instanceSettings);
|
||||||
const route = getManagementApiRoute(cloud);
|
const route = getManagementApiRoute(cloud);
|
||||||
@ -67,7 +67,8 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
}
|
}
|
||||||
|
|
||||||
isConfigured(): boolean {
|
isConfigured(): boolean {
|
||||||
return !!this.subscriptionId && this.subscriptionId.length > 0;
|
// If validation didn't return any error then the data source is properly configured
|
||||||
|
return !this.validateDatasource();
|
||||||
}
|
}
|
||||||
|
|
||||||
filterQuery(item: AzureMonitorQuery): boolean {
|
filterQuery(item: AzureMonitorQuery): boolean {
|
||||||
@ -105,9 +106,13 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
): Promise<DataQueryResponse> {
|
): Promise<DataQueryResponse> {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
for (const df of res.data) {
|
for (const df of res.data) {
|
||||||
const metricQuery = metricQueries[df.refId]?.azureMonitor;
|
const metricQuery = metricQueries[df.refId];
|
||||||
if (metricQuery) {
|
if (metricQuery && metricQuery.azureMonitor) {
|
||||||
const url = this.buildAzurePortalUrl(metricQuery, this.subscriptionId, this.timeSrv.timeRange());
|
const url = this.buildAzurePortalUrl(
|
||||||
|
metricQuery.azureMonitor,
|
||||||
|
metricQuery.subscription,
|
||||||
|
this.timeSrv.timeRange()
|
||||||
|
);
|
||||||
|
|
||||||
for (const field of df.fields) {
|
for (const field of df.fields) {
|
||||||
field.config.links = [
|
field.config.links = [
|
||||||
@ -174,7 +179,7 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
|
|
||||||
const templateSrv = getTemplateSrv();
|
const templateSrv = getTemplateSrv();
|
||||||
|
|
||||||
const subscriptionId = templateSrv.replace(target.subscription || this.subscriptionId, scopedVars);
|
const subscriptionId = templateSrv.replace(target.subscription || this.defaultSubscriptionId, scopedVars);
|
||||||
const resourceGroup = templateSrv.replace(item.resourceGroup, scopedVars);
|
const resourceGroup = templateSrv.replace(item.resourceGroup, scopedVars);
|
||||||
const resourceName = templateSrv.replace(item.resourceName, scopedVars);
|
const resourceName = templateSrv.replace(item.resourceName, scopedVars);
|
||||||
const metricNamespace = templateSrv.replace(item.metricNamespace, scopedVars);
|
const metricNamespace = templateSrv.replace(item.metricNamespace, scopedVars);
|
||||||
@ -229,8 +234,8 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
}
|
}
|
||||||
|
|
||||||
const resourceGroupsQuery = query.match(/^ResourceGroups\(\)/i);
|
const resourceGroupsQuery = query.match(/^ResourceGroups\(\)/i);
|
||||||
if (resourceGroupsQuery) {
|
if (resourceGroupsQuery && this.defaultSubscriptionId) {
|
||||||
return this.getResourceGroups(this.subscriptionId);
|
return this.getResourceGroups(this.defaultSubscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceGroupsQueryWithSub = query.match(/^ResourceGroups\(([^\)]+?)(,\s?([^,]+?))?\)/i);
|
const resourceGroupsQueryWithSub = query.match(/^ResourceGroups\(([^\)]+?)(,\s?([^,]+?))?\)/i);
|
||||||
@ -239,9 +244,9 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
}
|
}
|
||||||
|
|
||||||
const metricDefinitionsQuery = query.match(/^Namespaces\(([^\)]+?)(,\s?([^,]+?))?\)/i);
|
const metricDefinitionsQuery = query.match(/^Namespaces\(([^\)]+?)(,\s?([^,]+?))?\)/i);
|
||||||
if (metricDefinitionsQuery) {
|
if (metricDefinitionsQuery && this.defaultSubscriptionId) {
|
||||||
if (!metricDefinitionsQuery[3]) {
|
if (!metricDefinitionsQuery[3]) {
|
||||||
return this.getMetricDefinitions(this.subscriptionId, this.toVariable(metricDefinitionsQuery[1]));
|
return this.getMetricDefinitions(this.defaultSubscriptionId, this.toVariable(metricDefinitionsQuery[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,10 +259,10 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
}
|
}
|
||||||
|
|
||||||
const resourceNamesQuery = query.match(/^ResourceNames\(([^,]+?),\s?([^,]+?)\)/i);
|
const resourceNamesQuery = query.match(/^ResourceNames\(([^,]+?),\s?([^,]+?)\)/i);
|
||||||
if (resourceNamesQuery) {
|
if (resourceNamesQuery && this.defaultSubscriptionId) {
|
||||||
const resourceGroup = this.toVariable(resourceNamesQuery[1]);
|
const resourceGroup = this.toVariable(resourceNamesQuery[1]);
|
||||||
const metricDefinition = this.toVariable(resourceNamesQuery[2]);
|
const metricDefinition = this.toVariable(resourceNamesQuery[2]);
|
||||||
return this.getResourceNames(this.subscriptionId, resourceGroup, metricDefinition);
|
return this.getResourceNames(this.defaultSubscriptionId, resourceGroup, metricDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceNamesQueryWithSub = query.match(/^ResourceNames\(([^,]+?),\s?([^,]+?),\s?(.+?)\)/i);
|
const resourceNamesQueryWithSub = query.match(/^ResourceNames\(([^,]+?),\s?([^,]+?),\s?(.+?)\)/i);
|
||||||
@ -269,11 +274,11 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
}
|
}
|
||||||
|
|
||||||
const metricNamespaceQuery = query.match(/^MetricNamespace\(([^,]+?),\s?([^,]+?),\s?([^,]+?)\)/i);
|
const metricNamespaceQuery = query.match(/^MetricNamespace\(([^,]+?),\s?([^,]+?),\s?([^,]+?)\)/i);
|
||||||
if (metricNamespaceQuery) {
|
if (metricNamespaceQuery && this.defaultSubscriptionId) {
|
||||||
const resourceGroup = this.toVariable(metricNamespaceQuery[1]);
|
const resourceGroup = this.toVariable(metricNamespaceQuery[1]);
|
||||||
const metricDefinition = this.toVariable(metricNamespaceQuery[2]);
|
const metricDefinition = this.toVariable(metricNamespaceQuery[2]);
|
||||||
const resourceName = this.toVariable(metricNamespaceQuery[3]);
|
const resourceName = this.toVariable(metricNamespaceQuery[3]);
|
||||||
return this.getMetricNamespaces(this.subscriptionId, resourceGroup, metricDefinition, resourceName);
|
return this.getMetricNamespaces(this.defaultSubscriptionId, resourceGroup, metricDefinition, resourceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
const metricNamespaceQueryWithSub = query.match(
|
const metricNamespaceQueryWithSub = query.match(
|
||||||
@ -288,13 +293,19 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
}
|
}
|
||||||
|
|
||||||
const metricNamesQuery = query.match(/^MetricNames\(([^,]+?),\s?([^,]+?),\s?([^,]+?),\s?([^,]+?)\)/i);
|
const metricNamesQuery = query.match(/^MetricNames\(([^,]+?),\s?([^,]+?),\s?([^,]+?),\s?([^,]+?)\)/i);
|
||||||
if (metricNamesQuery) {
|
if (metricNamesQuery && this.defaultSubscriptionId) {
|
||||||
if (metricNamesQuery[3].indexOf(',') === -1) {
|
if (metricNamesQuery[3].indexOf(',') === -1) {
|
||||||
const resourceGroup = this.toVariable(metricNamesQuery[1]);
|
const resourceGroup = this.toVariable(metricNamesQuery[1]);
|
||||||
const metricDefinition = this.toVariable(metricNamesQuery[2]);
|
const metricDefinition = this.toVariable(metricNamesQuery[2]);
|
||||||
const resourceName = this.toVariable(metricNamesQuery[3]);
|
const resourceName = this.toVariable(metricNamesQuery[3]);
|
||||||
const metricNamespace = this.toVariable(metricNamesQuery[4]);
|
const metricNamespace = this.toVariable(metricNamesQuery[4]);
|
||||||
return this.getMetricNames(this.subscriptionId, resourceGroup, metricDefinition, resourceName, metricNamespace);
|
return this.getMetricNames(
|
||||||
|
this.defaultSubscriptionId,
|
||||||
|
resourceGroup,
|
||||||
|
metricDefinition,
|
||||||
|
resourceName,
|
||||||
|
metricNamespace
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,9 +329,13 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
return getTemplateSrv().replace((metric || '').trim());
|
return getTemplateSrv().replace((metric || '').trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
getSubscriptions() {
|
async getSubscriptions(): Promise<Array<{ text: string; value: string }>> {
|
||||||
|
if (!this.isConfigured()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const url = `${this.baseUrl}?api-version=2019-03-01`;
|
const url = `${this.baseUrl}?api-version=2019-03-01`;
|
||||||
return this.doRequest(url).then((result: any) => {
|
return await this.doRequest(url).then((result: any) => {
|
||||||
return ResponseParser.parseSubscriptions(result);
|
return ResponseParser.parseSubscriptions(result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -459,15 +474,16 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
testDatasource(): Promise<DatasourceValidationResult> {
|
async testDatasource(): Promise<DatasourceValidationResult> {
|
||||||
const validationError = this.validateDatasource();
|
const validationError = this.validateDatasource();
|
||||||
if (validationError) {
|
if (validationError) {
|
||||||
return Promise.resolve(validationError);
|
return Promise.resolve(validationError);
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `${this.baseUrl}?api-version=2019-03-01`;
|
try {
|
||||||
return this.doRequest(url)
|
const url = `${this.baseUrl}?api-version=2019-03-01`;
|
||||||
.then<DatasourceValidationResult>((response: any) => {
|
|
||||||
|
return await this.doRequest(url).then<DatasourceValidationResult>((response: any) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
return {
|
return {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@ -480,25 +496,25 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
status: 'error',
|
status: 'error',
|
||||||
message: 'Returned http status code ' + response.status,
|
message: 'Returned http status code ' + response.status,
|
||||||
};
|
};
|
||||||
})
|
|
||||||
.catch((error: any) => {
|
|
||||||
let message = 'Azure Monitor: ';
|
|
||||||
message += error.statusText ? error.statusText + ': ' : '';
|
|
||||||
|
|
||||||
if (error.data && error.data.error && error.data.error.code) {
|
|
||||||
message += error.data.error.code + '. ' + error.data.error.message;
|
|
||||||
} else if (error.data && error.data.error) {
|
|
||||||
message += error.data.error;
|
|
||||||
} else if (error.data) {
|
|
||||||
message += error.data;
|
|
||||||
} else {
|
|
||||||
message += 'Cannot connect to Azure Monitor REST API.';
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
status: 'error',
|
|
||||||
message: message,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
let message = 'Azure Monitor: ';
|
||||||
|
message += e.statusText ? e.statusText + ': ' : '';
|
||||||
|
|
||||||
|
if (e.data && e.data.error && e.data.error.code) {
|
||||||
|
message += e.data.error.code + '. ' + e.data.error.message;
|
||||||
|
} else if (e.data && e.data.error) {
|
||||||
|
message += e.data.error;
|
||||||
|
} else if (e.data) {
|
||||||
|
message += e.data;
|
||||||
|
} else {
|
||||||
|
message += 'Cannot connect to Azure Monitor REST API.';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
status: 'error',
|
||||||
|
message: message,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateDatasource(): DatasourceValidationResult | undefined {
|
private validateDatasource(): DatasourceValidationResult | undefined {
|
||||||
@ -520,13 +536,6 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isValidConfigField(this.subscriptionId)) {
|
|
||||||
return {
|
|
||||||
status: 'error',
|
|
||||||
message: 'The Subscription Id field is required.',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import QueryField from './QueryField';
|
|||||||
interface LogsQueryEditorProps {
|
interface LogsQueryEditorProps {
|
||||||
query: AzureMonitorQuery;
|
query: AzureMonitorQuery;
|
||||||
datasource: Datasource;
|
datasource: Datasource;
|
||||||
subscriptionId: string;
|
subscriptionId?: string;
|
||||||
onChange: (newQuery: AzureMonitorQuery) => void;
|
onChange: (newQuery: AzureMonitorQuery) => void;
|
||||||
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
||||||
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
||||||
|
@ -29,7 +29,7 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
|
|||||||
const hasRequiredFields = isCredentialsComplete(credentials);
|
const hasRequiredFields = isCredentialsComplete(credentials);
|
||||||
|
|
||||||
const [subscriptions, setSubscriptions] = useState<Array<SelectableValue<string>>>([]);
|
const [subscriptions, setSubscriptions] = useState<Array<SelectableValue<string>>>([]);
|
||||||
const [loadSubscriptions, onLoadSubscriptions] = useReducer((val) => val + 1, 0);
|
const [loadSubscriptionsClicked, onLoadSubscriptions] = useReducer((val) => val + 1, 0);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!getSubscriptions || !hasRequiredFields) {
|
if (!getSubscriptions || !hasRequiredFields) {
|
||||||
updateSubscriptions([]);
|
updateSubscriptions([]);
|
||||||
@ -38,7 +38,7 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
|
|||||||
let canceled = false;
|
let canceled = false;
|
||||||
getSubscriptions().then((result) => {
|
getSubscriptions().then((result) => {
|
||||||
if (!canceled) {
|
if (!canceled) {
|
||||||
updateSubscriptions(result);
|
updateSubscriptions(result, loadSubscriptionsClicked);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return () => {
|
return () => {
|
||||||
@ -46,18 +46,18 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
|
|||||||
};
|
};
|
||||||
// This effect is intended to be called only once initially and on Load Subscriptions click
|
// This effect is intended to be called only once initially and on Load Subscriptions click
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [loadSubscriptions]);
|
}, [loadSubscriptionsClicked]);
|
||||||
|
|
||||||
const updateSubscriptions = (received: Array<SelectableValue<string>>) => {
|
const updateSubscriptions = (received: Array<SelectableValue<string>>, autoSelect = false) => {
|
||||||
setSubscriptions(received);
|
setSubscriptions(received);
|
||||||
if (getSubscriptions) {
|
if (getSubscriptions) {
|
||||||
if (!credentials.defaultSubscriptionId && received.length > 0) {
|
if (autoSelect && !credentials.defaultSubscriptionId && received.length > 0) {
|
||||||
// Setting the default subscription if subscriptions received but no default subscription selected
|
// Selecting the default subscription if subscriptions received but no default subscription selected
|
||||||
onSubscriptionChange(received[0]);
|
onSubscriptionChange(received[0]);
|
||||||
} else if (credentials.defaultSubscriptionId) {
|
} else if (credentials.defaultSubscriptionId) {
|
||||||
const found = received.find((opt) => opt.value === credentials.defaultSubscriptionId);
|
const found = received.find((opt) => opt.value === credentials.defaultSubscriptionId);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
// Unsetting the default found if it isn't found among the received subscriptions
|
// Unselecting the default subscription if it isn't found among the received subscriptions
|
||||||
onSubscriptionChange(undefined);
|
onSubscriptionChange(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import useMigrations from './useMigrations';
|
|||||||
interface LogsQueryEditorProps {
|
interface LogsQueryEditorProps {
|
||||||
query: AzureMonitorQuery;
|
query: AzureMonitorQuery;
|
||||||
datasource: Datasource;
|
datasource: Datasource;
|
||||||
subscriptionId: string;
|
subscriptionId?: string;
|
||||||
onChange: (newQuery: AzureMonitorQuery) => void;
|
onChange: (newQuery: AzureMonitorQuery) => void;
|
||||||
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
||||||
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
||||||
|
@ -19,6 +19,7 @@ const WorkspaceField: React.FC<AzureQueryEditorFieldProps> = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!subscriptionId) {
|
if (!subscriptionId) {
|
||||||
workspaces.length > 0 && setWorkspaces([]);
|
workspaces.length > 0 && setWorkspaces([]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource
|
datasource
|
||||||
|
@ -19,7 +19,7 @@ import { InlineFieldRow } from '@grafana/ui';
|
|||||||
interface MetricsQueryEditorProps {
|
interface MetricsQueryEditorProps {
|
||||||
query: AzureMonitorQuery;
|
query: AzureMonitorQuery;
|
||||||
datasource: Datasource;
|
datasource: Datasource;
|
||||||
subscriptionId: string;
|
subscriptionId?: string;
|
||||||
onChange: (newQuery: AzureMonitorQuery) => void;
|
onChange: (newQuery: AzureMonitorQuery) => void;
|
||||||
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
||||||
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
||||||
|
@ -20,7 +20,7 @@ interface BaseQueryEditorProps {
|
|||||||
|
|
||||||
const QueryEditor: React.FC<BaseQueryEditorProps> = ({ query, datasource, onChange }) => {
|
const QueryEditor: React.FC<BaseQueryEditorProps> = ({ query, datasource, onChange }) => {
|
||||||
const [errorMessage, setError] = useLastError();
|
const [errorMessage, setError] = useLastError();
|
||||||
const subscriptionId = query.subscription || datasource.azureMonitorDatasource.subscriptionId;
|
const subscriptionId = query.subscription || datasource.azureMonitorDatasource.defaultSubscriptionId;
|
||||||
const variableOptionGroup = {
|
const variableOptionGroup = {
|
||||||
label: 'Template Variables',
|
label: 'Template Variables',
|
||||||
options: datasource.getVariables().map((v) => ({ label: v, value: v })),
|
options: datasource.getVariables().map((v) => ({ label: v, value: v })),
|
||||||
@ -52,7 +52,7 @@ const QueryEditor: React.FC<BaseQueryEditorProps> = ({ query, datasource, onChan
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface EditorForQueryTypeProps extends BaseQueryEditorProps {
|
interface EditorForQueryTypeProps extends BaseQueryEditorProps {
|
||||||
subscriptionId: string;
|
subscriptionId?: string;
|
||||||
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,6 @@ const SubscriptionField: React.FC<SubscriptionFieldProps> = ({
|
|||||||
const [subscriptions, setSubscriptions] = useState<AzureMonitorOption[]>([]);
|
const [subscriptions, setSubscriptions] = useState<AzureMonitorOption[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!datasource.azureMonitorDatasource.isConfigured()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
datasource.azureMonitorDatasource
|
datasource.azureMonitorDatasource
|
||||||
.getSubscriptions()
|
.getSubscriptions()
|
||||||
.then((results) => {
|
.then((results) => {
|
||||||
@ -34,28 +30,22 @@ const SubscriptionField: React.FC<SubscriptionFieldProps> = ({
|
|||||||
setSubscriptions(newSubscriptions);
|
setSubscriptions(newSubscriptions);
|
||||||
setError(ERROR_SOURCE, undefined);
|
setError(ERROR_SOURCE, undefined);
|
||||||
|
|
||||||
// Set a default subscription ID, if we can
|
let newSubscription = query.subscription || datasource.azureMonitorDatasource.defaultSubscriptionId;
|
||||||
let newSubscription = query.subscription;
|
|
||||||
|
|
||||||
if (!newSubscription && query.queryType === AzureQueryType.AzureMonitor) {
|
|
||||||
newSubscription = datasource.azureMonitorDatasource.subscriptionId;
|
|
||||||
} else if (!query.subscription && query.queryType === AzureQueryType.LogAnalytics) {
|
|
||||||
newSubscription = datasource.azureLogAnalyticsDatasource.subscriptionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newSubscription && newSubscriptions.length > 0) {
|
if (!newSubscription && newSubscriptions.length > 0) {
|
||||||
newSubscription = newSubscriptions[0].value;
|
newSubscription = newSubscriptions[0].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
newSubscription !== query.subscription &&
|
if (newSubscription && newSubscription !== query.subscription) {
|
||||||
onQueryChange({
|
onQueryChange({
|
||||||
...query,
|
...query,
|
||||||
subscription: newSubscription,
|
subscription: newSubscription,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => setError(ERROR_SOURCE, err));
|
.catch((err) => setError(ERROR_SOURCE, err));
|
||||||
}, [
|
}, [
|
||||||
datasource.azureLogAnalyticsDatasource?.subscriptionId,
|
datasource.azureMonitorDatasource?.defaultSubscriptionId,
|
||||||
datasource.azureMonitorDatasource,
|
datasource.azureMonitorDatasource,
|
||||||
onQueryChange,
|
onQueryChange,
|
||||||
query,
|
query,
|
||||||
|
@ -14,7 +14,7 @@ export interface MetricMetadata {
|
|||||||
export function useMetricsMetadata(
|
export function useMetricsMetadata(
|
||||||
datasource: Datasource,
|
datasource: Datasource,
|
||||||
query: AzureMonitorQuery,
|
query: AzureMonitorQuery,
|
||||||
subscriptionId: string,
|
subscriptionId: string | undefined,
|
||||||
onQueryChange: (newQuery: AzureMonitorQuery) => void
|
onQueryChange: (newQuery: AzureMonitorQuery) => void
|
||||||
) {
|
) {
|
||||||
const [metricMetadata, setMetricMetadata] = useState<MetricMetadata>({
|
const [metricMetadata, setMetricMetadata] = useState<MetricMetadata>({
|
||||||
|
@ -150,26 +150,13 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
|
|||||||
async testDatasource(): Promise<DatasourceValidationResult> {
|
async testDatasource(): Promise<DatasourceValidationResult> {
|
||||||
const promises: Array<Promise<DatasourceValidationResult>> = [];
|
const promises: Array<Promise<DatasourceValidationResult>> = [];
|
||||||
|
|
||||||
if (this.azureMonitorDatasource.isConfigured()) {
|
promises.push(this.azureMonitorDatasource.testDatasource());
|
||||||
promises.push(this.azureMonitorDatasource.testDatasource());
|
promises.push(this.azureLogAnalyticsDatasource.testDatasource());
|
||||||
}
|
|
||||||
|
|
||||||
if (this.appInsightsDatasource.isConfigured()) {
|
if (this.appInsightsDatasource.isConfigured()) {
|
||||||
promises.push(this.appInsightsDatasource.testDatasource());
|
promises.push(this.appInsightsDatasource.testDatasource());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.azureLogAnalyticsDatasource.isConfigured()) {
|
|
||||||
promises.push(this.azureLogAnalyticsDatasource.testDatasource());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (promises.length === 0) {
|
|
||||||
return {
|
|
||||||
status: 'error',
|
|
||||||
message: `Nothing configured. At least one of the API's must be configured.`,
|
|
||||||
title: 'Error',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return await Promise.all(promises).then((results) => {
|
return await Promise.all(promises).then((results) => {
|
||||||
let status: 'success' | 'error' = 'success';
|
let status: 'success' | 'error' = 'success';
|
||||||
let message = '';
|
let message = '';
|
||||||
|
@ -222,7 +222,7 @@ export interface AzureMonitorOption<T = string> {
|
|||||||
export interface AzureQueryEditorFieldProps {
|
export interface AzureQueryEditorFieldProps {
|
||||||
query: AzureMonitorQuery;
|
query: AzureMonitorQuery;
|
||||||
datasource: Datasource;
|
datasource: Datasource;
|
||||||
subscriptionId: string;
|
subscriptionId?: string;
|
||||||
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
||||||
|
|
||||||
onQueryChange: (newQuery: AzureMonitorQuery) => void;
|
onQueryChange: (newQuery: AzureMonitorQuery) => void;
|
||||||
|
Loading…
Reference in New Issue
Block a user