D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
usr
/
share
/
grafana
/
public
/
app
/
plugins
/
datasource
/
cloudwatch
/
components
/
Filename :
ConfigEditor.tsx
back
Copy
import React, { useEffect, useState } from 'react'; import { useDebounce } from 'react-use'; import { ConnectionConfig } from '@grafana/aws-sdk'; import { rangeUtil, DataSourcePluginOptionsEditorProps, onUpdateDatasourceJsonDataOption, updateDatasourcePluginJsonDataOption, } from '@grafana/data'; import { Input, InlineField, FieldProps, SecureSocksProxySettings } from '@grafana/ui'; import { notifyApp } from 'app/core/actions'; import { config } from 'app/core/config'; import { createWarningNotification } from 'app/core/copy/appNotification'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { store } from 'app/store/store'; import { CloudWatchDatasource } from '../datasource'; import { SelectableResourceValue } from '../resources/types'; import { CloudWatchJsonData, CloudWatchSecureJsonData } from '../types'; import { LogGroupsFieldWrapper } from './LogGroups/LogGroupsField'; import { XrayLinkConfig } from './XrayLinkConfig'; export type Props = DataSourcePluginOptionsEditorProps<CloudWatchJsonData, CloudWatchSecureJsonData>; type LogGroupFieldState = Pick<FieldProps, 'invalid'> & { error?: string | null }; export const ConfigEditor = (props: Props) => { const { options, onOptionsChange } = props; const { defaultLogGroups, logsTimeout, defaultRegion, logGroups } = options.jsonData; const datasource = useDatasource(props); useAuthenticationWarning(options.jsonData); const logsTimeoutError = useTimoutValidation(logsTimeout); const saved = useDataSourceSavedState(props); const [logGroupFieldState, setLogGroupFieldState] = useState<LogGroupFieldState>({ invalid: false, }); useEffect(() => setLogGroupFieldState({ invalid: false }), [props.options]); return ( <> <ConnectionConfig {...props} labelWidth={29} loadRegions={ datasource && (async () => { return datasource.resources .getRegions() .then((regions) => regions.reduce( (acc: string[], curr: SelectableResourceValue) => (curr.value ? [...acc, curr.value] : acc), [] ) ); }) } > <InlineField label="Namespaces of Custom Metrics" labelWidth={29} tooltip="Namespaces of Custom Metrics."> <Input width={60} placeholder="Namespace1,Namespace2" value={options.jsonData.customMetricsNamespaces || ''} onChange={onUpdateDatasourceJsonDataOption(props, 'customMetricsNamespaces')} /> </InlineField> </ConnectionConfig> {config.secureSocksDSProxyEnabled && ( <SecureSocksProxySettings options={options} onOptionsChange={onOptionsChange} /> )} <h3 className="page-heading">CloudWatch Logs</h3> <div className="gf-form-group"> <InlineField label="Retry Timeout" labelWidth={28} tooltip='Cloudwatch Logs allows for a maximum of 30 concurrent queries. If Grafana hits a concurrent max query error from Cloudwatch Logs it will auto-retry requesting a query for up to 30min. This retry timeout strategy is configurable. Must be a valid duration string, such as "15m" "30s" "2000ms" etc.' invalid={Boolean(logsTimeoutError)} > <Input width={60} placeholder="30m" value={options.jsonData.logsTimeout || ''} onChange={onUpdateDatasourceJsonDataOption(props, 'logsTimeout')} title={'The timeout must be a valid duration string, such as "15m" "30s" "2000ms" etc.'} /> </InlineField> <InlineField label="Default Log Groups" labelWidth={28} tooltip="Optionally, specify default log groups for CloudWatch Logs queries." shrink={true} {...logGroupFieldState} > {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} //legacy props legacyOnChange={(logGroups) => { updateDatasourcePluginJsonDataOption(props, 'defaultLogGroups', logGroups); }} /> ) : ( <></> )} </InlineField> </div> <XrayLinkConfig onChange={(uid) => updateDatasourcePluginJsonDataOption(props, 'tracingDatasourceUid', uid)} datasourceUid={options.jsonData.tracingDatasourceUid} /> </> ); }; function useAuthenticationWarning(jsonData: CloudWatchJsonData) { const addWarning = (message: string) => { store.dispatch(notifyApp(createWarningNotification('CloudWatch Authentication', message))); }; useEffect(() => { if (jsonData.authType === 'arn') { addWarning('Since grafana 7.3 authentication type "arn" is deprecated, falling back to default SDK provider'); } else if (jsonData.authType === 'credentials' && !jsonData.profile && !jsonData.database) { addWarning( 'As of grafana 7.3 authentication type "credentials" should be used only for shared file credentials. \ If you don\'t have a credentials file, switch to the default SDK provider for extracting credentials \ from environment variables or IAM roles' ); } }, [jsonData.authType, jsonData.database, jsonData.profile]); } function useDatasource(props: Props) { const [datasource, setDatasource] = useState<CloudWatchDatasource>(); useEffect(() => { if (props.options.version) { getDatasourceSrv() .loadDatasource(props.options.name) .then((datasource) => { if (datasource instanceof CloudWatchDatasource) { setDatasource(datasource); } }); } }, [props.options.version, props.options.name]); return datasource; } function useTimoutValidation(value: string | undefined) { const [err, setErr] = useState<undefined | string>(undefined); useDebounce( () => { if (value) { try { rangeUtil.describeInterval(value); setErr(undefined); } catch (e) { if (e instanceof Error) { setErr(e.toString()); } } } else { setErr(undefined); } }, 350, [value] ); return err; } function useDataSourceSavedState(props: Props) { const [saved, setSaved] = useState(!!props.options.version && props.options.version > 1); useEffect(() => { setSaved(false); }, [ props.options.jsonData.assumeRoleArn, props.options.jsonData.authType, props.options.jsonData.defaultRegion, props.options.jsonData.endpoint, props.options.jsonData.externalId, props.options.jsonData.profile, props.options.secureJsonData?.accessKey, props.options.secureJsonData?.secretKey, ]); useEffect(() => { props.options.version && props.options.version > 1 && setSaved(true); }, [props.options.version]); return saved; }