mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Cloudwatch: Break out resource requests from datasource file (#55358)
* break out resource requests from datasource file * fix lint issues
This commit is contained in:
parent
4df41972f1
commit
caba98590d
@ -56,7 +56,7 @@ exports[`no enzyme tests`] = {
|
||||
"public/app/features/dimensions/editors/ThresholdsEditor/ThresholdsEditor.test.tsx:145048794": [
|
||||
[0, 17, 13, "RegExp match", "2409514259"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx:3543762762": [
|
||||
"public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx:2210656642": [
|
||||
[1, 19, 13, "RegExp match", "2409514259"]
|
||||
]
|
||||
}`
|
||||
@ -5905,12 +5905,18 @@ exports[`better eslint`] = {
|
||||
"public/app/plugins/datasource/cloud-monitoring/types.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/__mocks__/LogsQueryRunner.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/__mocks__/monarch/Monaco.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/api.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "6"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
@ -5953,15 +5959,7 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/datasource.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/guards.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
@ -5985,9 +5983,6 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/metric-math/completion/CompletionItemProvider.test.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
|
@ -77,8 +77,8 @@ export function setupMockedDataSource({
|
||||
const datasource = new CloudWatchDatasource(CloudWatchSettings, templateService, timeSrv);
|
||||
datasource.getVariables = () => ['test'];
|
||||
|
||||
datasource.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
datasource.getRegions = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getRegions = jest.fn().mockResolvedValue([]);
|
||||
datasource.logsQueryRunner.defaultLogGroups = [];
|
||||
const fetchMock = jest.fn().mockReturnValue(of({}));
|
||||
setBackendSrv({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { DataFrame } from '@grafana/data';
|
||||
import { CustomVariableModel, DataFrame } from '@grafana/data';
|
||||
import { BackendDataSourceResponse, getBackendSrv, setBackendSrv } from '@grafana/runtime';
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
@ -16,7 +16,7 @@ export function setupMockedLogsQueryRunner({
|
||||
},
|
||||
variables,
|
||||
mockGetVariableName = true,
|
||||
}: { data?: BackendDataSourceResponse; variables?: any; mockGetVariableName?: boolean } = {}) {
|
||||
}: { data?: BackendDataSourceResponse; variables?: CustomVariableModel[]; mockGetVariableName?: boolean } = {}) {
|
||||
let templateService = new TemplateSrv();
|
||||
if (variables) {
|
||||
templateService = setupMockedTemplateService(variables);
|
||||
|
111
public/app/plugins/datasource/cloudwatch/api.ts
Normal file
111
public/app/plugins/datasource/cloudwatch/api.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import { DataSourceInstanceSettings } from '@grafana/data';
|
||||
import { getBackendSrv, BackendSrv } from '@grafana/runtime';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
|
||||
import { CloudWatchRequest } from './query-runner/CloudWatchRequest';
|
||||
import { CloudWatchJsonData, Dimensions } from './types';
|
||||
|
||||
export class CloudWatchAPI extends CloudWatchRequest {
|
||||
private backendSrv: BackendSrv;
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<CloudWatchJsonData>, templateSrv: TemplateSrv) {
|
||||
super(instanceSettings, templateSrv);
|
||||
this.backendSrv = getBackendSrv();
|
||||
}
|
||||
|
||||
resourceRequest(subtype: string, parameters?: any): Promise<Array<{ text: any; label: any; value: any }>> {
|
||||
return this.backendSrv.get(`/api/datasources/${this.instanceSettings.id}/resources/${subtype}`, parameters);
|
||||
}
|
||||
|
||||
getRegions(): Promise<Array<{ label: string; value: string; text: string }>> {
|
||||
return this.resourceRequest('regions').then((regions: any) => [
|
||||
{ label: 'default', value: 'default', text: 'default' },
|
||||
...regions,
|
||||
]);
|
||||
}
|
||||
|
||||
getNamespaces() {
|
||||
return this.resourceRequest('namespaces');
|
||||
}
|
||||
|
||||
async getMetrics(namespace: string | undefined, region?: string) {
|
||||
if (!namespace) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.resourceRequest('metrics', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
namespace: this.templateSrv.replace(namespace),
|
||||
});
|
||||
}
|
||||
|
||||
async getAllMetrics(region: string): Promise<Array<{ metricName: string; namespace: string }>> {
|
||||
const values = await this.resourceRequest('all-metrics', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
});
|
||||
|
||||
return values.map((v) => ({ metricName: v.value, namespace: v.text }));
|
||||
}
|
||||
|
||||
async getDimensionKeys(
|
||||
namespace: string | undefined,
|
||||
region: string,
|
||||
dimensionFilters: Dimensions = {},
|
||||
metricName = ''
|
||||
) {
|
||||
if (!namespace) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.resourceRequest('dimension-keys', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
namespace: this.templateSrv.replace(namespace),
|
||||
dimensionFilters: JSON.stringify(this.convertDimensionFormat(dimensionFilters, {})),
|
||||
metricName,
|
||||
});
|
||||
}
|
||||
|
||||
async getDimensionValues(
|
||||
region: string,
|
||||
namespace: string | undefined,
|
||||
metricName: string | undefined,
|
||||
dimensionKey: string,
|
||||
filterDimensions: {}
|
||||
) {
|
||||
if (!namespace || !metricName) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const values = await this.resourceRequest('dimension-values', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
namespace: this.templateSrv.replace(namespace),
|
||||
metricName: this.templateSrv.replace(metricName.trim()),
|
||||
dimensionKey: this.templateSrv.replace(dimensionKey),
|
||||
dimensions: JSON.stringify(this.convertDimensionFormat(filterDimensions, {})),
|
||||
});
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
getEbsVolumeIds(region: string, instanceId: string) {
|
||||
return this.resourceRequest('ebs-volume-ids', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
instanceId: this.templateSrv.replace(instanceId),
|
||||
});
|
||||
}
|
||||
|
||||
getEc2InstanceAttribute(region: string, attributeName: string, filters: any) {
|
||||
return this.resourceRequest('ec2-instance-attribute', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
attributeName: this.templateSrv.replace(attributeName),
|
||||
filters: JSON.stringify(this.convertMultiFilterFormat(filters, 'filter key')),
|
||||
});
|
||||
}
|
||||
|
||||
getResourceARNs(region: string, resourceType: string, tags: any) {
|
||||
return this.resourceRequest('resource-arns', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
resourceType: this.templateSrv.replace(resourceType),
|
||||
tags: JSON.stringify(this.convertMultiFilterFormat(tags, 'tag name')),
|
||||
});
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ import { uniq } from 'lodash';
|
||||
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import type { Monaco, monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { CloudWatchDatasource } from '../../datasource';
|
||||
import { CloudWatchAPI } from '../../api';
|
||||
import { CompletionItemProvider } from '../../monarch/CompletionItemProvider';
|
||||
import { LinkedToken } from '../../monarch/LinkedToken';
|
||||
import { TRIGGER_SUGGEST } from '../../monarch/commands';
|
||||
@ -34,9 +34,9 @@ type CompletionItem = monacoTypes.languages.CompletionItem;
|
||||
export class SQLCompletionItemProvider extends CompletionItemProvider {
|
||||
region: string;
|
||||
|
||||
constructor(datasource: CloudWatchDatasource, templateSrv: TemplateSrv = getTemplateSrv()) {
|
||||
super(datasource, templateSrv);
|
||||
this.region = datasource.getActualRegion();
|
||||
constructor(api: CloudWatchAPI, templateSrv: TemplateSrv = getTemplateSrv()) {
|
||||
super(api, templateSrv);
|
||||
this.region = api.getActualRegion() ?? '';
|
||||
this.getStatementPosition = getStatementPosition;
|
||||
this.getSuggestionKinds = getSuggestionKinds;
|
||||
this.tokenTypes = SQLTokenTypes;
|
||||
@ -112,14 +112,14 @@ export class SQLCompletionItemProvider extends CompletionItemProvider {
|
||||
const namespaceToken = getNamespaceToken(currentToken);
|
||||
if (namespaceToken?.value) {
|
||||
// if a namespace is specified, only suggest metrics for the namespace
|
||||
const metrics = await this.datasource.getMetrics(
|
||||
const metrics = await this.api.getMetrics(
|
||||
this.templateSrv.replace(namespaceToken?.value.replace(/\"/g, '')),
|
||||
this.templateSrv.replace(this.region)
|
||||
);
|
||||
metrics.map((m) => addSuggestion(m.value));
|
||||
} else {
|
||||
// If no namespace is specified in the query, just list all metrics
|
||||
const metrics = await this.datasource.getAllMetrics(this.templateSrv.replace(this.region));
|
||||
const metrics = await this.api.getAllMetrics(this.templateSrv.replace(this.region));
|
||||
uniq(metrics.map((m) => m.metricName)).map((m) => addSuggestion(m, { insertText: m }));
|
||||
}
|
||||
}
|
||||
@ -147,12 +147,12 @@ export class SQLCompletionItemProvider extends CompletionItemProvider {
|
||||
let namespaces = [];
|
||||
if (metricNameToken?.value) {
|
||||
// if a metric is specified, only suggest namespaces that actually have that metric
|
||||
const metrics = await this.datasource.getAllMetrics(this.region);
|
||||
const metrics = await this.api.getAllMetrics(this.region);
|
||||
const metricName = this.templateSrv.replace(metricNameToken.value);
|
||||
namespaces = metrics.filter((m) => m.metricName === metricName).map((m) => m.namespace);
|
||||
} else {
|
||||
// if no metric is specified, just suggest all namespaces
|
||||
const ns = await this.datasource.getNamespaces();
|
||||
const ns = await this.api.getNamespaces();
|
||||
namespaces = ns.map((n) => n.value);
|
||||
}
|
||||
namespaces.map((n) => addSuggestion(`"${n}"`, { insertText: `"${n}"` }));
|
||||
@ -179,7 +179,7 @@ export class SQLCompletionItemProvider extends CompletionItemProvider {
|
||||
dimensionFilter = (labelKeyTokens || []).reduce((acc, curr) => {
|
||||
return { ...acc, [curr.value]: null };
|
||||
}, {});
|
||||
const keys = await this.datasource.getDimensionKeys(
|
||||
const keys = await this.api.getDimensionKeys(
|
||||
this.templateSrv.replace(namespaceToken.value.replace(/\"/g, '')),
|
||||
this.templateSrv.replace(this.region),
|
||||
dimensionFilter,
|
||||
@ -199,7 +199,7 @@ export class SQLCompletionItemProvider extends CompletionItemProvider {
|
||||
const metricNameToken = getMetricNameToken(currentToken);
|
||||
const labelKey = currentToken?.getPreviousNonWhiteSpaceToken()?.getPreviousNonWhiteSpaceToken();
|
||||
if (namespaceToken?.value && labelKey?.value && metricNameToken?.value) {
|
||||
const values = await this.datasource.getDimensionValues(
|
||||
const values = await this.api.getDimensionValues(
|
||||
this.templateSrv.replace(this.region),
|
||||
this.templateSrv.replace(namespaceToken.value.replace(/\"/g, '')),
|
||||
this.templateSrv.replace(metricNameToken.value),
|
||||
@ -266,12 +266,12 @@ export class SQLCompletionItemProvider extends CompletionItemProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// always suggest template variables
|
||||
this.templateVariables.map((v) => {
|
||||
addSuggestion(v, {
|
||||
this.templateSrv.getVariables().map((v) => {
|
||||
const variable = `$${v.name}`;
|
||||
addSuggestion(variable, {
|
||||
range,
|
||||
label: v,
|
||||
insertText: v,
|
||||
label: variable,
|
||||
insertText: variable,
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
sortText: CompletionItemPriority.Low,
|
||||
});
|
||||
|
@ -29,10 +29,10 @@ const q: CloudWatchQuery = {
|
||||
alarmNamePrefix: '',
|
||||
};
|
||||
|
||||
ds.datasource.getRegions = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getRegions = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getVariables = jest.fn().mockReturnValue([]);
|
||||
|
||||
const props: QueryEditorProps<CloudWatchDatasource, CloudWatchQuery, CloudWatchJsonData> = {
|
||||
@ -51,7 +51,7 @@ describe('AnnotationQueryEditor', () => {
|
||||
});
|
||||
|
||||
it('should return an error component in case CloudWatchQuery is not CloudWatchAnnotationQuery', async () => {
|
||||
ds.datasource.getDimensionValues = jest.fn().mockResolvedValue([[{ label: 'dimVal1', value: 'dimVal1' }]]);
|
||||
ds.datasource.api.getDimensionValues = jest.fn().mockResolvedValue([[{ label: 'dimVal1', value: 'dimVal1' }]]);
|
||||
render(
|
||||
<AnnotationQueryEditor {...props} query={{ ...props.query, queryMode: 'Metrics' } as CloudWatchMetricsQuery} />
|
||||
);
|
||||
@ -59,7 +59,7 @@ describe('AnnotationQueryEditor', () => {
|
||||
});
|
||||
|
||||
it('should not display wildcard option in dimension value dropdown', async () => {
|
||||
ds.datasource.getDimensionValues = jest.fn().mockResolvedValue([[{ label: 'dimVal1', value: 'dimVal1' }]]);
|
||||
ds.datasource.api.getDimensionValues = jest.fn().mockResolvedValue([[{ label: 'dimVal1', value: 'dimVal1' }]]);
|
||||
(props.query as CloudWatchAnnotationQuery).dimensions = { instanceId: 'instance-123' };
|
||||
render(<AnnotationQueryEditor {...props} />);
|
||||
const valueElement = screen.getByText('instance-123');
|
||||
|
@ -52,7 +52,7 @@ export default class CloudWatchLink extends Component<Props, State> {
|
||||
source: query.logGroupNames ?? [],
|
||||
};
|
||||
|
||||
return encodeUrl(urlProps, datasource.getActualRegion(query.region));
|
||||
return encodeUrl(urlProps, datasource.api.getActualRegion(query.region));
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -12,12 +12,14 @@ import { ConfigEditor, Props } from './ConfigEditor';
|
||||
jest.mock('app/features/plugins/datasource_srv', () => ({
|
||||
getDatasourceSrv: () => ({
|
||||
loadDatasource: jest.fn().mockResolvedValue({
|
||||
getRegions: jest.fn().mockResolvedValue([
|
||||
{
|
||||
label: 'ap-east-1',
|
||||
value: 'ap-east-1',
|
||||
},
|
||||
]),
|
||||
api: {
|
||||
getRegions: jest.fn().mockResolvedValue([
|
||||
{
|
||||
label: 'ap-east-1',
|
||||
value: 'ap-east-1',
|
||||
},
|
||||
]),
|
||||
},
|
||||
getActualRegion: jest.fn().mockReturnValue('ap-east-1'),
|
||||
getVariables: jest.fn().mockReturnValue([]),
|
||||
logsQueryRunner: {
|
||||
|
@ -63,7 +63,7 @@ export const ConfigEditor: FC<Props> = (props: Props) => {
|
||||
{...props}
|
||||
loadRegions={
|
||||
datasource &&
|
||||
(() => datasource!.getRegions().then((r) => r.filter((r) => r.value !== 'default').map((v) => v.value)))
|
||||
(() => datasource.api.getRegions().then((r) => r.filter((r) => r.value !== 'default').map((v) => v.value)))
|
||||
}
|
||||
>
|
||||
<InlineField label="Namespaces of Custom Metrics" labelWidth={28} tooltip="Namespaces of Custom Metrics.">
|
||||
|
@ -10,9 +10,9 @@ const ds = setupMockedDataSource({
|
||||
variables: [],
|
||||
});
|
||||
|
||||
ds.datasource.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getVariables = jest.fn().mockReturnValue([]);
|
||||
const q: CloudWatchMetricsQuery = {
|
||||
id: '',
|
||||
|
@ -50,7 +50,7 @@ export const FilterItem: FunctionComponent<Props> = ({
|
||||
return [];
|
||||
}
|
||||
|
||||
return datasource
|
||||
return datasource.api
|
||||
.getDimensionValues(region, namespace, metricName, filter.key, dimensionsExcludingCurrentKey)
|
||||
.then((result: Array<SelectableValue<string>>) => {
|
||||
if (result.length && !disableExpressions) {
|
||||
|
@ -98,7 +98,7 @@ export const LogGroupSelector: React.FC<LogGroupSelectorProps> = ({
|
||||
}
|
||||
|
||||
setLoadingLogGroups(true);
|
||||
return fetchLogGroupOptions(datasource.getActualRegion(region))
|
||||
return fetchLogGroupOptions(datasource.getActualRegion(region) ?? '')
|
||||
.then((logGroups) => {
|
||||
const newSelectedLogGroups = intersection(
|
||||
selectedLogGroups,
|
||||
|
@ -11,9 +11,9 @@ const ds = setupMockedDataSource({
|
||||
variables: [],
|
||||
});
|
||||
|
||||
ds.datasource.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.getVariables = jest.fn().mockReturnValue([]);
|
||||
const metricStat: MetricStat = {
|
||||
region: 'us-east-2',
|
||||
@ -121,8 +121,8 @@ describe('MetricStatEditor', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
propsNamespaceMetrics.datasource.getNamespaces = jest.fn().mockResolvedValue(namespaces);
|
||||
propsNamespaceMetrics.datasource.getMetrics = jest.fn().mockResolvedValue(metrics);
|
||||
propsNamespaceMetrics.datasource.api.getNamespaces = jest.fn().mockResolvedValue(namespaces);
|
||||
propsNamespaceMetrics.datasource.api.getMetrics = jest.fn().mockResolvedValue(metrics);
|
||||
onChange.mockClear();
|
||||
onRunQuery.mockClear();
|
||||
});
|
||||
@ -148,7 +148,7 @@ describe('MetricStatEditor', () => {
|
||||
});
|
||||
|
||||
it('should remove metricName from metricStat if it does not exist in new namespace', async () => {
|
||||
propsNamespaceMetrics.datasource.getMetrics = jest
|
||||
propsNamespaceMetrics.datasource.api.getMetrics = jest
|
||||
.fn()
|
||||
.mockImplementation((namespace: string, region: string) => {
|
||||
let mockMetrics =
|
||||
|
@ -6,6 +6,7 @@ import { EditorField, EditorFieldGroup, EditorRow, EditorRows, EditorSwitch, Sel
|
||||
import { Dimensions } from '..';
|
||||
import { CloudWatchDatasource } from '../../datasource';
|
||||
import { useDimensionKeys, useMetrics, useNamespaces } from '../../hooks';
|
||||
import { standardStatistics } from '../../standardStatistics';
|
||||
import { MetricStat } from '../../types';
|
||||
import { appendTemplateVariables, toOption } from '../../utils/utils';
|
||||
|
||||
@ -46,7 +47,7 @@ export function MetricStatEditor({
|
||||
if (!metricName) {
|
||||
return metricStat;
|
||||
}
|
||||
await datasource.getMetrics(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
await datasource.api.getMetrics(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
if (!result.find((metric) => metric.value === metricName)) {
|
||||
metricName = '';
|
||||
}
|
||||
@ -89,15 +90,15 @@ export function MetricStatEditor({
|
||||
<Select
|
||||
inputId={`${refId}-metric-stat-editor-select-statistic`}
|
||||
allowCustomValue
|
||||
value={toOption(metricStat.statistic ?? datasource.standardStatistics[0])}
|
||||
value={toOption(metricStat.statistic ?? standardStatistics[0])}
|
||||
options={appendTemplateVariables(
|
||||
datasource,
|
||||
datasource.standardStatistics.filter((s) => s !== metricStat.statistic).map(toOption)
|
||||
standardStatistics.filter((s) => s !== metricStat.statistic).map(toOption)
|
||||
)}
|
||||
onChange={({ value: statistic }) => {
|
||||
if (
|
||||
!statistic ||
|
||||
(!datasource.standardStatistics.includes(statistic) &&
|
||||
(!standardStatistics.includes(statistic) &&
|
||||
!/^p\d{2}(?:\.\d{1,2})?$/.test(statistic) &&
|
||||
!statistic.startsWith('$'))
|
||||
) {
|
||||
|
@ -46,10 +46,10 @@ const setup = () => {
|
||||
|
||||
const datasource = new CloudWatchDatasource(instanceSettings, templateSrv as any, {} as any);
|
||||
datasource.metricFindQuery = async () => [{ value: 'test', label: 'test', text: 'test' }];
|
||||
datasource.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
datasource.getRegions = jest.fn().mockResolvedValue([]);
|
||||
datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getRegions = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
|
||||
const props: Props = {
|
||||
query: {
|
||||
@ -150,7 +150,7 @@ describe('QueryEditor', () => {
|
||||
if (props.query.queryMode !== 'Metrics') {
|
||||
fail(`expected props.query.queryMode to be 'Metrics', got '${props.query.queryMode}' instead`);
|
||||
}
|
||||
props.datasource.getDimensionValues = jest.fn().mockResolvedValue([[{ label: 'dimVal1', value: 'dimVal1' }]]);
|
||||
props.datasource.api.getDimensionValues = jest.fn().mockResolvedValue([[{ label: 'dimVal1', value: 'dimVal1' }]]);
|
||||
props.query.metricQueryType = MetricQueryType.Search;
|
||||
props.query.metricEditorMode = MetricEditorMode.Builder;
|
||||
props.query.dimensions = { instanceId: 'instance-123' };
|
||||
|
@ -10,7 +10,7 @@ import MetricsQueryHeader from './MetricsQueryHeader';
|
||||
const ds = setupMockedDataSource({
|
||||
variables: [],
|
||||
});
|
||||
ds.datasource.getRegions = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getRegions = jest.fn().mockResolvedValue([]);
|
||||
const query: CloudWatchMetricsQuery = {
|
||||
id: '',
|
||||
region: 'us-east-2',
|
||||
|
@ -9,7 +9,7 @@ import QueryHeader from './QueryHeader';
|
||||
const ds = setupMockedDataSource({
|
||||
variables: [],
|
||||
});
|
||||
ds.datasource.getRegions = jest.fn().mockResolvedValue([]);
|
||||
ds.datasource.api.getRegions = jest.fn().mockResolvedValue([]);
|
||||
|
||||
describe('QueryHeader', () => {
|
||||
it('should display metric options for metrics', async () => {
|
||||
|
@ -22,10 +22,10 @@ const makeSQLQuery = (sql?: SQLExpression): CloudWatchMetricsQuery => ({
|
||||
|
||||
describe('Cloudwatch SQLBuilderEditor', () => {
|
||||
beforeEach(() => {
|
||||
datasource.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
datasource.getDimensionValues = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getNamespaces = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getDimensionValues = jest.fn().mockResolvedValue([]);
|
||||
});
|
||||
|
||||
const baseProps = {
|
||||
@ -47,7 +47,7 @@ describe('Cloudwatch SQLBuilderEditor', () => {
|
||||
});
|
||||
|
||||
render(<SQLBuilderEditor {...baseProps} query={query} />);
|
||||
await waitFor(() => expect(datasource.getNamespaces).toHaveBeenCalled());
|
||||
await waitFor(() => expect(datasource.api.getNamespaces).toHaveBeenCalled());
|
||||
|
||||
expect(screen.getByText('AWS/EC2')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('With schema')).not.toBeChecked();
|
||||
@ -68,7 +68,7 @@ describe('Cloudwatch SQLBuilderEditor', () => {
|
||||
});
|
||||
|
||||
render(<SQLBuilderEditor {...baseProps} query={query} />);
|
||||
await waitFor(() => expect(datasource.getNamespaces).toHaveBeenCalled());
|
||||
await waitFor(() => expect(datasource.api.getNamespaces).toHaveBeenCalled());
|
||||
|
||||
expect(screen.getByText('AWS/EC2')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('With schema')).toBeChecked();
|
||||
@ -95,7 +95,12 @@ describe('Cloudwatch SQLBuilderEditor', () => {
|
||||
|
||||
render(<SQLBuilderEditor {...baseProps} query={query} />);
|
||||
await waitFor(() =>
|
||||
expect(datasource.getDimensionKeys).toHaveBeenCalledWith('AWS/EC2', query.region, { InstanceId: null }, undefined)
|
||||
expect(datasource.api.getDimensionKeys).toHaveBeenCalledWith(
|
||||
'AWS/EC2',
|
||||
query.region,
|
||||
{ InstanceId: null },
|
||||
undefined
|
||||
)
|
||||
);
|
||||
expect(screen.getByText('AWS/EC2')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('With schema')).toBeChecked();
|
||||
@ -117,7 +122,7 @@ describe('Cloudwatch SQLBuilderEditor', () => {
|
||||
});
|
||||
|
||||
render(<SQLBuilderEditor {...baseProps} query={query} />);
|
||||
await waitFor(() => expect(datasource.getNamespaces).toHaveBeenCalled());
|
||||
await waitFor(() => expect(datasource.api.getNamespaces).toHaveBeenCalled());
|
||||
|
||||
expect(screen.getByText('AVERAGE')).toBeInTheDocument();
|
||||
expect(screen.getByText('CPUUtilization')).toBeInTheDocument();
|
||||
@ -133,7 +138,7 @@ describe('Cloudwatch SQLBuilderEditor', () => {
|
||||
});
|
||||
|
||||
render(<SQLBuilderEditor {...baseProps} query={query} />);
|
||||
await waitFor(() => expect(datasource.getNamespaces).toHaveBeenCalled());
|
||||
await waitFor(() => expect(datasource.api.getNamespaces).toHaveBeenCalled());
|
||||
|
||||
expect(screen.getByText('AVG')).toBeInTheDocument();
|
||||
const directionElement = screen.getByLabelText('Direction');
|
||||
@ -145,7 +150,7 @@ describe('Cloudwatch SQLBuilderEditor', () => {
|
||||
const query = makeSQLQuery({});
|
||||
|
||||
render(<SQLBuilderEditor {...baseProps} query={query} />);
|
||||
await waitFor(() => expect(datasource.getNamespaces).toHaveBeenCalled());
|
||||
await waitFor(() => expect(datasource.api.getNamespaces).toHaveBeenCalled());
|
||||
|
||||
expect(screen.queryByText('AVG')).toBeNull();
|
||||
const directionElement = screen.getByLabelText('Direction');
|
||||
|
@ -60,15 +60,15 @@ const metrics = [
|
||||
|
||||
describe('Cloudwatch SQLBuilderSelectRow', () => {
|
||||
beforeEach(() => {
|
||||
datasource.getNamespaces = jest.fn().mockResolvedValue(namespaces);
|
||||
datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
datasource.getDimensionValues = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getNamespaces = jest.fn().mockResolvedValue(namespaces);
|
||||
datasource.api.getMetrics = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||
datasource.api.getDimensionValues = jest.fn().mockResolvedValue([]);
|
||||
onQueryChange.mockReset();
|
||||
});
|
||||
|
||||
it('Should not reset metricName when selecting a namespace if metric exist in new namespace', async () => {
|
||||
datasource.getMetrics = jest.fn().mockResolvedValue(metrics);
|
||||
datasource.api.getMetrics = jest.fn().mockResolvedValue(metrics);
|
||||
|
||||
await act(async () => {
|
||||
render(<SQLBuilderSelectRow {...baseProps} />);
|
||||
@ -103,7 +103,7 @@ describe('Cloudwatch SQLBuilderSelectRow', () => {
|
||||
});
|
||||
|
||||
it('Should reset metricName when selecting a namespace if metric does not exist in new namespace', async () => {
|
||||
datasource.getMetrics = jest.fn().mockImplementation((namespace: string, region: string) => {
|
||||
datasource.api.getMetrics = jest.fn().mockImplementation((namespace: string, region: string) => {
|
||||
let mockMetrics =
|
||||
namespace === 'n1' && region === baseProps.query.region
|
||||
? metrics
|
||||
|
@ -62,7 +62,7 @@ const SQLBuilderSelectRow: React.FC<SQLBuilderSelectRowProps> = ({ datasource, q
|
||||
|
||||
const validateMetricName = async (query: CloudWatchMetricsQuery) => {
|
||||
let { region, sql } = query;
|
||||
await datasource.getMetrics(query.namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
await datasource.api.getMetrics(query.namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
if (!result.some((metric) => metric.value === metricName)) {
|
||||
sql = removeMetricName(query).sql;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ const FilterItem: React.FC<FilterItemProps> = (props) => {
|
||||
return [];
|
||||
}
|
||||
|
||||
return datasource
|
||||
return datasource.api
|
||||
.getDimensionValues(query.region, namespace, metricName, filter.property.name, {})
|
||||
.then((result: Array<SelectableValue<string>>) => {
|
||||
return appendTemplateVariables(datasource, result);
|
||||
|
@ -22,22 +22,22 @@ const defaultQuery = {
|
||||
|
||||
const ds = setupMockedDataSource();
|
||||
|
||||
ds.datasource.getRegions = jest.fn().mockResolvedValue([
|
||||
ds.datasource.api.getRegions = jest.fn().mockResolvedValue([
|
||||
{ label: 'a1', value: 'a1' },
|
||||
{ label: 'b1', value: 'b1' },
|
||||
{ label: 'c1', value: 'c1' },
|
||||
]);
|
||||
ds.datasource.getNamespaces = jest.fn().mockResolvedValue([
|
||||
ds.datasource.api.getNamespaces = jest.fn().mockResolvedValue([
|
||||
{ label: 'x2', value: 'x2' },
|
||||
{ label: 'y2', value: 'y2' },
|
||||
{ label: 'z2', value: 'z2' },
|
||||
]);
|
||||
ds.datasource.getMetrics = jest.fn().mockResolvedValue([
|
||||
ds.datasource.api.getMetrics = jest.fn().mockResolvedValue([
|
||||
{ label: 'h3', value: 'h3' },
|
||||
{ label: 'i3', value: 'i3' },
|
||||
{ label: 'j3', value: 'j3' },
|
||||
]);
|
||||
ds.datasource.getDimensionKeys = jest
|
||||
ds.datasource.api.getDimensionKeys = jest
|
||||
.fn()
|
||||
.mockImplementation((_namespace: string, region: string, dimensionFilters?: Dimensions) => {
|
||||
if (!!dimensionFilters) {
|
||||
@ -55,12 +55,12 @@ ds.datasource.getDimensionKeys = jest
|
||||
}
|
||||
return Promise.resolve([{ label: 't4', value: 't4' }]);
|
||||
});
|
||||
ds.datasource.getDimensionValues = jest.fn().mockResolvedValue([
|
||||
ds.datasource.api.getDimensionValues = jest.fn().mockResolvedValue([
|
||||
{ label: 'foo', value: 'foo' },
|
||||
{ label: 'bar', value: 'bar' },
|
||||
]);
|
||||
ds.datasource.getVariables = jest.fn().mockReturnValue([]);
|
||||
ds.datasource.getEc2InstanceAttribute = jest.fn().mockReturnValue([]);
|
||||
ds.datasource.api.getEc2InstanceAttribute = jest.fn().mockReturnValue([]);
|
||||
|
||||
const onChange = jest.fn();
|
||||
const defaultProps: Props = {
|
||||
@ -141,7 +141,7 @@ describe('VariableEditor', () => {
|
||||
await select(keySelect, 'v4', {
|
||||
container: document.body,
|
||||
});
|
||||
expect(ds.datasource.getDimensionKeys).toHaveBeenCalledWith('z2', 'a1', {}, '');
|
||||
expect(ds.datasource.api.getDimensionKeys).toHaveBeenCalledWith('z2', 'a1', {}, '');
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
...defaultQuery,
|
||||
queryType: VariableQueryType.DimensionValues,
|
||||
@ -224,8 +224,8 @@ describe('VariableEditor', () => {
|
||||
container: document.body,
|
||||
});
|
||||
|
||||
expect(ds.datasource.getMetrics).toHaveBeenCalledWith('z2', 'b1');
|
||||
expect(ds.datasource.getDimensionKeys).toHaveBeenCalledWith('z2', 'b1');
|
||||
expect(ds.datasource.api.getMetrics).toHaveBeenCalledWith('z2', 'b1');
|
||||
expect(ds.datasource.api.getDimensionKeys).toHaveBeenCalledWith('z2', 'b1');
|
||||
expect(props.onChange).toHaveBeenCalledWith({
|
||||
...defaultQuery,
|
||||
refId: 'CloudWatchVariableQueryEditor-VariableQuery',
|
||||
|
@ -65,14 +65,14 @@ export const VariableQueryEditor = ({ query, datasource, onChange }: Props) => {
|
||||
const sanitizeQuery = async (query: VariableQuery) => {
|
||||
let { metricName, dimensionKey, dimensionFilters, namespace, region } = query;
|
||||
if (metricName) {
|
||||
await datasource.getMetrics(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
await datasource.api.getMetrics(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
if (!result.find((metric) => metric.value === metricName)) {
|
||||
metricName = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
if (dimensionKey) {
|
||||
await datasource.getDimensionKeys(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
await datasource.api.getDimensionKeys(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
if (!result.find((key) => key.value === dimensionKey)) {
|
||||
dimensionKey = '';
|
||||
dimensionFilters = {};
|
||||
|
@ -204,7 +204,7 @@ describe('datasource', () => {
|
||||
describe('resource requests', () => {
|
||||
it('should map resource response to metric response', async () => {
|
||||
const datasource = setupMockedDataSource().datasource;
|
||||
datasource.doMetricResourceRequest = jest.fn().mockResolvedValue([
|
||||
datasource.api.resourceRequest = jest.fn().mockResolvedValue([
|
||||
{
|
||||
text: 'AWS/EC2',
|
||||
value: 'CPUUtilization',
|
||||
@ -214,7 +214,7 @@ describe('datasource', () => {
|
||||
value: 'CPUPercentage',
|
||||
},
|
||||
]);
|
||||
const allMetrics = await datasource.getAllMetrics('us-east-2');
|
||||
const allMetrics = await datasource.api.getAllMetrics('us-east-2');
|
||||
expect(allMetrics[0].metricName).toEqual('CPUUtilization');
|
||||
expect(allMetrics[0].namespace).toEqual('AWS/EC2');
|
||||
expect(allMetrics[1].metricName).toEqual('CPUPercentage');
|
||||
|
@ -18,6 +18,7 @@ import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_sr
|
||||
import { RowContextOptions } from '../../../features/logs/components/LogRowContextProvider';
|
||||
|
||||
import { CloudWatchAnnotationSupport } from './annotationSupport';
|
||||
import { CloudWatchAPI } from './api';
|
||||
import { SQLCompletionItemProvider } from './cloudwatch-sql/completion/CompletionItemProvider';
|
||||
import { isCloudWatchAnnotationQuery, isCloudWatchLogsQuery, isCloudWatchMetricsQuery } from './guards';
|
||||
import { CloudWatchLanguageProvider } from './language_provider';
|
||||
@ -31,7 +32,6 @@ import {
|
||||
CloudWatchLogsQuery,
|
||||
CloudWatchMetricsQuery,
|
||||
CloudWatchQuery,
|
||||
Dimensions,
|
||||
} from './types';
|
||||
import { CloudWatchVariableSupport } from './variables';
|
||||
|
||||
@ -39,18 +39,18 @@ export class CloudWatchDatasource
|
||||
extends DataSourceWithBackend<CloudWatchQuery, CloudWatchJsonData>
|
||||
implements DataSourceWithLogsContextSupport<CloudWatchLogsQuery>
|
||||
{
|
||||
defaultRegion: any;
|
||||
defaultRegion?: string;
|
||||
languageProvider: CloudWatchLanguageProvider;
|
||||
sqlCompletionItemProvider: SQLCompletionItemProvider;
|
||||
metricMathCompletionItemProvider: MetricMathCompletionItemProvider;
|
||||
|
||||
type = 'cloudwatch';
|
||||
standardStatistics = ['Average', 'Maximum', 'Minimum', 'Sum', 'SampleCount'];
|
||||
|
||||
private metricsQueryRunner: CloudWatchMetricsQueryRunner;
|
||||
private annotationQueryRunner: CloudWatchAnnotationQueryRunner;
|
||||
// this member should be private too, but we need to fix https://github.com/grafana/grafana/issues/55243 to enable that
|
||||
logsQueryRunner: CloudWatchLogsQueryRunner;
|
||||
api: CloudWatchAPI;
|
||||
|
||||
constructor(
|
||||
instanceSettings: DataSourceInstanceSettings<CloudWatchJsonData>,
|
||||
@ -59,18 +59,17 @@ export class CloudWatchDatasource
|
||||
) {
|
||||
super(instanceSettings);
|
||||
this.defaultRegion = instanceSettings.jsonData.defaultRegion;
|
||||
this.api = new CloudWatchAPI(instanceSettings, templateSrv);
|
||||
this.languageProvider = new CloudWatchLanguageProvider(this);
|
||||
this.sqlCompletionItemProvider = new SQLCompletionItemProvider(this, this.templateSrv);
|
||||
this.metricMathCompletionItemProvider = new MetricMathCompletionItemProvider(this, this.templateSrv);
|
||||
this.variables = new CloudWatchVariableSupport(this);
|
||||
this.annotations = CloudWatchAnnotationSupport;
|
||||
this.sqlCompletionItemProvider = new SQLCompletionItemProvider(this.api, this.templateSrv);
|
||||
this.metricMathCompletionItemProvider = new MetricMathCompletionItemProvider(this.api, this.templateSrv);
|
||||
this.metricsQueryRunner = new CloudWatchMetricsQueryRunner(instanceSettings, templateSrv);
|
||||
this.logsQueryRunner = new CloudWatchLogsQueryRunner(instanceSettings, templateSrv, timeSrv);
|
||||
this.annotationQueryRunner = new CloudWatchAnnotationQueryRunner(instanceSettings, templateSrv);
|
||||
this.variables = new CloudWatchVariableSupport(this.api, this.logsQueryRunner);
|
||||
this.annotations = CloudWatchAnnotationSupport;
|
||||
}
|
||||
|
||||
// datasource api
|
||||
|
||||
filterQuery(query: CloudWatchQuery) {
|
||||
return query.hide !== true || (isCloudWatchMetricsQuery(query) && query.id !== '');
|
||||
}
|
||||
@ -79,18 +78,31 @@ export class CloudWatchDatasource
|
||||
options = cloneDeep(options);
|
||||
|
||||
let queries = options.targets.filter(this.filterQuery);
|
||||
const { logQueries, metricsQueries, annotationQueries } = getTargetsByQueryMode(queries);
|
||||
|
||||
const logQueries: CloudWatchLogsQuery[] = [];
|
||||
const metricsQueries: CloudWatchMetricsQuery[] = [];
|
||||
const annotationQueries: CloudWatchAnnotationQuery[] = [];
|
||||
|
||||
queries.forEach((query) => {
|
||||
if (isCloudWatchAnnotationQuery(query)) {
|
||||
annotationQueries.push(query);
|
||||
} else if (isCloudWatchLogsQuery(query)) {
|
||||
logQueries.push(query);
|
||||
} else {
|
||||
metricsQueries.push(query);
|
||||
}
|
||||
});
|
||||
|
||||
const dataQueryResponses: Array<Observable<DataQueryResponse>> = [];
|
||||
if (logQueries.length > 0) {
|
||||
if (logQueries.length) {
|
||||
dataQueryResponses.push(this.logsQueryRunner.handleLogQueries(logQueries, options));
|
||||
}
|
||||
|
||||
if (metricsQueries.length > 0) {
|
||||
if (metricsQueries.length) {
|
||||
dataQueryResponses.push(this.metricsQueryRunner.handleMetricQueries(metricsQueries, options));
|
||||
}
|
||||
|
||||
if (annotationQueries.length > 0) {
|
||||
if (annotationQueries.length) {
|
||||
dataQueryResponses.push(this.annotationQueryRunner.handleAnnotationQuery(annotationQueries, options));
|
||||
}
|
||||
// No valid targets, return the empty result to save a round trip.
|
||||
@ -111,8 +123,9 @@ export class CloudWatchDatasource
|
||||
|
||||
return queries.map((query) => ({
|
||||
...query,
|
||||
region: this.getActualRegion(
|
||||
this.metricsQueryRunner.replaceVariableAndDisplayWarningIfMulti(query.region, scopedVars)
|
||||
region: this.metricsQueryRunner.replaceVariableAndDisplayWarningIfMulti(
|
||||
this.getActualRegion(query.region),
|
||||
scopedVars
|
||||
),
|
||||
...(isCloudWatchMetricsQuery(query) &&
|
||||
this.metricsQueryRunner.interpolateMetricsQueryVariables(query, scopedVars)),
|
||||
@ -155,134 +168,10 @@ export class CloudWatchDatasource
|
||||
return this.templateSrv.getVariables().map((v) => `$${v.name}`);
|
||||
}
|
||||
|
||||
getDefaultRegion() {
|
||||
return this.defaultRegion;
|
||||
}
|
||||
|
||||
getActualRegion(region?: string) {
|
||||
if (region === 'default' || region === undefined || region === '') {
|
||||
return this.getDefaultRegion();
|
||||
return this.defaultRegion;
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
doMetricResourceRequest(subtype: string, parameters?: any): Promise<Array<{ text: any; label: any; value: any }>> {
|
||||
return this.getResource(subtype, parameters);
|
||||
}
|
||||
|
||||
// resource requests
|
||||
getRegions(): Promise<Array<{ label: string; value: string; text: string }>> {
|
||||
return this.doMetricResourceRequest('regions').then((regions: any) => [
|
||||
{ label: 'default', value: 'default', text: 'default' },
|
||||
...regions,
|
||||
]);
|
||||
}
|
||||
|
||||
getNamespaces() {
|
||||
return this.doMetricResourceRequest('namespaces');
|
||||
}
|
||||
|
||||
async getMetrics(namespace: string | undefined, region?: string) {
|
||||
if (!namespace) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.doMetricResourceRequest('metrics', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
namespace: this.templateSrv.replace(namespace),
|
||||
});
|
||||
}
|
||||
|
||||
async getAllMetrics(region: string): Promise<Array<{ metricName: string; namespace: string }>> {
|
||||
const values = await this.doMetricResourceRequest('all-metrics', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
});
|
||||
|
||||
return values.map((v) => ({ metricName: v.value, namespace: v.text }));
|
||||
}
|
||||
|
||||
async getDimensionKeys(
|
||||
namespace: string | undefined,
|
||||
region: string,
|
||||
dimensionFilters: Dimensions = {},
|
||||
metricName = ''
|
||||
) {
|
||||
if (!namespace) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.doMetricResourceRequest('dimension-keys', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
namespace: this.templateSrv.replace(namespace),
|
||||
dimensionFilters: JSON.stringify(this.metricsQueryRunner.convertDimensionFormat(dimensionFilters, {})),
|
||||
metricName,
|
||||
});
|
||||
}
|
||||
|
||||
async getDimensionValues(
|
||||
region: string,
|
||||
namespace: string | undefined,
|
||||
metricName: string | undefined,
|
||||
dimensionKey: string,
|
||||
filterDimensions: {}
|
||||
) {
|
||||
if (!namespace || !metricName) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const values = await this.doMetricResourceRequest('dimension-values', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
namespace: this.templateSrv.replace(namespace),
|
||||
metricName: this.templateSrv.replace(metricName.trim()),
|
||||
dimensionKey: this.templateSrv.replace(dimensionKey),
|
||||
dimensions: JSON.stringify(this.metricsQueryRunner.convertDimensionFormat(filterDimensions, {})),
|
||||
});
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
getEbsVolumeIds(region: string, instanceId: string) {
|
||||
return this.doMetricResourceRequest('ebs-volume-ids', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
instanceId: this.templateSrv.replace(instanceId),
|
||||
});
|
||||
}
|
||||
|
||||
getEc2InstanceAttribute(region: string, attributeName: string, filters: any) {
|
||||
return this.doMetricResourceRequest('ec2-instance-attribute', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
attributeName: this.templateSrv.replace(attributeName),
|
||||
filters: JSON.stringify(this.metricsQueryRunner.convertMultiFilterFormat(filters, 'filter key')),
|
||||
});
|
||||
}
|
||||
|
||||
getResourceARNs(region: string, resourceType: string, tags: any) {
|
||||
return this.doMetricResourceRequest('resource-arns', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
resourceType: this.templateSrv.replace(resourceType),
|
||||
tags: JSON.stringify(this.metricsQueryRunner.convertMultiFilterFormat(tags, 'tag name')),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getTargetsByQueryMode(targets: CloudWatchQuery[]) {
|
||||
const logQueries: CloudWatchLogsQuery[] = [];
|
||||
const metricsQueries: CloudWatchMetricsQuery[] = [];
|
||||
const annotationQueries: CloudWatchAnnotationQuery[] = [];
|
||||
|
||||
targets.forEach((query) => {
|
||||
if (isCloudWatchAnnotationQuery(query)) {
|
||||
annotationQueries.push(query);
|
||||
} else if (isCloudWatchLogsQuery(query)) {
|
||||
logQueries.push(query);
|
||||
} else {
|
||||
metricsQueries.push(query);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
logQueries,
|
||||
metricsQueries,
|
||||
annotationQueries,
|
||||
};
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export const useRegions = (datasource: CloudWatchDatasource): [Array<SelectableV
|
||||
options: datasource.getVariables().map(toOption),
|
||||
};
|
||||
|
||||
datasource
|
||||
datasource.api
|
||||
.getRegions()
|
||||
.then((regions: Array<SelectableValue<string>>) => setRegions([...regions, variableOptionGroup]))
|
||||
.finally(() => setRegionsIsLoading(false));
|
||||
@ -31,7 +31,7 @@ export const useRegions = (datasource: CloudWatchDatasource): [Array<SelectableV
|
||||
export const useNamespaces = (datasource: CloudWatchDatasource) => {
|
||||
const [namespaces, setNamespaces] = useState<Array<SelectableValue<string>>>([]);
|
||||
useEffect(() => {
|
||||
datasource.getNamespaces().then((namespaces) => {
|
||||
datasource.api.getNamespaces().then((namespaces) => {
|
||||
setNamespaces(appendTemplateVariables(datasource, namespaces));
|
||||
});
|
||||
}, [datasource]);
|
||||
@ -42,7 +42,7 @@ export const useNamespaces = (datasource: CloudWatchDatasource) => {
|
||||
export const useMetrics = (datasource: CloudWatchDatasource, region: string, namespace: string | undefined) => {
|
||||
const [metrics, setMetrics] = useState<Array<SelectableValue<string>>>([]);
|
||||
useEffect(() => {
|
||||
datasource.getMetrics(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
datasource.api.getMetrics(namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||
setMetrics(appendTemplateVariables(datasource, result));
|
||||
});
|
||||
}, [datasource, region, namespace]);
|
||||
@ -61,7 +61,7 @@ export const useDimensionKeys = (
|
||||
|
||||
// doing deep comparison to avoid making new api calls to list metrics unless dimension filter object props changes
|
||||
useDeepCompareEffect(() => {
|
||||
datasource
|
||||
datasource.api
|
||||
.getDimensionKeys(namespace, region, dimensionFilter, metricName)
|
||||
.then((result: Array<SelectableValue<string>>) => {
|
||||
setDimensionKeys(appendTemplateVariables(datasource, result));
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
import { Monaco, monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { setupMockedTemplateService } from '../../__mocks__/CloudWatchDataSource';
|
||||
import * as MetricMathTestData from '../../__mocks__/metric-math-test-data';
|
||||
import MonacoMock from '../../__mocks__/monarch/Monaco';
|
||||
import TextModel from '../../__mocks__/monarch/TextModel';
|
||||
import { CloudWatchDatasource } from '../../datasource';
|
||||
import { CloudWatchAPI } from '../../api';
|
||||
import cloudWatchMetricMathLanguageDefinition from '../definition';
|
||||
import {
|
||||
METRIC_MATH_FNS,
|
||||
@ -19,10 +19,9 @@ import { MetricMathCompletionItemProvider } from './CompletionItemProvider';
|
||||
const getSuggestions = async (value: string, position: monacoTypes.IPosition) => {
|
||||
const setup = new MetricMathCompletionItemProvider(
|
||||
{
|
||||
getVariables: () => [],
|
||||
getActualRegion: () => 'us-east-2',
|
||||
} as any as CloudWatchDatasource,
|
||||
getTemplateSrv()
|
||||
} as CloudWatchAPI,
|
||||
setupMockedTemplateService([])
|
||||
);
|
||||
const monaco = MonacoMock as Monaco;
|
||||
const provider = setup.getCompletionProvider(monaco, cloudWatchMetricMathLanguageDefinition);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import type { Monaco, monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { CloudWatchDatasource } from '../../datasource';
|
||||
import { CloudWatchAPI } from '../../api';
|
||||
import { CompletionItemProvider } from '../../monarch/CompletionItemProvider';
|
||||
import { LinkedToken } from '../../monarch/LinkedToken';
|
||||
import { TRIGGER_SUGGEST } from '../../monarch/commands';
|
||||
@ -21,8 +21,8 @@ import { MetricMathTokenTypes } from './types';
|
||||
type CompletionItem = monacoTypes.languages.CompletionItem;
|
||||
|
||||
export class MetricMathCompletionItemProvider extends CompletionItemProvider {
|
||||
constructor(datasource: CloudWatchDatasource, templateSrv: TemplateSrv = getTemplateSrv()) {
|
||||
super(datasource, templateSrv);
|
||||
constructor(api: CloudWatchAPI, templateSrv: TemplateSrv = getTemplateSrv()) {
|
||||
super(api, templateSrv);
|
||||
this.getStatementPosition = getStatementPosition;
|
||||
this.getSuggestionKinds = getSuggestionKinds;
|
||||
this.tokenTypes = MetricMathTokenTypes;
|
||||
@ -110,11 +110,12 @@ export class MetricMathCompletionItemProvider extends CompletionItemProvider {
|
||||
}
|
||||
|
||||
// always suggest template variables
|
||||
this.templateVariables.map((v) => {
|
||||
addSuggestion(v, {
|
||||
this.templateSrv.getVariables().map((v) => {
|
||||
const variable = `$${v.name}`;
|
||||
addSuggestion(variable, {
|
||||
range,
|
||||
label: v,
|
||||
insertText: v,
|
||||
label: variable,
|
||||
insertText: variable,
|
||||
kind: monaco.languages.CompletionItemKind.Variable,
|
||||
sortText: CompletionItemPriority.Low,
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import type { Monaco, monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { CloudWatchDatasource } from '../datasource';
|
||||
import { CloudWatchAPI } from '../api';
|
||||
|
||||
import { LinkedToken } from './LinkedToken';
|
||||
import { linkedTokenBuilder } from './linkedTokenBuilder';
|
||||
@ -18,15 +18,13 @@ CompletionItemProvider is an extendable class which needs to implement :
|
||||
- getSuggestions
|
||||
*/
|
||||
export class CompletionItemProvider implements Completeable {
|
||||
templateVariables: string[];
|
||||
datasource: CloudWatchDatasource;
|
||||
api: CloudWatchAPI;
|
||||
templateSrv: TemplateSrv;
|
||||
tokenTypes: TokenTypes;
|
||||
|
||||
constructor(datasource: CloudWatchDatasource, templateSrv: TemplateSrv = getTemplateSrv()) {
|
||||
this.datasource = datasource;
|
||||
constructor(api: CloudWatchAPI, templateSrv: TemplateSrv = getTemplateSrv()) {
|
||||
this.api = api;
|
||||
this.templateSrv = templateSrv;
|
||||
this.templateVariables = this.datasource.getVariables();
|
||||
this.templateSrv = templateSrv;
|
||||
|
||||
// implement with more specific tokens when extending this class
|
||||
|
@ -6,10 +6,10 @@ import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
|
||||
import { CloudWatchAnnotationQuery, CloudWatchJsonData, CloudWatchQuery } from '../types';
|
||||
|
||||
import { CloudWatchQueryRunner } from './CloudWatchQueryRunner';
|
||||
import { CloudWatchRequest } from './CloudWatchRequest';
|
||||
|
||||
// This class handles execution of CloudWatch annotation queries
|
||||
export class CloudWatchAnnotationQueryRunner extends CloudWatchQueryRunner {
|
||||
export class CloudWatchAnnotationQueryRunner extends CloudWatchRequest {
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<CloudWatchJsonData>, templateSrv: TemplateSrv) {
|
||||
super(instanceSettings, templateSrv);
|
||||
}
|
||||
|
@ -51,13 +51,13 @@ import { addDataLinksToLogsResponse } from '../utils/datalinks';
|
||||
import { runWithRetry } from '../utils/logsRetry';
|
||||
import { increasingInterval } from '../utils/rxjs/increasingInterval';
|
||||
|
||||
import { CloudWatchQueryRunner } from './CloudWatchQueryRunner';
|
||||
import { CloudWatchRequest } from './CloudWatchRequest';
|
||||
|
||||
export const LOG_IDENTIFIER_INTERNAL = '__log__grafana_internal__';
|
||||
export const LOGSTREAM_IDENTIFIER_INTERNAL = '__logstream__grafana_internal__';
|
||||
|
||||
// This class handles execution of CloudWatch logs query data queries
|
||||
export class CloudWatchLogsQueryRunner extends CloudWatchQueryRunner {
|
||||
export class CloudWatchLogsQueryRunner extends CloudWatchRequest {
|
||||
logsTimeout: string;
|
||||
defaultLogGroups: string[];
|
||||
logQueries: Record<string, { id: string; region: string; statsQuery: boolean }> = {};
|
||||
|
@ -34,7 +34,7 @@ import {
|
||||
MetricRequest,
|
||||
} from '../types';
|
||||
|
||||
import { CloudWatchQueryRunner } from './CloudWatchQueryRunner';
|
||||
import { CloudWatchRequest } from './CloudWatchRequest';
|
||||
|
||||
const displayAlert = (datasourceName: string, region: string) =>
|
||||
store.dispatch(
|
||||
@ -47,9 +47,8 @@ const displayAlert = (datasourceName: string, region: string) =>
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// This class handles execution of CloudWatch metrics query data queries
|
||||
export class CloudWatchMetricsQueryRunner extends CloudWatchQueryRunner {
|
||||
export class CloudWatchMetricsQueryRunner extends CloudWatchRequest {
|
||||
debouncedAlert: (datasourceName: string, region: string) => void = memoizedDebounce(
|
||||
displayAlert,
|
||||
AppNotificationTimeout.Error
|
||||
|
@ -11,7 +11,7 @@ import { AppNotificationTimeout } from 'app/types';
|
||||
import memoizedDebounce from '../memoizedDebounce';
|
||||
import { CloudWatchJsonData, Dimensions, MetricRequest, MultiFilters, TSDBResponse } from '../types';
|
||||
|
||||
export abstract class CloudWatchQueryRunner {
|
||||
export abstract class CloudWatchRequest {
|
||||
templateSrv: TemplateSrv;
|
||||
ref: DataSourceRef;
|
||||
dsQueryEndpoint = '/api/ds/query';
|
@ -0,0 +1 @@
|
||||
export const standardStatistics = ['Average', 'Maximum', 'Minimum', 'Sum', 'SampleCount'];
|
@ -14,18 +14,18 @@ const defaultQuery: VariableQuery = {
|
||||
refId: '',
|
||||
};
|
||||
|
||||
const ds = setupMockedDataSource({ variables: [labelsVariable, dimensionVariable] });
|
||||
ds.datasource.getRegions = jest.fn().mockResolvedValue([{ label: 'a', value: 'a' }]);
|
||||
ds.datasource.getNamespaces = jest.fn().mockResolvedValue([{ label: 'b', value: 'b' }]);
|
||||
ds.datasource.getMetrics = jest.fn().mockResolvedValue([{ label: 'c', value: 'c' }]);
|
||||
ds.datasource.getDimensionKeys = jest.fn().mockResolvedValue([{ label: 'd', value: 'd' }]);
|
||||
ds.datasource.logsQueryRunner.describeAllLogGroups = jest.fn().mockResolvedValue(['a', 'b']);
|
||||
const mock = setupMockedDataSource({ variables: [labelsVariable, dimensionVariable] });
|
||||
mock.datasource.api.getRegions = jest.fn().mockResolvedValue([{ label: 'a', value: 'a' }]);
|
||||
mock.datasource.api.getNamespaces = jest.fn().mockResolvedValue([{ label: 'b', value: 'b' }]);
|
||||
mock.datasource.api.getMetrics = jest.fn().mockResolvedValue([{ label: 'c', value: 'c' }]);
|
||||
mock.datasource.api.getDimensionKeys = jest.fn().mockResolvedValue([{ label: 'd', value: 'd' }]);
|
||||
mock.datasource.logsQueryRunner.describeAllLogGroups = jest.fn().mockResolvedValue(['a', 'b']);
|
||||
const getDimensionValues = jest.fn().mockResolvedValue([{ label: 'e', value: 'e' }]);
|
||||
const getEbsVolumeIds = jest.fn().mockResolvedValue([{ label: 'f', value: 'f' }]);
|
||||
const getEc2InstanceAttribute = jest.fn().mockResolvedValue([{ label: 'g', value: 'g' }]);
|
||||
const getResourceARNs = jest.fn().mockResolvedValue([{ label: 'h', value: 'h' }]);
|
||||
|
||||
const variables = new CloudWatchVariableSupport(ds.datasource);
|
||||
const variables = new CloudWatchVariableSupport(mock.datasource.api, mock.datasource.logsQueryRunner);
|
||||
|
||||
describe('variables', () => {
|
||||
it('should run regions', async () => {
|
||||
@ -57,7 +57,7 @@ describe('variables', () => {
|
||||
dimensionFilters: { a: 'b' },
|
||||
};
|
||||
beforeEach(() => {
|
||||
ds.datasource.getDimensionValues = getDimensionValues;
|
||||
mock.datasource.api.getDimensionValues = getDimensionValues;
|
||||
getDimensionValues.mockClear();
|
||||
});
|
||||
|
||||
@ -87,7 +87,7 @@ describe('variables', () => {
|
||||
|
||||
describe('EBS volume ids', () => {
|
||||
beforeEach(() => {
|
||||
ds.datasource.getEbsVolumeIds = getEbsVolumeIds;
|
||||
mock.datasource.api.getEbsVolumeIds = getEbsVolumeIds;
|
||||
getEbsVolumeIds.mockClear();
|
||||
});
|
||||
|
||||
@ -116,7 +116,7 @@ describe('variables', () => {
|
||||
ec2Filters: { a: ['b'] },
|
||||
};
|
||||
beforeEach(() => {
|
||||
ds.datasource.getEc2InstanceAttribute = getEc2InstanceAttribute;
|
||||
mock.datasource.api.getEc2InstanceAttribute = getEc2InstanceAttribute;
|
||||
getEc2InstanceAttribute.mockClear();
|
||||
});
|
||||
|
||||
@ -141,7 +141,7 @@ describe('variables', () => {
|
||||
tags: { a: ['b'] },
|
||||
};
|
||||
beforeEach(() => {
|
||||
ds.datasource.getResourceARNs = getResourceARNs;
|
||||
mock.datasource.api.getResourceARNs = getResourceARNs;
|
||||
getResourceARNs.mockClear();
|
||||
});
|
||||
|
||||
|
@ -3,17 +3,17 @@ import { map } from 'rxjs/operators';
|
||||
|
||||
import { CustomVariableSupport, DataQueryRequest, DataQueryResponse } from '@grafana/data';
|
||||
|
||||
import { CloudWatchAPI } from './api';
|
||||
import { VariableQueryEditor } from './components/VariableQueryEditor/VariableQueryEditor';
|
||||
import { CloudWatchDatasource } from './datasource';
|
||||
import { migrateVariableQuery } from './migrations/variableQueryMigrations';
|
||||
import { CloudWatchLogsQueryRunner } from './query-runner/CloudWatchLogsQueryRunner';
|
||||
import { standardStatistics } from './standardStatistics';
|
||||
import { VariableQuery, VariableQueryType } from './types';
|
||||
|
||||
export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchDatasource, VariableQuery> {
|
||||
private readonly datasource: CloudWatchDatasource;
|
||||
|
||||
constructor(datasource: CloudWatchDatasource) {
|
||||
constructor(private readonly api: CloudWatchAPI, private readonly logsQueryRunner: CloudWatchLogsQueryRunner) {
|
||||
super();
|
||||
this.datasource = datasource;
|
||||
this.query = this.query.bind(this);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
}
|
||||
|
||||
async handleLogGroupsQuery({ region, logGroupPrefix }: VariableQuery) {
|
||||
const logGroups = await this.datasource.logsQueryRunner.describeAllLogGroups({
|
||||
const logGroups: string[] = await this.logsQueryRunner.describeAllLogGroups({
|
||||
region,
|
||||
logGroupNamePrefix: logGroupPrefix,
|
||||
});
|
||||
@ -67,7 +67,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
}
|
||||
|
||||
async handleRegionsQuery() {
|
||||
const regions = await this.datasource.getRegions();
|
||||
const regions = await this.api.getRegions();
|
||||
return regions.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -76,7 +76,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
}
|
||||
|
||||
async handleNamespacesQuery() {
|
||||
const namespaces = await this.datasource.getNamespaces();
|
||||
const namespaces = await this.api.getNamespaces();
|
||||
return namespaces.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -85,7 +85,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
}
|
||||
|
||||
async handleMetricsQuery({ namespace, region }: VariableQuery) {
|
||||
const metrics = await this.datasource.getMetrics(namespace, region);
|
||||
const metrics = await this.api.getMetrics(namespace, region);
|
||||
return metrics.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -94,7 +94,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
}
|
||||
|
||||
async handleDimensionKeysQuery({ namespace, region }: VariableQuery) {
|
||||
const keys = await this.datasource.getDimensionKeys(namespace, region);
|
||||
const keys = await this.api.getDimensionKeys(namespace, region);
|
||||
return keys.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -106,13 +106,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
if (!dimensionKey || !metricName) {
|
||||
return [];
|
||||
}
|
||||
const keys = await this.datasource.getDimensionValues(
|
||||
region,
|
||||
namespace,
|
||||
metricName,
|
||||
dimensionKey,
|
||||
dimensionFilters ?? {}
|
||||
);
|
||||
const keys = await this.api.getDimensionValues(region, namespace, metricName, dimensionKey, dimensionFilters ?? {});
|
||||
return keys.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -124,7 +118,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
if (!instanceID) {
|
||||
return [];
|
||||
}
|
||||
const ids = await this.datasource.getEbsVolumeIds(region, instanceID);
|
||||
const ids = await this.api.getEbsVolumeIds(region, instanceID);
|
||||
return ids.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -136,7 +130,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
if (!attributeName) {
|
||||
return [];
|
||||
}
|
||||
const values = await this.datasource.getEc2InstanceAttribute(region, attributeName, ec2Filters ?? {});
|
||||
const values = await this.api.getEc2InstanceAttribute(region, attributeName, ec2Filters ?? {});
|
||||
return values.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -148,7 +142,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
if (!resourceType) {
|
||||
return [];
|
||||
}
|
||||
const keys = await this.datasource.getResourceARNs(region, resourceType, tags ?? {});
|
||||
const keys = await this.api.getResourceARNs(region, resourceType, tags ?? {});
|
||||
return keys.map((s: { label: string; value: string }) => ({
|
||||
text: s.label,
|
||||
value: s.value,
|
||||
@ -157,7 +151,7 @@ export class CloudWatchVariableSupport extends CustomVariableSupport<CloudWatchD
|
||||
}
|
||||
|
||||
async handleStatisticsQuery() {
|
||||
return this.datasource.standardStatistics.map((s: string) => ({
|
||||
return standardStatistics.map((s: string) => ({
|
||||
text: s,
|
||||
value: s,
|
||||
expandable: true,
|
||||
|
Loading…
Reference in New Issue
Block a user