Elasticsearch: add additional settings section (#71037)

* Elasticsearch: add additional settings section

* Remove extra lines

* Elastic config: add divider between name and http settings

* Data links: fix subsection title

* Remove unused import
This commit is contained in:
Matias Chomicki 2023-07-05 10:45:10 +02:00 committed by GitHub
parent 7fed3f84f6
commit d153fd434a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 202 additions and 161 deletions

View File

@ -2,7 +2,9 @@ import React, { useEffect, useRef } from 'react';
import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { ConfigSection } from '@grafana/experimental';
import { Alert, DataSourceHttpSettings } from '@grafana/ui';
import { Divider } from 'app/core/components/Divider';
import { config } from 'app/core/config';
import { ElasticsearchOptions } from '../types';
@ -36,6 +38,9 @@ export const ConfigEditor = (props: Props) => {
Browser access mode in the Elasticsearch datasource is no longer available. Switch to server access mode.
</Alert>
)}
<Divider />
<DataSourceHttpSettings
defaultUrl="http://localhost:9200"
dataSourceConfig={options}
@ -46,30 +51,39 @@ export const ConfigEditor = (props: Props) => {
secureSocksDSProxyEnabled={config.secureSocksDSProxyEnabled}
/>
<ElasticDetails value={options} onChange={onOptionsChange} />
<Divider />
<LogsConfig
value={options.jsonData}
onChange={(newValue) =>
onOptionsChange({
...options,
jsonData: newValue,
})
}
/>
<DataLinks
value={options.jsonData.dataLinks}
onChange={(newValue) => {
onOptionsChange({
...options,
jsonData: {
...options.jsonData,
dataLinks: newValue,
},
});
}}
/>
<ConfigSection
title="Additional settings"
description="Additional settings are optional settings that can be configured for more control over your data source."
isCollapsible={true}
isInitiallyOpen
>
<ElasticDetails value={options} onChange={onOptionsChange} />
<Divider hideLine />
<LogsConfig
value={options.jsonData}
onChange={(newValue) =>
onOptionsChange({
...options,
jsonData: newValue,
})
}
/>
<Divider hideLine />
<DataLinks
value={options.jsonData.dataLinks}
onChange={(newValue) => {
onOptionsChange({
...options,
jsonData: {
...options.jsonData,
dataLinks: newValue,
},
});
}}
/>
</ConfigSection>
</>
);
};

View File

@ -2,7 +2,9 @@ import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2, VariableOrigin, DataLinkBuiltInVars } from '@grafana/data';
import { ConfigSubSection } from '@grafana/experimental';
import { Button, useStyles2 } from '@grafana/ui';
import { ConfigDescriptionLink } from 'app/core/components/ConfigDescriptionLink';
import { DataLinkConfig } from '../types';
@ -10,9 +12,11 @@ import { DataLink } from './DataLink';
const getStyles = (theme: GrafanaTheme2) => {
return {
infoText: css`
padding-bottom: ${theme.spacing(2)};
color: ${theme.colors.text.secondary};
addButton: css`
margin-right: 10px;
`,
container: css`
margin-bottom: ${theme.spacing(2)};
`,
dataLink: css`
margin-bottom: ${theme.spacing(1)};
@ -29,60 +33,63 @@ export const DataLinks = (props: Props) => {
const styles = useStyles2(getStyles);
return (
<>
<h3 className="page-heading">Data links</h3>
<ConfigSubSection
title="Data links"
description={
<ConfigDescriptionLink
description="Add links to existing fields. Links will be shown in log row details next to the field value."
suffix="elasticsearch/#data-links"
feature="Elasticsearch data links"
/>
}
>
<div className={styles.container}>
{value && value.length > 0 && (
<div className="gf-form-group">
{value.map((field, index) => {
return (
<DataLink
className={styles.dataLink}
key={index}
value={field}
onChange={(newField) => {
const newDataLinks = [...value];
newDataLinks.splice(index, 1, newField);
onChange(newDataLinks);
}}
onDelete={() => {
const newDataLinks = [...value];
newDataLinks.splice(index, 1);
onChange(newDataLinks);
}}
suggestions={[
{
value: DataLinkBuiltInVars.valueRaw,
label: 'Raw value',
documentation: 'Raw value of the field',
origin: VariableOrigin.Value,
},
]}
/>
);
})}
</div>
)}
<div className={styles.infoText}>
Add links to existing fields. Links will be shown in log row details next to the field value.
<Button
type="button"
variant={'secondary'}
className={styles.addButton}
icon="plus"
onClick={(event) => {
event.preventDefault();
const newDataLinks = [...(value || []), { field: '', url: '' }];
onChange(newDataLinks);
}}
>
Add
</Button>
</div>
{value && value.length > 0 && (
<div className="gf-form-group">
{value.map((field, index) => {
return (
<DataLink
className={styles.dataLink}
key={index}
value={field}
onChange={(newField) => {
const newDataLinks = [...value];
newDataLinks.splice(index, 1, newField);
onChange(newDataLinks);
}}
onDelete={() => {
const newDataLinks = [...value];
newDataLinks.splice(index, 1);
onChange(newDataLinks);
}}
suggestions={[
{
value: DataLinkBuiltInVars.valueRaw,
label: 'Raw value',
documentation: 'Raw value of the field',
origin: VariableOrigin.Value,
},
]}
/>
);
})}
</div>
)}
<Button
type="button"
variant={'secondary'}
className={css`
margin-right: 10px;
`}
icon="plus"
onClick={(event) => {
event.preventDefault();
const newDataLinks = [...(value || []), { field: '', url: '' }];
onChange(newDataLinks);
}}
>
Add
</Button>
</>
</ConfigSubSection>
);
};

View File

@ -1,7 +1,9 @@
import React from 'react';
import { DataSourceSettings, SelectableValue } from '@grafana/data';
import { FieldSet, InlineField, Input, Select, InlineSwitch } from '@grafana/ui';
import { ConfigSubSection } from '@grafana/experimental';
import { InlineField, Input, Select, InlineSwitch } from '@grafana/ui';
import { ConfigDescriptionLink } from 'app/core/components/ConfigDescriptionLink';
import { ElasticsearchOptions, Interval } from '../types';
@ -20,92 +22,99 @@ type Props = {
};
export const ElasticDetails = ({ value, onChange }: Props) => {
return (
<>
<FieldSet label="Elasticsearch details">
<InlineField label="Index name" htmlFor="es_config_indexName" labelWidth={26}>
<Input
id="es_config_indexName"
value={value.jsonData.index ?? (value.database || '')}
onChange={indexChangeHandler(value, onChange)}
width={24}
placeholder="es-index-name"
required
/>
</InlineField>
<ConfigSubSection
title="Elasticsearch details"
description={
<ConfigDescriptionLink
description="Specific settings for the Elasticsearch data source."
suffix="elasticsearch/#index-settings"
feature="Elasticsearch details"
/>
}
>
<InlineField label="Index name" htmlFor="es_config_indexName" labelWidth={26}>
<Input
id="es_config_indexName"
value={value.jsonData.index ?? (value.database || '')}
onChange={indexChangeHandler(value, onChange)}
width={24}
placeholder="es-index-name"
required
/>
</InlineField>
<InlineField label="Pattern" htmlFor="es_config_indexPattern" labelWidth={26}>
<Select
inputId="es_config_indexPattern"
value={indexPatternTypes.find(
(pattern) => pattern.value === (value.jsonData.interval === undefined ? 'none' : value.jsonData.interval)
)}
options={indexPatternTypes}
onChange={intervalHandler(value, onChange)}
width={24}
/>
</InlineField>
<InlineField label="Pattern" htmlFor="es_config_indexPattern" labelWidth={26}>
<Select
inputId="es_config_indexPattern"
value={indexPatternTypes.find(
(pattern) => pattern.value === (value.jsonData.interval === undefined ? 'none' : value.jsonData.interval)
)}
options={indexPatternTypes}
onChange={intervalHandler(value, onChange)}
width={24}
/>
</InlineField>
<InlineField label="Time field name" htmlFor="es_config_timeField" labelWidth={26}>
<Input
id="es_config_timeField"
value={value.jsonData.timeField || ''}
onChange={jsonDataChangeHandler('timeField', value, onChange)}
width={24}
placeholder="@timestamp"
required
/>
</InlineField>
<InlineField label="Time field name" htmlFor="es_config_timeField" labelWidth={26}>
<Input
id="es_config_timeField"
value={value.jsonData.timeField || ''}
onChange={jsonDataChangeHandler('timeField', value, onChange)}
width={24}
placeholder="@timestamp"
required
/>
</InlineField>
<InlineField label="Max concurrent Shard Requests" htmlFor="es_config_shardRequests" labelWidth={26}>
<Input
id="es_config_shardRequests"
value={value.jsonData.maxConcurrentShardRequests || ''}
onChange={jsonDataChangeHandler('maxConcurrentShardRequests', value, onChange)}
width={24}
/>
</InlineField>
<InlineField label="Max concurrent Shard Requests" htmlFor="es_config_shardRequests" labelWidth={26}>
<Input
id="es_config_shardRequests"
value={value.jsonData.maxConcurrentShardRequests || ''}
onChange={jsonDataChangeHandler('maxConcurrentShardRequests', value, onChange)}
width={24}
/>
</InlineField>
<InlineField
label="Min time interval"
htmlFor="es_config_minTimeInterval"
labelWidth={26}
tooltip={
<>
A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '}
<code>1m</code> if your data is written every minute.
</>
}
error="Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s"
invalid={!!value.jsonData.timeInterval && !/^\d+(ms|[Mwdhmsy])$/.test(value.jsonData.timeInterval)}
>
<Input
id="es_config_minTimeInterval"
value={value.jsonData.timeInterval || ''}
onChange={jsonDataChangeHandler('timeInterval', value, onChange)}
width={24}
placeholder="10s"
/>
</InlineField>
<InlineField
label="Min time interval"
htmlFor="es_config_minTimeInterval"
labelWidth={26}
tooltip={
<>
A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '}
<code>1m</code> if your data is written every minute.
</>
}
error="Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s"
invalid={!!value.jsonData.timeInterval && !/^\d+(ms|[Mwdhmsy])$/.test(value.jsonData.timeInterval)}
>
<Input
id="es_config_minTimeInterval"
value={value.jsonData.timeInterval || ''}
onChange={jsonDataChangeHandler('timeInterval', value, onChange)}
width={24}
placeholder="10s"
/>
</InlineField>
<InlineField label="X-Pack enabled" labelWidth={26}>
<InlineField label="X-Pack enabled" labelWidth={26}>
<InlineSwitch
id="es_config_xpackEnabled"
value={value.jsonData.xpack || false}
onChange={jsonDataSwitchChangeHandler('xpack', value, onChange)}
/>
</InlineField>
{value.jsonData.xpack && (
<InlineField label="Include Frozen Indices" htmlFor="es_config_frozenIndices" labelWidth={26}>
<InlineSwitch
id="es_config_xpackEnabled"
value={value.jsonData.xpack || false}
onChange={jsonDataSwitchChangeHandler('xpack', value, onChange)}
id="es_config_frozenIndices"
value={value.jsonData.includeFrozen ?? false}
onChange={jsonDataSwitchChangeHandler('includeFrozen', value, onChange)}
/>
</InlineField>
{value.jsonData.xpack && (
<InlineField label="Include Frozen Indices" htmlFor="es_config_frozenIndices" labelWidth={26}>
<InlineSwitch
id="es_config_frozenIndices"
value={value.jsonData.includeFrozen ?? false}
onChange={jsonDataSwitchChangeHandler('includeFrozen', value, onChange)}
/>
</InlineField>
)}
</FieldSet>
</>
)}
</ConfigSubSection>
);
};

View File

@ -1,6 +1,8 @@
import React from 'react';
import { Input, InlineField, FieldSet } from '@grafana/ui';
import { ConfigSubSection } from '@grafana/experimental';
import { Input, InlineField } from '@grafana/ui';
import { ConfigDescriptionLink } from 'app/core/components/ConfigDescriptionLink';
import { ElasticsearchOptions } from '../types';
@ -19,7 +21,16 @@ export const LogsConfig = (props: Props) => {
};
return (
<FieldSet label="Logs">
<ConfigSubSection
title="Logs"
description={
<ConfigDescriptionLink
description="Configure which fields the data source uses for log messages and log levels."
suffix="elasticsearch/#logs"
feature="Elasticsearch log fields"
/>
}
>
<InlineField label="Message field name" labelWidth={22}>
<Input
id="es_logs-config_logMessageField"
@ -38,6 +49,6 @@ export const LogsConfig = (props: Props) => {
width={24}
/>
</InlineField>
</FieldSet>
</ConfigSubSection>
);
};