mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Cloudwatch: Add back support for old Log Group picker (#73524)
Cloudwatch: Add back support for old Log Group picker behind feature toggle. Fixes issue for aws gov cloud users
This commit is contained in:
parent
62821c69b3
commit
34a831c83e
@ -8,10 +8,12 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
@ -282,3 +284,38 @@ func (e *cloudWatchExecutor) resourceGroupsGetResources(ctx context.Context, plu
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// legacy route, will be removed once GovCloud supports Cross Account Observability
|
||||
func (e *cloudWatchExecutor) handleGetLogGroups(ctx context.Context, pluginCtx backend.PluginContext, parameters url.Values) ([]suggestData, error) {
|
||||
region := parameters.Get("region")
|
||||
limit := parameters.Get("limit")
|
||||
logGroupNamePrefix := parameters.Get("logGroupNamePrefix")
|
||||
|
||||
logsClient, err := e.getCWLogsClient(ctx, pluginCtx, region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logGroupLimit := defaultLogGroupLimit
|
||||
intLimit, err := strconv.ParseInt(limit, 10, 64)
|
||||
if err == nil && intLimit > 0 {
|
||||
logGroupLimit = intLimit
|
||||
}
|
||||
|
||||
input := &cloudwatchlogs.DescribeLogGroupsInput{Limit: aws.Int64(logGroupLimit)}
|
||||
if len(logGroupNamePrefix) > 0 {
|
||||
input.LogGroupNamePrefix = aws.String(logGroupNamePrefix)
|
||||
}
|
||||
var response *cloudwatchlogs.DescribeLogGroupsOutput
|
||||
response, err = logsClient.DescribeLogGroups(input)
|
||||
if err != nil || response == nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]suggestData, 0)
|
||||
for _, logGroup := range response.LogGroups {
|
||||
logGroupName := *logGroup.LogGroupName
|
||||
result = append(result, suggestData{Text: logGroupName, Value: logGroupName, Label: logGroupName})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ func (e *cloudWatchExecutor) newResourceMux() *http.ServeMux {
|
||||
mux.HandleFunc("/log-group-fields", routes.ResourceRequestMiddleware(routes.LogGroupFieldsHandler, logger, e.getRequestContext))
|
||||
mux.HandleFunc("/external-id", routes.ResourceRequestMiddleware(routes.ExternalIdHandler, logger, e.getRequestContext))
|
||||
|
||||
// remove this once AWS's Cross Account Observability is supported in GovCloud
|
||||
mux.HandleFunc("/legacy-log-groups", handleResourceReq(e.handleGetLogGroups))
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,9 @@ jest.mock('@grafana/runtime', () => ({
|
||||
config: {
|
||||
...jest.requireActual('@grafana/runtime').config,
|
||||
awsAssumeRoleEnabled: true,
|
||||
featureToggles: {
|
||||
cloudWatchCrossAccountQuerying: true,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
@ -166,7 +169,7 @@ describe('Render', () => {
|
||||
|
||||
it('should display log group selector field', async () => {
|
||||
setup();
|
||||
await waitFor(async () => expect(await screen.getByText('Select log groups')).toBeInTheDocument());
|
||||
await waitFor(async () => expect(screen.getByText('Select log groups')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('should only display the first two default log groups and show all of them when clicking "Show all" button', async () => {
|
||||
@ -204,9 +207,7 @@ describe('Render', () => {
|
||||
});
|
||||
|
||||
it('should show error message if Select log group button is clicked when data source is never saved', async () => {
|
||||
const SAVED_VERSION = undefined;
|
||||
setup({ version: SAVED_VERSION });
|
||||
|
||||
setup({ version: 1 });
|
||||
await waitFor(() => expect(screen.getByText('Select log groups')).toBeInTheDocument());
|
||||
await userEvent.click(screen.getByText('Select log groups'));
|
||||
await waitFor(() =>
|
||||
@ -265,12 +266,11 @@ describe('Render', () => {
|
||||
});
|
||||
|
||||
it('should open log group selector if Select log group button is clicked when data source has saved changes', async () => {
|
||||
const SAVED_VERSION = undefined;
|
||||
const newProps = {
|
||||
...props,
|
||||
options: {
|
||||
...props.options,
|
||||
version: SAVED_VERSION,
|
||||
version: 1,
|
||||
},
|
||||
};
|
||||
const meta: PluginMeta = {
|
||||
@ -291,7 +291,7 @@ describe('Render', () => {
|
||||
...newProps,
|
||||
options: {
|
||||
...newProps.options,
|
||||
version: 1,
|
||||
version: 2,
|
||||
},
|
||||
};
|
||||
rerender(
|
||||
|
@ -21,7 +21,7 @@ import { store } from 'app/store/store';
|
||||
import { CloudWatchDatasource } from '../../datasource';
|
||||
import { SelectableResourceValue } from '../../resources/types';
|
||||
import { CloudWatchJsonData, CloudWatchSecureJsonData } from '../../types';
|
||||
import { LogGroupsField } from '../shared/LogGroups/LogGroupsField';
|
||||
import { LogGroupsFieldWrapper } from '../shared/LogGroups/LogGroupsField';
|
||||
|
||||
import { XrayLinkConfig } from './XrayLinkConfig';
|
||||
|
||||
@ -124,39 +124,47 @@ export const ConfigEditor = (props: Props) => {
|
||||
shrink={true}
|
||||
{...logGroupFieldState}
|
||||
>
|
||||
<LogGroupsField
|
||||
region={defaultRegion ?? ''}
|
||||
datasource={datasource}
|
||||
onBeforeOpen={() => {
|
||||
if (saved) {
|
||||
return;
|
||||
}
|
||||
{datasource ? (
|
||||
<LogGroupsFieldWrapper
|
||||
region={defaultRegion ?? ''}
|
||||
datasource={datasource}
|
||||
onBeforeOpen={() => {
|
||||
if (saved) {
|
||||
return;
|
||||
}
|
||||
|
||||
let error = 'You need to save the data source before adding log groups.';
|
||||
if (props.options.version && props.options.version > 1) {
|
||||
error =
|
||||
'You have unsaved connection detail changes. You need to save the data source before adding log groups.';
|
||||
}
|
||||
setLogGroupFieldState({
|
||||
invalid: true,
|
||||
error,
|
||||
});
|
||||
throw new Error(error);
|
||||
}}
|
||||
legacyLogGroupNames={defaultLogGroups}
|
||||
logGroups={logGroups}
|
||||
onChange={(updatedLogGroups) => {
|
||||
onOptionsChange({
|
||||
...props.options,
|
||||
jsonData: {
|
||||
...props.options.jsonData,
|
||||
logGroups: updatedLogGroups,
|
||||
defaultLogGroups: undefined,
|
||||
},
|
||||
});
|
||||
}}
|
||||
maxNoOfVisibleLogGroups={2}
|
||||
/>
|
||||
let error = 'You need to save the data source before adding log groups.';
|
||||
if (props.options.version && props.options.version > 1) {
|
||||
error =
|
||||
'You have unsaved connection detail changes. You need to save the data source before adding log groups.';
|
||||
}
|
||||
setLogGroupFieldState({
|
||||
invalid: true,
|
||||
error,
|
||||
});
|
||||
throw new Error(error);
|
||||
}}
|
||||
legacyLogGroupNames={defaultLogGroups}
|
||||
logGroups={logGroups}
|
||||
onChange={(updatedLogGroups) => {
|
||||
onOptionsChange({
|
||||
...props.options,
|
||||
jsonData: {
|
||||
...props.options.jsonData,
|
||||
logGroups: updatedLogGroups,
|
||||
defaultLogGroups: undefined,
|
||||
},
|
||||
});
|
||||
}}
|
||||
maxNoOfVisibleLogGroups={2}
|
||||
//legacy props
|
||||
legacyOnChange={(logGroups) => {
|
||||
updateDatasourcePluginJsonDataOption(props, 'defaultLogGroups', logGroups);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</InlineField>
|
||||
</div>
|
||||
<XrayLinkConfig
|
||||
@ -242,7 +250,7 @@ function useDataSourceSavedState(props: Props) {
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
props.options.version && setSaved(true);
|
||||
props.options.version && props.options.version > 1 && setSaved(true);
|
||||
}, [props.options.version]);
|
||||
|
||||
return saved;
|
||||
|
@ -10,7 +10,7 @@ import { TRIGGER_SUGGEST } from '../../../language/monarch/commands';
|
||||
import { registerLanguage } from '../../../language/monarch/register';
|
||||
import { CloudWatchJsonData, CloudWatchLogsQuery, CloudWatchQuery } from '../../../types';
|
||||
import { getStatsGroups } from '../../../utils/query/getStatsGroups';
|
||||
import { LogGroupsField } from '../../shared/LogGroups/LogGroupsField';
|
||||
import { LogGroupsFieldWrapper } from '../../shared/LogGroups/LogGroupsField';
|
||||
|
||||
export interface CloudWatchLogsQueryFieldProps
|
||||
extends QueryEditorProps<CloudWatchDatasource, CloudWatchQuery, CloudWatchJsonData>,
|
||||
@ -47,7 +47,7 @@ export const CloudWatchLogsQueryFieldMonaco = (props: CloudWatchLogsQueryFieldPr
|
||||
|
||||
return (
|
||||
<>
|
||||
<LogGroupsField
|
||||
<LogGroupsFieldWrapper
|
||||
region={query.region}
|
||||
datasource={datasource}
|
||||
legacyLogGroupNames={query.logGroupNames}
|
||||
@ -55,6 +55,10 @@ export const CloudWatchLogsQueryFieldMonaco = (props: CloudWatchLogsQueryFieldPr
|
||||
onChange={(logGroups) => {
|
||||
onChange({ ...query, logGroups, logGroupNames: undefined });
|
||||
}}
|
||||
//legacy props
|
||||
legacyOnChange={(logGroupNames) => {
|
||||
onChange({ ...query, logGroupNames });
|
||||
}}
|
||||
/>
|
||||
<div className="gf-form-inline gf-form-inline--nowrap flex-grow-1">
|
||||
<div className="gf-form--grow flex-shrink-1">
|
||||
|
@ -18,9 +18,9 @@ import {
|
||||
// dom also includes Element polyfills
|
||||
import { CloudWatchDatasource } from '../../../datasource';
|
||||
import syntax from '../../../language/cloudwatch-logs/syntax';
|
||||
import { CloudWatchJsonData, CloudWatchLogsQuery, CloudWatchQuery } from '../../../types';
|
||||
import { CloudWatchJsonData, CloudWatchLogsQuery, CloudWatchQuery, LogGroup } from '../../../types';
|
||||
import { getStatsGroups } from '../../../utils/query/getStatsGroups';
|
||||
import { LogGroupsField } from '../../shared/LogGroups/LogGroupsField';
|
||||
import { LogGroupsFieldWrapper } from '../../shared/LogGroups/LogGroupsField';
|
||||
|
||||
export interface CloudWatchLogsQueryFieldProps
|
||||
extends QueryEditorProps<CloudWatchDatasource, CloudWatchQuery, CloudWatchJsonData>,
|
||||
@ -81,14 +81,18 @@ export const CloudWatchLogsQueryField = (props: CloudWatchLogsQueryFieldProps) =
|
||||
|
||||
return (
|
||||
<>
|
||||
<LogGroupsField
|
||||
<LogGroupsFieldWrapper
|
||||
region={query.region}
|
||||
datasource={datasource}
|
||||
legacyLogGroupNames={query.logGroupNames}
|
||||
logGroups={query.logGroups}
|
||||
onChange={(logGroups) => {
|
||||
onChange={(logGroups: LogGroup[]) => {
|
||||
onChange({ ...query, logGroups, logGroupNames: undefined });
|
||||
}}
|
||||
//legacy props can be removed once we remove support for Legacy Log Group Selector
|
||||
legacyOnChange={(logGroups: string[]) => {
|
||||
onChange({ ...query, logGroupNames: logGroups });
|
||||
}}
|
||||
/>
|
||||
<div className="gf-form-inline gf-form-inline--nowrap flex-grow-1">
|
||||
<div className="gf-form gf-form--grow flex-shrink-1">
|
||||
|
@ -45,6 +45,16 @@ jest.mock('./MetricsQueryEditor/SQLCodeEditor', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
config: {
|
||||
...jest.requireActual('@grafana/runtime').config,
|
||||
featureToggles: {
|
||||
cloudWatchCrossAccountQuerying: true,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export { SQLCodeEditor } from './MetricsQueryEditor/SQLCodeEditor';
|
||||
|
||||
describe('QueryEditor should render right editor', () => {
|
||||
|
@ -0,0 +1,30 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
|
||||
import { CloudWatchDatasource } from '../../../datasource';
|
||||
|
||||
import { LogGroupSelector } from './LegacyLogGroupSelector';
|
||||
|
||||
type Props = {
|
||||
datasource: CloudWatchDatasource;
|
||||
onChange: (logGroups: string[]) => void;
|
||||
region: string;
|
||||
legacyLogGroupNames: string[];
|
||||
};
|
||||
|
||||
const rowGap = css`
|
||||
gap: 3px;
|
||||
`;
|
||||
|
||||
export const LegacyLogGroupSelection = ({ datasource, region, legacyLogGroupNames, onChange }: Props) => {
|
||||
return (
|
||||
<div className={`gf-form gf-form--grow flex-grow-1 ${rowGap}`}>
|
||||
<LogGroupSelector
|
||||
region={region}
|
||||
selectedLogGroups={legacyLogGroupNames}
|
||||
datasource={datasource}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,144 @@
|
||||
import { debounce, unionBy } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { SelectableValue, toOption } from '@grafana/data';
|
||||
import { MultiSelect } from '@grafana/ui';
|
||||
import { InputActionMeta } from '@grafana/ui/src/components/Select/types';
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||
import { dispatch } from 'app/store/store';
|
||||
|
||||
import { CloudWatchDatasource } from '../../../datasource';
|
||||
import { appendTemplateVariables } from '../../../utils/utils';
|
||||
|
||||
const MAX_LOG_GROUPS = 20;
|
||||
const MAX_VISIBLE_LOG_GROUPS = 4;
|
||||
const DEBOUNCE_TIMER = 300;
|
||||
|
||||
export interface LogGroupSelectorProps {
|
||||
region: string;
|
||||
selectedLogGroups: string[];
|
||||
onChange: (logGroups: string[]) => void;
|
||||
|
||||
datasource?: CloudWatchDatasource;
|
||||
onOpenMenu?: () => Promise<void>;
|
||||
width?: number | 'auto';
|
||||
saved?: boolean; // is only used in the config editor
|
||||
}
|
||||
|
||||
export const LogGroupSelector: React.FC<LogGroupSelectorProps> = ({
|
||||
region,
|
||||
selectedLogGroups,
|
||||
onChange,
|
||||
datasource,
|
||||
onOpenMenu,
|
||||
width,
|
||||
saved = true,
|
||||
}) => {
|
||||
const [loadingLogGroups, setLoadingLogGroups] = useState(false);
|
||||
const [availableLogGroups, setAvailableLogGroups] = useState<Array<SelectableValue<string>>>([]);
|
||||
const logGroupOptions = useMemo(
|
||||
() => unionBy(availableLogGroups, selectedLogGroups?.map(toOption), 'value'),
|
||||
[availableLogGroups, selectedLogGroups]
|
||||
);
|
||||
|
||||
const fetchLogGroupOptions = useCallback(
|
||||
async (region: string, logGroupNamePrefix?: string) => {
|
||||
if (!datasource) {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const logGroups = await datasource.resources.legacyDescribeLogGroups(region, logGroupNamePrefix);
|
||||
return logGroups;
|
||||
} catch (err) {
|
||||
dispatch(notifyApp(createErrorNotification(typeof err === 'string' ? err : JSON.stringify(err))));
|
||||
return [];
|
||||
}
|
||||
},
|
||||
[datasource]
|
||||
);
|
||||
|
||||
const onLogGroupSearch = async (searchTerm: string, region: string, actionMeta: InputActionMeta) => {
|
||||
if (actionMeta.action !== 'input-change' || !datasource) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to fetch matching log groups if the search term isn't valid
|
||||
// This is also useful for preventing searches when a user is typing out a log group with template vars
|
||||
// See https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_LogGroup.html for the source of the pattern below
|
||||
const logGroupNamePattern = /^[\.\-_/#A-Za-z0-9]+$/;
|
||||
if (!logGroupNamePattern.test(searchTerm)) {
|
||||
if (searchTerm !== '') {
|
||||
dispatch(notifyApp(createErrorNotification('Invalid Log Group name: ' + searchTerm)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setLoadingLogGroups(true);
|
||||
const matchingLogGroups = await fetchLogGroupOptions(region, searchTerm);
|
||||
setAvailableLogGroups(unionBy(availableLogGroups, matchingLogGroups, 'value'));
|
||||
setLoadingLogGroups(false);
|
||||
};
|
||||
|
||||
// Reset the log group options if the datasource or region change and are saved
|
||||
useEffect(() => {
|
||||
async function getAvailableLogGroupOptions() {
|
||||
// Don't call describeLogGroups if datasource or region is undefined
|
||||
if (!datasource || !datasource.getActualRegion(region)) {
|
||||
setAvailableLogGroups([]);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoadingLogGroups(true);
|
||||
return fetchLogGroupOptions(datasource.getActualRegion(region))
|
||||
.then((logGroups) => {
|
||||
setAvailableLogGroups(logGroups);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoadingLogGroups(false);
|
||||
});
|
||||
}
|
||||
|
||||
// Config editor does not fetch new log group options unless changes have been saved
|
||||
saved && getAvailableLogGroupOptions();
|
||||
|
||||
// if component unmounts in the middle of setting state, we reset state and unsubscribe from fetchLogGroupOptions
|
||||
return () => {
|
||||
setAvailableLogGroups([]);
|
||||
setLoadingLogGroups(false);
|
||||
};
|
||||
// this hook shouldn't get called every time selectedLogGroups or onChange updates
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [datasource, region, saved]);
|
||||
|
||||
const onOpenLogGroupMenu = async () => {
|
||||
if (onOpenMenu) {
|
||||
await onOpenMenu();
|
||||
}
|
||||
};
|
||||
|
||||
const onLogGroupSearchDebounced = debounce(onLogGroupSearch, DEBOUNCE_TIMER);
|
||||
|
||||
return (
|
||||
<MultiSelect
|
||||
inputId="default-log-groups"
|
||||
aria-label="Log Groups"
|
||||
allowCustomValue
|
||||
options={datasource ? appendTemplateVariables(datasource, logGroupOptions) : logGroupOptions}
|
||||
value={selectedLogGroups}
|
||||
onChange={(v) => onChange(v.filter(({ value }) => value).map(({ value }) => value))}
|
||||
closeMenuOnSelect={false}
|
||||
isClearable
|
||||
isOptionDisabled={() => selectedLogGroups.length >= MAX_LOG_GROUPS}
|
||||
placeholder="Choose Log Groups"
|
||||
maxVisibleValues={MAX_VISIBLE_LOG_GROUPS}
|
||||
noOptionsMessage="No log groups available"
|
||||
isLoading={loadingLogGroups}
|
||||
onOpenMenu={onOpenLogGroupMenu}
|
||||
onInputChange={(value, actionMeta) => {
|
||||
onLogGroupSearchDebounced(value, region, actionMeta);
|
||||
}}
|
||||
width={width}
|
||||
/>
|
||||
);
|
||||
};
|
@ -1,17 +1,20 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import { CloudWatchDatasource } from '../../../datasource';
|
||||
import { useAccountOptions } from '../../../hooks';
|
||||
import { DescribeLogGroupsRequest } from '../../../resources/types';
|
||||
import { LogGroup } from '../../../types';
|
||||
import { isTemplateVariable } from '../../../utils/templateVariableUtils';
|
||||
|
||||
import { LegacyLogGroupSelection } from './LegacyLogGroupNamesSelection';
|
||||
import { LogGroupsSelector } from './LogGroupsSelector';
|
||||
import { SelectedLogGroups } from './SelectedLogGroups';
|
||||
|
||||
type Props = {
|
||||
datasource?: CloudWatchDatasource;
|
||||
datasource: CloudWatchDatasource;
|
||||
onChange: (logGroups: LogGroup[]) => void;
|
||||
legacyLogGroupNames?: string[];
|
||||
logGroups?: LogGroup[];
|
||||
@ -90,3 +93,32 @@ export const LogGroupsField = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// We had to bring back the Legacy Log Group selector to support due to an issue where GovClouds do not support the new Log Group API
|
||||
// when that is fixed we can get rid of this wrapper component and just export the LogGroupsField
|
||||
type WrapperProps = {
|
||||
datasource: CloudWatchDatasource;
|
||||
onChange: (logGroups: LogGroup[]) => void;
|
||||
legacyLogGroupNames?: string[]; // will need this for a while for migration purposes
|
||||
logGroups?: LogGroup[];
|
||||
region: string;
|
||||
maxNoOfVisibleLogGroups?: number;
|
||||
onBeforeOpen?: () => void;
|
||||
|
||||
// Legacy Props, can remove once we remove support for Legacy Log Group Selector
|
||||
legacyOnChange: (logGroups: string[]) => void;
|
||||
};
|
||||
|
||||
export const LogGroupsFieldWrapper = (props: WrapperProps) => {
|
||||
if (!config.featureToggles.cloudWatchCrossAccountQuerying) {
|
||||
return (
|
||||
<LegacyLogGroupSelection
|
||||
{...props}
|
||||
onChange={props.legacyOnChange}
|
||||
legacyLogGroupNames={props.legacyLogGroupNames || []}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <LogGroupsField {...props} />;
|
||||
};
|
||||
|
@ -72,6 +72,7 @@ export class CloudWatchDatasource
|
||||
this.annotationQueryRunner = new CloudWatchAnnotationQueryRunner(instanceSettings, templateSrv);
|
||||
this.variables = new CloudWatchVariableSupport(this.resources);
|
||||
this.annotations = CloudWatchAnnotationSupport;
|
||||
this.defaultLogGroups = instanceSettings.jsonData.defaultLogGroups;
|
||||
}
|
||||
|
||||
filterQuery(query: CloudWatchQuery) {
|
||||
|
@ -164,4 +164,11 @@ export class ResourcesAPI extends CloudWatchRequest {
|
||||
tags: JSON.stringify(this.convertMultiFilterFormat(tags, 'tag name')),
|
||||
});
|
||||
}
|
||||
|
||||
legacyDescribeLogGroups(region: string, logGroupNamePrefix?: string) {
|
||||
return this.memoizedGetRequest<SelectableResourceValue[]>('legacy-log-groups', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
logGroupNamePrefix: logGroupNamePrefix || '',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user