mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Elasticsearch: Fix script fields in query editor (#31681)
* Elasticsearch: Fix script fields in query editor * properly name bucke_script deries
This commit is contained in:
parent
54f281d6ed
commit
64a8514e47
@ -23,12 +23,16 @@ interface Props {
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export const MetricPicker: FunctionComponent<Props> = ({ options, onChange, className, value }) => (
|
||||
<Segment
|
||||
className={cx(className, noWrap)}
|
||||
options={toOptions(options)}
|
||||
onChange={onChange}
|
||||
placeholder="Select Metric"
|
||||
value={!!value ? toOption(options.find((option) => option.id === value)!) : null}
|
||||
/>
|
||||
);
|
||||
export const MetricPicker: FunctionComponent<Props> = ({ options, onChange, className, value }) => {
|
||||
const selectedOption = options.find((option) => option.id === value);
|
||||
|
||||
return (
|
||||
<Segment
|
||||
className={cx(className, noWrap)}
|
||||
options={toOptions(options)}
|
||||
onChange={onChange}
|
||||
placeholder="Select Metric"
|
||||
value={!!selectedOption ? toOption(selectedOption) : null}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -4,8 +4,9 @@ import { useDispatch } from '../../../../hooks/useStatelessReducer';
|
||||
import { changeMetricSetting } from '../state/actions';
|
||||
import { ChangeMetricSettingAction } from '../state/types';
|
||||
import { SettingKeyOf } from '../../../types';
|
||||
import { MetricAggregationWithSettings } from '../aggregations';
|
||||
import { MetricAggregationWithInlineScript, MetricAggregationWithSettings } from '../aggregations';
|
||||
import { uniqueId } from 'lodash';
|
||||
import { getScriptValue } from 'app/plugins/datasource/elasticsearch/utils';
|
||||
|
||||
interface Props<T extends MetricAggregationWithSettings, K extends SettingKeyOf<T>> {
|
||||
label: string;
|
||||
@ -26,13 +27,19 @@ export function SettingField<T extends MetricAggregationWithSettings, K extends
|
||||
const [id] = useState(uniqueId(`es-field-id-`));
|
||||
const settings = metric.settings;
|
||||
|
||||
let defaultValue = settings?.[settingName as keyof typeof settings] || '';
|
||||
|
||||
if (settingName === 'script') {
|
||||
defaultValue = getScriptValue(metric as MetricAggregationWithInlineScript);
|
||||
}
|
||||
|
||||
return (
|
||||
<InlineField label={label} labelWidth={16} tooltip={tooltip}>
|
||||
<Input
|
||||
id={id}
|
||||
placeholder={placeholder}
|
||||
onBlur={(e) => dispatch(changeMetricSetting(metric, settingName, e.target.value as any))}
|
||||
defaultValue={settings?.[settingName as keyof typeof settings]}
|
||||
defaultValue={defaultValue}
|
||||
/>
|
||||
</InlineField>
|
||||
);
|
||||
|
@ -43,9 +43,10 @@ export interface MetricAggregationWithMissingSupport extends BaseMetricAggregati
|
||||
};
|
||||
}
|
||||
|
||||
type InlineScript = string | { inline?: string };
|
||||
export interface MetricAggregationWithInlineScript extends BaseMetricAggregation {
|
||||
settings?: {
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
};
|
||||
}
|
||||
|
||||
@ -59,7 +60,7 @@ export interface Average
|
||||
MetricAggregationWithInlineScript {
|
||||
type: 'avg';
|
||||
settings?: {
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
missing?: string;
|
||||
};
|
||||
}
|
||||
@ -67,7 +68,7 @@ export interface Average
|
||||
export interface Sum extends MetricAggregationWithField, MetricAggregationWithInlineScript {
|
||||
type: 'sum';
|
||||
settings?: {
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
missing?: string;
|
||||
};
|
||||
}
|
||||
@ -75,7 +76,7 @@ export interface Sum extends MetricAggregationWithField, MetricAggregationWithIn
|
||||
export interface Max extends MetricAggregationWithField, MetricAggregationWithInlineScript {
|
||||
type: 'max';
|
||||
settings?: {
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
missing?: string;
|
||||
};
|
||||
}
|
||||
@ -83,7 +84,7 @@ export interface Max extends MetricAggregationWithField, MetricAggregationWithIn
|
||||
export interface Min extends MetricAggregationWithField, MetricAggregationWithInlineScript {
|
||||
type: 'min';
|
||||
settings?: {
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
missing?: string;
|
||||
};
|
||||
}
|
||||
@ -105,7 +106,7 @@ export interface ExtendedStat {
|
||||
export interface ExtendedStats extends MetricAggregationWithField, MetricAggregationWithInlineScript {
|
||||
type: 'extended_stats';
|
||||
settings?: {
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
missing?: string;
|
||||
sigma?: string;
|
||||
};
|
||||
@ -118,7 +119,7 @@ export interface Percentiles extends MetricAggregationWithField, MetricAggregati
|
||||
type: 'percentiles';
|
||||
settings?: {
|
||||
percents?: string[];
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
missing?: string;
|
||||
};
|
||||
}
|
||||
@ -238,7 +239,7 @@ export interface MovingFunction extends BasePipelineMetricAggregation {
|
||||
type: 'moving_fn';
|
||||
settings?: {
|
||||
window?: string;
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
shift?: string;
|
||||
};
|
||||
}
|
||||
@ -267,7 +268,7 @@ export interface CumulativeSum extends BasePipelineMetricAggregation {
|
||||
export interface BucketScript extends PipelineMetricAggregationWithMultipleBucketPaths {
|
||||
type: 'bucket_script';
|
||||
settings?: {
|
||||
script?: string;
|
||||
script?: InlineScript;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ import { bucketAggregationConfig } from './components/QueryEditor/BucketAggregat
|
||||
import { isBucketAggregationWithField } from './components/QueryEditor/BucketAggregationsEditor/aggregations';
|
||||
import { generate, Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, first, map, mergeMap, skipWhile, throwIfEmpty } from 'rxjs/operators';
|
||||
import { getScriptValue } from './utils';
|
||||
|
||||
// Those are metadata fields as defined in https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-fields.html#_identity_metadata_fields.
|
||||
// custom fields can start with underscores, therefore is not safe to exclude anything that starts with one.
|
||||
@ -425,7 +426,7 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
|
||||
text += metric.field;
|
||||
}
|
||||
if (isPipelineAggregationWithMultipleBucketPaths(metric)) {
|
||||
text += metric.settings?.script?.replace(new RegExp('params.', 'g'), '');
|
||||
text += getScriptValue(metric).replace(new RegExp('params.', 'g'), '');
|
||||
}
|
||||
text += '), ';
|
||||
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
ExtendedStatMetaType,
|
||||
isMetricAggregationWithField,
|
||||
} from './components/QueryEditor/MetricAggregationsEditor/aggregations';
|
||||
import { describeMetric } from './utils';
|
||||
import { describeMetric, getScriptValue } from './utils';
|
||||
import { metricAggregationConfig } from './components/QueryEditor/MetricAggregationsEditor/utils';
|
||||
|
||||
const HIGHLIGHT_TAGS_EXP = `${queryDef.highlightTags.pre}([^@]+)${queryDef.highlightTags.post}`;
|
||||
@ -207,7 +207,7 @@ export class ElasticResponse {
|
||||
|
||||
if (metric.type === 'bucket_script') {
|
||||
//Use the formula in the column name
|
||||
metricName = metric.settings?.script || '';
|
||||
metricName = getScriptValue(metric);
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,7 +306,7 @@ export class ElasticResponse {
|
||||
if (series.metric && queryDef.isPipelineAggWithMultipleBucketPaths(series.metric)) {
|
||||
const agg: any = _.find(target.metrics, { id: series.metricId });
|
||||
if (agg && agg.settings.script) {
|
||||
metricName = agg.settings.script;
|
||||
metricName = getScriptValue(agg);
|
||||
|
||||
for (const pv of agg.pipelineVariables) {
|
||||
const appliedAgg: any = _.find(target.metrics, { id: pv.pipelineAgg });
|
||||
|
@ -9,10 +9,12 @@ import {
|
||||
isMetricAggregationWithSettings,
|
||||
isPipelineAggregation,
|
||||
isPipelineAggregationWithMultipleBucketPaths,
|
||||
MetricAggregation,
|
||||
MetricAggregationWithInlineScript,
|
||||
} from './components/QueryEditor/MetricAggregationsEditor/aggregations';
|
||||
import { defaultBucketAgg, defaultMetricAgg, findMetricById, highlightTags } from './query_def';
|
||||
import { ElasticsearchQuery } from './types';
|
||||
import { convertOrderByToMetricId } from './utils';
|
||||
import { convertOrderByToMetricId, getScriptValue } from './utils';
|
||||
|
||||
export class ElasticQueryBuilder {
|
||||
timeField: string;
|
||||
@ -204,8 +206,9 @@ export class ElasticQueryBuilder {
|
||||
target.metrics = target.metrics || [defaultMetricAgg()];
|
||||
target.bucketAggs = target.bucketAggs || [defaultBucketAgg()];
|
||||
target.timeField = this.timeField;
|
||||
let metric: MetricAggregation;
|
||||
|
||||
let i, j, pv, nestedAggs, metric;
|
||||
let i, j, pv, nestedAggs;
|
||||
const query = {
|
||||
size: 0,
|
||||
query: {
|
||||
@ -340,7 +343,9 @@ export class ElasticQueryBuilder {
|
||||
if (isMetricAggregationWithSettings(metric)) {
|
||||
Object.entries(metric.settings || {})
|
||||
.filter(([_, v]) => v !== null)
|
||||
.forEach(([k, v]) => (metricAgg[k] = v));
|
||||
.forEach(([k, v]) => {
|
||||
metricAgg[k] = k === 'script' ? getScriptValue(metric as MetricAggregationWithInlineScript) : v;
|
||||
});
|
||||
}
|
||||
|
||||
aggField[metric.type] = metricAgg;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {
|
||||
isMetricAggregationWithField,
|
||||
MetricAggregation,
|
||||
MetricAggregationWithInlineScript,
|
||||
} from './components/QueryEditor/MetricAggregationsEditor/aggregations';
|
||||
import { metricAggregationConfig } from './components/QueryEditor/MetricAggregationsEditor/utils';
|
||||
|
||||
@ -62,3 +63,31 @@ export const convertOrderByToMetricId = (orderBy: string): string | undefined =>
|
||||
const metricIdMatches = orderBy.match(/^(\d+)/);
|
||||
return metricIdMatches ? metricIdMatches[1] : void 0;
|
||||
};
|
||||
|
||||
/** Gets the actual script value for metrics that support inline scripts.
|
||||
*
|
||||
* This is needed because the `script` is a bit polymorphic.
|
||||
* when creating a query with Grafana < 7.4 it was stored as:
|
||||
* ```json
|
||||
* {
|
||||
* "settings": {
|
||||
* "script": {
|
||||
* "inline": "value"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* while from 7.4 it's stored as
|
||||
* ```json
|
||||
* {
|
||||
* "settings": {
|
||||
* "script": "value"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* This allows us to access both formats and support both queries created before 7.4 and after.
|
||||
*/
|
||||
export const getScriptValue = (metric: MetricAggregationWithInlineScript) =>
|
||||
(typeof metric.settings?.script === 'object' ? metric.settings?.script?.inline : metric.settings?.script) || '';
|
||||
|
Loading…
Reference in New Issue
Block a user