mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
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:
parent
ec9167e972
commit
3b9a4e6444
@ -274,6 +274,45 @@ There are also some Grafana variables that can be used in Azure Log Analytics qu
|
||||
|
||||
- `$__interval` - Grafana calculates the minimum time grain that can be used to group by time in queries. More details on how it works [here]({{< relref "../../reference/templating.md#interval-variables" >}}). It returns a time grain like `5m` or `1h` that can be used in the bin function. E.g. `summarize count() by bin(TimeGenerated, $__interval)`
|
||||
|
||||
### Templating with Variables for Azure Log Analytics
|
||||
|
||||
Any Log Analytics query that returns a list of values can be used in the `Query` field in the Variable edit view. There is also one Grafana function for Log Analytics that returns a list of workspaces.
|
||||
|
||||
Refer to the [Variables]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
|
||||
types of template variables.
|
||||
|
||||
| Name | Description |
|
||||
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| _workspaces()_ | Returns a list of workspaces for the default subscription. |
|
||||
| _workspaces(12345678-aaaa-bbbb-cccc-123456789aaa)_ | Returns a list of workspaces for the specified subscription (the parameter can be quoted or unquoted). |
|
||||
|
||||
Example variable queries:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Query | Description |
|
||||
| --------------------------------------------------------------------------------------- | --------------------------------------------------------- |
|
||||
| _subscriptions()_ | Returns a list of Azure subscriptions |
|
||||
| _workspaces()_ | Returns a list of workspaces for default subscription |
|
||||
| _workspaces("12345678-aaaa-bbbb-cccc-123456789aaa")_ | Returns a list of workspaces for a specified subscription |
|
||||
| _workspaces("$subscription")_ | With template variable for the subscription parameter |
|
||||
| _workspace("myWorkspace").Heartbeat \| distinct Computer_ | Returns a list of Virtual Machines |
|
||||
| _workspace("$workspace").Heartbeat \| distinct Computer_ | Returns a list of Virtual Machines with template variable |
|
||||
| _workspace("$workspace").Perf \| distinct ObjectName_ | Returns a list of objects from the Perf table |
|
||||
| _workspace("$workspace").Perf \| where ObjectName == "$object" \| distinct CounterName_ | Returns a list of metric names from the Perf table |
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Example of a time series query using variables:
|
||||
|
||||
```
|
||||
Perf
|
||||
| where ObjectName == "$object" and CounterName == "$metric"
|
||||
| where TimeGenerated >= $__timeFrom() and TimeGenerated <= $__timeTo()
|
||||
| where $__contains(Computer, $computer)
|
||||
| summarize avg(CounterValue) by bin(TimeGenerated, $__interval), Computer
|
||||
| order by TimeGenerated asc
|
||||
```
|
||||
|
||||
### Azure Log Analytics Alerting
|
||||
|
||||
Not implemented yet.
|
||||
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user