Prometheus: removes props mutation (#105650)

This commit is contained in:
Hugo Häggmark
2025-05-20 14:01:17 +02:00
committed by GitHub
parent dbd88033f0
commit 7108f82cc4
@@ -3,6 +3,7 @@ import { SyntheticEvent, useState } from 'react';
import {
DataSourcePluginOptionsEditorProps,
DataSourceSettings,
onUpdateDatasourceJsonDataOptionChecked,
SelectableValue,
updateDatasourcePluginJsonDataOption,
@@ -60,14 +61,19 @@ export const NON_NEGATIVE_INTEGER_REGEX = /^(0|[1-9]\d*)(\.\d+)?(e\+?\d+)?$/; //
const durationError = 'Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s';
export const countError = 'Value is not valid, you can use non-negative integers, including scientific notation';
export const PromSettings = (props: Props) => {
const { options, onOptionsChange } = props;
const getOptionsWithDefaults = (options: DataSourceSettings<PromOptions>) => {
if (options.jsonData.httpMethod) {
return options;
}
// We are explicitly adding httpMethod so, it is correctly displayed in dropdown.
// This way, it is more predictable for users.
if (!options.jsonData.httpMethod) {
options.jsonData.httpMethod = 'POST';
}
return { ...options, jsonData: { ...options.jsonData, httpMethod: 'POST' } };
};
export const PromSettings = (props: Props) => {
const { onOptionsChange } = props;
const optionsWithDefaults = getOptionsWithDefaults(props.options);
const theme = useTheme2();
const styles = overhaulStyles(theme);
@@ -111,15 +117,15 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<>
<Input
className="width-20"
value={options.jsonData.timeInterval}
value={optionsWithDefaults.jsonData.timeInterval}
spellCheck={false}
placeholder="15s"
onChange={onChangeHandler('timeInterval', options, onOptionsChange)}
onChange={onChangeHandler('timeInterval', optionsWithDefaults, onOptionsChange)}
onBlur={(e) =>
updateValidDuration({
...validDuration,
@@ -141,13 +147,13 @@ export const PromSettings = (props: Props) => {
labelWidth={PROM_CONFIG_LABEL_WIDTH}
tooltip={<>Set the Prometheus query timeout. {docsTip()}</>}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<>
<Input
className="width-20"
value={options.jsonData.queryTimeout}
onChange={onChangeHandler('queryTimeout', options, onOptionsChange)}
value={optionsWithDefaults.jsonData.queryTimeout}
onChange={onChangeHandler('queryTimeout', optionsWithDefaults, onOptionsChange)}
spellCheck={false}
placeholder="60s"
onBlur={(e) =>
@@ -174,16 +180,16 @@ export const PromSettings = (props: Props) => {
labelWidth={PROM_CONFIG_LABEL_WIDTH}
tooltip={<>Set default editor option for all users of this data source. {docsTip()}</>}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Select
aria-label={`Default Editor (Code or Builder)`}
options={editorOptions}
value={
editorOptions.find((o) => o.value === options.jsonData.defaultEditor) ??
editorOptions.find((o) => o.value === optionsWithDefaults.jsonData.defaultEditor) ??
editorOptions.find((o) => o.value === QueryEditorMode.Builder)
}
onChange={onChangeHandler('defaultEditor', options, onOptionsChange)}
onChange={onChangeHandler('defaultEditor', optionsWithDefaults, onOptionsChange)}
width={40}
data-testid={selectors.components.DataSource.Prometheus.configPage.defaultEditor}
/>
@@ -201,11 +207,11 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
className={styles.switchField}
>
<Switch
value={options.jsonData.disableMetricsLookup ?? false}
value={optionsWithDefaults.jsonData.disableMetricsLookup ?? false}
onChange={onUpdateDatasourceJsonDataOptionChecked(props, 'disableMetricsLookup')}
id={selectors.components.DataSource.Prometheus.configPage.disableMetricLookup}
/>
@@ -215,18 +221,20 @@ export const PromSettings = (props: Props) => {
</ConfigSubSection>
<ConfigSubSection title="Performance" className={styles.container}>
{!options.jsonData.prometheusType && !options.jsonData.prometheusVersion && options.readOnly && (
<div className={styles.versionMargin}>
For more information on configuring prometheus type and version in data sources, see the{' '}
<a
className={styles.textUnderline}
href="https://grafana.com/docs/grafana/latest/administration/provisioning/"
>
provisioning documentation
</a>
.
</div>
)}
{!optionsWithDefaults.jsonData.prometheusType &&
!optionsWithDefaults.jsonData.prometheusVersion &&
optionsWithDefaults.readOnly && (
<div className={styles.versionMargin}>
For more information on configuring prometheus type and version in data sources, see the{' '}
<a
className={styles.textUnderline}
href="https://grafana.com/docs/grafana/latest/administration/provisioning/"
>
provisioning documentation
</a>
.
</div>
)}
<div className="gf-form-group">
<div className="gf-form-inline">
<div className="gf-form">
@@ -245,13 +253,15 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Select
aria-label="Prometheus type"
options={prometheusFlavorSelectItems}
value={prometheusFlavorSelectItems.find((o) => o.value === options.jsonData.prometheusType)}
onChange={onChangeHandler('prometheusType', options, onOptionsChange)}
value={prometheusFlavorSelectItems.find(
(o) => o.value === optionsWithDefaults.jsonData.prometheusType
)}
onChange={onChangeHandler('prometheusType', optionsWithDefaults, onOptionsChange)}
width={40}
data-testid={selectors.components.DataSource.Prometheus.configPage.prometheusType}
/>
@@ -259,27 +269,27 @@ export const PromSettings = (props: Props) => {
</div>
</div>
<div className="gf-form-inline">
{options.jsonData.prometheusType && (
{optionsWithDefaults.jsonData.prometheusType && (
<div className="gf-form">
<InlineField
label={`${options.jsonData.prometheusType} version`}
label={`${optionsWithDefaults.jsonData.prometheusType} version`}
labelWidth={PROM_CONFIG_LABEL_WIDTH}
tooltip={
<>
Use this to set the version of your {options.jsonData.prometheusType} instance if it is not
automatically configured. {docsTip()}
Use this to set the version of your {optionsWithDefaults.jsonData.prometheusType} instance if it
is not automatically configured. {docsTip()}
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Select
aria-label={`${options.jsonData.prometheusType} type`}
options={PromFlavorVersions[options.jsonData.prometheusType]}
value={PromFlavorVersions[options.jsonData.prometheusType]?.find(
(o) => o.value === options.jsonData.prometheusVersion
aria-label={`${optionsWithDefaults.jsonData.prometheusType} type`}
options={PromFlavorVersions[optionsWithDefaults.jsonData.prometheusType]}
value={PromFlavorVersions[optionsWithDefaults.jsonData.prometheusType]?.find(
(o) => o.value === optionsWithDefaults.jsonData.prometheusVersion
)}
onChange={onChangeHandler('prometheusVersion', options, onOptionsChange)}
onChange={onChangeHandler('prometheusVersion', optionsWithDefaults, onOptionsChange)}
width={40}
data-testid={selectors.components.DataSource.Prometheus.configPage.prometheusVersion}
/>
@@ -300,14 +310,15 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Select
width={40}
onChange={onChangeHandler('cacheLevel', options, onOptionsChange)}
onChange={onChangeHandler('cacheLevel', optionsWithDefaults, onOptionsChange)}
options={cacheValueOptions}
value={
cacheValueOptions.find((o) => o.value === options.jsonData.cacheLevel) ?? PrometheusCacheLevel.Low
cacheValueOptions.find((o) => o.value === optionsWithDefaults.jsonData.cacheLevel) ??
PrometheusCacheLevel.Low
}
data-testid={selectors.components.DataSource.Prometheus.configPage.cacheLevel}
/>
@@ -328,13 +339,17 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<>
<Input
className="width-20"
value={options.jsonData.codeModeMetricNamesSuggestionLimit}
onChange={onChangeHandler('codeModeMetricNamesSuggestionLimit', options, onOptionsChange)}
value={optionsWithDefaults.jsonData.codeModeMetricNamesSuggestionLimit}
onChange={onChangeHandler(
'codeModeMetricNamesSuggestionLimit',
optionsWithDefaults,
onOptionsChange
)}
spellCheck={false}
placeholder={SUGGESTIONS_LIMIT.toString()}
onBlur={(e) =>
@@ -372,10 +387,10 @@ export const PromSettings = (props: Props) => {
}
interactive={true}
className={styles.switchField}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Switch
value={options.jsonData.incrementalQuerying ?? false}
value={optionsWithDefaults.jsonData.incrementalQuerying ?? false}
onChange={onUpdateDatasourceJsonDataOptionChecked(props, 'incrementalQuerying')}
id={selectors.components.DataSource.Prometheus.configPage.incrementalQuerying}
/>
@@ -384,7 +399,7 @@ export const PromSettings = (props: Props) => {
</div>
<div className="gf-form-inline">
{options.jsonData.incrementalQuerying && (
{optionsWithDefaults.jsonData.incrementalQuerying && (
<InlineField
label="Query overlap window"
labelWidth={PROM_CONFIG_LABEL_WIDTH}
@@ -395,7 +410,7 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<>
<Input
@@ -406,8 +421,10 @@ export const PromSettings = (props: Props) => {
})
}
className="width-20"
value={options.jsonData.incrementalQueryOverlapWindow ?? defaultPrometheusQueryOverlapWindow}
onChange={onChangeHandler('incrementalQueryOverlapWindow', options, onOptionsChange)}
value={
optionsWithDefaults.jsonData.incrementalQueryOverlapWindow ?? defaultPrometheusQueryOverlapWindow
}
onChange={onChangeHandler('incrementalQueryOverlapWindow', optionsWithDefaults, onOptionsChange)}
spellCheck={false}
data-testid={selectors.components.DataSource.Prometheus.configPage.queryOverlapWindow}
/>
@@ -425,10 +442,10 @@ export const PromSettings = (props: Props) => {
tooltip={<>This feature will disable recording rules Turn this on to improve dashboard performance</>}
interactive={true}
className={styles.switchField}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Switch
value={options.jsonData.disableRecordingRules ?? false}
value={optionsWithDefaults.jsonData.disableRecordingRules ?? false}
onChange={onUpdateDatasourceJsonDataOptionChecked(props, 'disableRecordingRules')}
id={selectors.components.DataSource.Prometheus.configPage.disableRecordingRules}
/>
@@ -452,12 +469,12 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Input
className="width-20"
value={options.jsonData.customQueryParameters}
onChange={onChangeHandler('customQueryParameters', options, onOptionsChange)}
value={optionsWithDefaults.jsonData.customQueryParameters}
onChange={onChangeHandler('customQueryParameters', optionsWithDefaults, onOptionsChange)}
spellCheck={false}
placeholder="Example: max_source_resolution=5m&timeout=10"
data-testid={selectors.components.DataSource.Prometheus.configPage.customQueryParameters}
@@ -479,14 +496,14 @@ export const PromSettings = (props: Props) => {
}
interactive={true}
label="HTTP method"
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
>
<Select
width={40}
aria-label="Select HTTP method"
options={httpOptions}
value={httpOptions.find((o) => o.value === options.jsonData.httpMethod)}
onChange={onChangeHandler('httpMethod', options, onOptionsChange)}
value={httpOptions.find((o) => o.value === optionsWithDefaults.jsonData.httpMethod)}
onChange={onChangeHandler('httpMethod', optionsWithDefaults, onOptionsChange)}
data-testid={selectors.components.DataSource.Prometheus.configPage.httpMethod}
/>
</InlineField>
@@ -504,11 +521,11 @@ export const PromSettings = (props: Props) => {
</>
}
interactive={true}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
className={styles.switchField}
>
<Switch
value={options.jsonData.seriesEndpoint ?? false}
value={optionsWithDefaults.jsonData.seriesEndpoint ?? false}
onChange={onUpdateDatasourceJsonDataOptionChecked(props, 'seriesEndpoint')}
/>
</InlineField>
@@ -516,15 +533,15 @@ export const PromSettings = (props: Props) => {
</ConfigSubSection>
<ExemplarsSettings
options={options.jsonData.exemplarTraceIdDestinations}
options={optionsWithDefaults.jsonData.exemplarTraceIdDestinations}
onChange={(exemplarOptions) =>
updateDatasourcePluginJsonDataOption(
{ onOptionsChange, options },
{ onOptionsChange, options: optionsWithDefaults },
'exemplarTraceIdDestinations',
exemplarOptions
)
}
disabled={options.readOnly}
disabled={optionsWithDefaults.readOnly}
/>
</>
);