AzureMonitor: support workspaces function for template variables (#22882)

* azuremonitor: adds support for workspaces query macro...

...for Azure Logs template variable queries

* docs: azure logs workspaces templating function

* Update docs/sources/features/datasources/azuremonitor.md

Co-Authored-By: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* docs: convert list into table

* docs: fixes prettier formatting problem

Prettier adds a slash before dollar signs in markdown. Disabling it
for this table with a prettier comment.

https://prettier.io/docs/en/ignore.html

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>
This commit is contained in:
Daniel Lee
2020-03-19 00:41:35 +01:00
committed by GitHub
parent ec9167e972
commit 3b9a4e6444
4 changed files with 162 additions and 37 deletions

View File

@@ -2,7 +2,7 @@ import AzureMonitorDatasource from '../datasource';
import FakeSchemaData from './__mocks__/schema';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { KustoSchema } from '../types';
import { KustoSchema, AzureLogsVariable } from '../types';
import { toUtc } from '@grafana/data';
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
@@ -283,53 +283,129 @@ describe('AzureLogAnalyticsDatasource', () => {
});
describe('When performing metricFindQuery', () => {
const tableResponseWithOneColumn = {
tables: [
{
name: 'PrimaryResult',
columns: [
{
name: 'Category',
type: 'string',
},
],
rows: [['Administrative'], ['Policy']],
},
],
};
let queryResults: AzureLogsVariable[];
const workspaceResponse = {
const workspacesResponse = {
value: [
{
name: 'aworkspace',
name: 'workspace1',
properties: {
source: 'Azure',
customerId: 'abc1b44e-3e57-4410-b027-6cc0ae6dee67',
customerId: 'eeee4fde-1aaa-4d60-9974-eeee562ffaa1',
},
},
{
name: 'workspace2',
properties: {
customerId: 'eeee4fde-1aaa-4d60-9974-eeee562ffaa2',
},
},
],
};
let queryResults: any[];
describe('and is the workspaces() macro', () => {
beforeEach(async () => {
datasourceRequestMock.mockImplementation((options: { url: string }) => {
expect(options.url).toContain('xxx');
return Promise.resolve({ data: workspacesResponse, status: 200 });
});
beforeEach(async () => {
datasourceRequestMock.mockImplementation((options: { url: string }) => {
if (options.url.indexOf('Microsoft.OperationalInsights/workspaces') > -1) {
return Promise.resolve({ data: workspaceResponse, status: 200 });
} else {
return Promise.resolve({ data: tableResponseWithOneColumn, status: 200 });
}
queryResults = await ctx.ds.metricFindQuery('workspaces()');
});
queryResults = await ctx.ds.metricFindQuery('workspace("aworkspace").AzureActivity | distinct Category');
it('should return a list of workspaces', () => {
expect(queryResults.length).toBe(2);
expect(queryResults[0].text).toBe('workspace1');
expect(queryResults[0].value).toBe('eeee4fde-1aaa-4d60-9974-eeee562ffaa1');
expect(queryResults[1].text).toBe('workspace2');
expect(queryResults[1].value).toBe('eeee4fde-1aaa-4d60-9974-eeee562ffaa2');
});
});
it('should return a list of categories in the correct format', () => {
expect(queryResults.length).toBe(2);
expect(queryResults[0].text).toBe('Administrative');
expect(queryResults[0].value).toBe('Administrative');
expect(queryResults[1].text).toBe('Policy');
expect(queryResults[1].value).toBe('Policy');
describe('and is the workspaces() macro with the subscription parameter', () => {
beforeEach(async () => {
datasourceRequestMock.mockImplementation((options: { url: string }) => {
expect(options.url).toContain('11112222-eeee-4949-9b2d-9106972f9123');
return Promise.resolve({ data: workspacesResponse, status: 200 });
});
queryResults = await ctx.ds.metricFindQuery('workspaces(11112222-eeee-4949-9b2d-9106972f9123)');
});
it('should return a list of workspaces', () => {
expect(queryResults.length).toBe(2);
expect(queryResults[0].text).toBe('workspace1');
expect(queryResults[0].value).toBe('eeee4fde-1aaa-4d60-9974-eeee562ffaa1');
expect(queryResults[1].text).toBe('workspace2');
expect(queryResults[1].value).toBe('eeee4fde-1aaa-4d60-9974-eeee562ffaa2');
});
});
describe('and is the workspaces() macro with the subscription parameter quoted', () => {
beforeEach(async () => {
datasourceRequestMock.mockImplementation((options: { url: string }) => {
expect(options.url).toContain('11112222-eeee-4949-9b2d-9106972f9123');
return Promise.resolve({ data: workspacesResponse, status: 200 });
});
queryResults = await ctx.ds.metricFindQuery('workspaces("11112222-eeee-4949-9b2d-9106972f9123")');
});
it('should return a list of workspaces', () => {
expect(queryResults.length).toBe(2);
expect(queryResults[0].text).toBe('workspace1');
expect(queryResults[0].value).toBe('eeee4fde-1aaa-4d60-9974-eeee562ffaa1');
expect(queryResults[1].text).toBe('workspace2');
expect(queryResults[1].value).toBe('eeee4fde-1aaa-4d60-9974-eeee562ffaa2');
});
});
describe('and is a custom query', () => {
const tableResponseWithOneColumn = {
tables: [
{
name: 'PrimaryResult',
columns: [
{
name: 'Category',
type: 'string',
},
],
rows: [['Administrative'], ['Policy']],
},
],
};
const workspaceResponse = {
value: [
{
name: 'aworkspace',
properties: {
source: 'Azure',
customerId: 'abc1b44e-3e57-4410-b027-6cc0ae6dee67',
},
},
],
};
beforeEach(async () => {
datasourceRequestMock.mockImplementation((options: { url: string }) => {
if (options.url.indexOf('Microsoft.OperationalInsights/workspaces') > -1) {
return Promise.resolve({ data: workspaceResponse, status: 200 });
} else {
return Promise.resolve({ data: tableResponseWithOneColumn, status: 200 });
}
});
queryResults = await ctx.ds.metricFindQuery('workspace("aworkspace").AzureActivity | distinct Category');
});
it('should return a list of categories in the correct format', () => {
expect(queryResults.length).toBe(2);
expect(queryResults[0].text).toBe('Administrative');
expect(queryResults[0].value).toBe('Administrative');
expect(queryResults[1].text).toBe('Policy');
expect(queryResults[1].value).toBe('Policy');
});
});
});

View File

@@ -1,7 +1,7 @@
import _ from 'lodash';
import LogAnalyticsQuerystringBuilder from '../log_analytics/querystring_builder';
import ResponseParser from './response_parser';
import { AzureMonitorQuery, AzureDataSourceJsonData } from '../types';
import { AzureMonitorQuery, AzureDataSourceJsonData, AzureLogsVariable } from '../types';
import { DataQueryRequest, DataSourceInstanceSettings } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
@@ -47,7 +47,7 @@ export default class AzureLogAnalyticsDatasource {
}
}
getWorkspaces(subscription: string) {
getWorkspaces(subscription: string): Promise<AzureLogsVariable[]> {
const subscriptionId = this.templateSrv.replace(subscription || this.subscriptionId);
const workspaceListUrl =
@@ -118,6 +118,16 @@ export default class AzureLogAnalyticsDatasource {
}
metricFindQuery(query: string) {
const workspacesQuery = query.match(/^workspaces\(\)/i);
if (workspacesQuery) {
return this.getWorkspaces(this.subscriptionId);
}
const workspacesQueryWithSub = query.match(/^workspaces\(["']?([^\)]+?)["']?\)/i);
if (workspacesQueryWithSub) {
return this.getWorkspaces((workspacesQueryWithSub[1] || '').trim());
}
return this.getDefaultOrFirstWorkspace().then((workspace: any) => {
const queries: any[] = this.buildQuery(query, null, workspace);

View File

@@ -160,7 +160,7 @@ describe('AzureMonitorDatasource', () => {
};
beforeEach(() => {
datasourceRequestMock.mockImplementation((options: { url: string }) => Promise.resolve(response));
datasourceRequestMock.mockImplementation(() => Promise.resolve(response));
});
it('should return a list of subscriptions', () => {