mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Elasticsearch: Add interval type selector to interval field (#76805)
* Elasticsearch: add interval type selector * Interval type: add tooltip * DateHistogramSettingsEditor: create unit test * Elastic histogram settings: refactor showing calendar type * Update test * Prettier * DateHistogramSettingsEditor: change tooltip according to interval type * Calendar intervals: add comment * Prettier
This commit is contained in:
parent
41d394c594
commit
e5f92c010d
@ -26,6 +26,9 @@ import {
|
||||
} from './types';
|
||||
import { convertOrderByToMetricId, getScriptValue } from './utils';
|
||||
|
||||
// Omitting 1m, 1h, 1d for now, as these cover the main use cases for calendar_interval
|
||||
export const calendarIntervals: string[] = ['1w', '1M', '1q', '1y'];
|
||||
|
||||
export class ElasticQueryBuilder {
|
||||
timeField: string;
|
||||
|
||||
@ -100,7 +103,6 @@ export class ElasticQueryBuilder {
|
||||
getDateHistogramAgg(aggDef: DateHistogram) {
|
||||
const esAgg: any = {};
|
||||
const settings = aggDef.settings || {};
|
||||
const calendarIntervals: string[] = ['1w', '1M', '1q', '1y'];
|
||||
|
||||
esAgg.field = aggDef.field || this.timeField;
|
||||
esAgg.min_doc_count = settings.min_doc_count || 0;
|
||||
|
@ -0,0 +1,87 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { selectOptionInTest } from 'test/helpers/selectOptionInTest';
|
||||
|
||||
import { DateHistogram } from 'app/plugins/datasource/elasticsearch/types';
|
||||
|
||||
import { useDispatch } from '../../../../hooks/useStatelessReducer';
|
||||
|
||||
import { DateHistogramSettingsEditor } from './DateHistogramSettingsEditor';
|
||||
|
||||
jest.mock('../../../../hooks/useStatelessReducer');
|
||||
|
||||
describe('DateHistogramSettingsEditor', () => {
|
||||
test('Renders the date histogram selector', async () => {
|
||||
const bucketAgg: DateHistogram = {
|
||||
field: '@timestamp',
|
||||
id: '2',
|
||||
settings: { interval: 'auto' },
|
||||
type: 'date_histogram',
|
||||
};
|
||||
render(<DateHistogramSettingsEditor bucketAgg={bucketAgg} />);
|
||||
expect(await screen.findByText('Fixed interval')).toBeInTheDocument();
|
||||
expect(await screen.findByText('auto')).toBeInTheDocument();
|
||||
});
|
||||
test('Renders the date histogram selector with a fixed interval', async () => {
|
||||
const bucketAgg: DateHistogram = {
|
||||
field: '@timestamp',
|
||||
id: '2',
|
||||
settings: { interval: '10s' },
|
||||
type: 'date_histogram',
|
||||
};
|
||||
render(<DateHistogramSettingsEditor bucketAgg={bucketAgg} />);
|
||||
expect(await screen.findByText('Fixed interval')).toBeInTheDocument();
|
||||
expect(await screen.findByText('10s')).toBeInTheDocument();
|
||||
});
|
||||
test('Renders the date histogram selector with a calendar interval', async () => {
|
||||
const bucketAgg: DateHistogram = {
|
||||
field: '@timestamp',
|
||||
id: '2',
|
||||
settings: { interval: '1w' },
|
||||
type: 'date_histogram',
|
||||
};
|
||||
render(<DateHistogramSettingsEditor bucketAgg={bucketAgg} />);
|
||||
expect(await screen.findByText('Calendar interval')).toBeInTheDocument();
|
||||
expect(await screen.findByText('1w')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('Handling change', () => {
|
||||
let dispatch = jest.fn();
|
||||
beforeEach(() => {
|
||||
dispatch.mockClear();
|
||||
jest.mocked(useDispatch).mockReturnValue(dispatch);
|
||||
});
|
||||
test('Handles changing from calendar to fixed interval type', async () => {
|
||||
const bucketAgg: DateHistogram = {
|
||||
field: '@timestamp',
|
||||
id: '2',
|
||||
settings: { interval: '1w' },
|
||||
type: 'date_histogram',
|
||||
};
|
||||
render(<DateHistogramSettingsEditor bucketAgg={bucketAgg} />);
|
||||
|
||||
expect(await screen.findByText('Calendar interval')).toBeInTheDocument();
|
||||
expect(await screen.findByText('1w')).toBeInTheDocument();
|
||||
|
||||
await selectOptionInTest(screen.getByLabelText('Calendar interval'), '10s');
|
||||
|
||||
expect(dispatch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
test('Renders the date histogram selector with a calendar interval', async () => {
|
||||
const bucketAgg: DateHistogram = {
|
||||
field: '@timestamp',
|
||||
id: '2',
|
||||
settings: { interval: '1m' },
|
||||
type: 'date_histogram',
|
||||
};
|
||||
render(<DateHistogramSettingsEditor bucketAgg={bucketAgg} />);
|
||||
|
||||
expect(await screen.findByText('Fixed interval')).toBeInTheDocument();
|
||||
expect(await screen.findByText('1m')).toBeInTheDocument();
|
||||
|
||||
await selectOptionInTest(screen.getByLabelText('Fixed interval'), '1q');
|
||||
|
||||
expect(dispatch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,9 +1,10 @@
|
||||
import { uniqueId } from 'lodash';
|
||||
import React, { useRef } from 'react';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import { GroupBase, OptionsOrGroups } from 'react-select';
|
||||
|
||||
import { InternalTimeZones, SelectableValue } from '@grafana/data';
|
||||
import { InlineField, Input, Select, TimeZonePicker } from '@grafana/ui';
|
||||
import { calendarIntervals } from 'app/plugins/datasource/elasticsearch/QueryBuilder';
|
||||
|
||||
import { useDispatch } from '../../../../hooks/useStatelessReducer';
|
||||
import { DateHistogram } from '../../../../types';
|
||||
@ -22,6 +23,10 @@ const defaultIntervalOptions: Array<SelectableValue<string>> = [
|
||||
{ label: '20m', value: '20m' },
|
||||
{ label: '1h', value: '1h' },
|
||||
{ label: '1d', value: '1d' },
|
||||
{ label: '1w', value: '1w' },
|
||||
{ label: '1M', value: '1M' },
|
||||
{ label: '1q', value: '1q' },
|
||||
{ label: '1y', value: '1y' },
|
||||
];
|
||||
|
||||
const hasValue =
|
||||
@ -48,16 +53,35 @@ interface Props {
|
||||
bucketAgg: DateHistogram;
|
||||
}
|
||||
|
||||
const getIntervalType = (interval: string | undefined): 'calendar' | 'fixed' => {
|
||||
return interval && calendarIntervals.includes(interval) ? 'calendar' : 'fixed';
|
||||
};
|
||||
|
||||
export const DateHistogramSettingsEditor = ({ bucketAgg }: Props) => {
|
||||
const dispatch = useDispatch();
|
||||
const { current: baseId } = useRef(uniqueId('es-date_histogram-'));
|
||||
|
||||
const handleIntervalChange = ({ value }: SelectableValue<string>) =>
|
||||
dispatch(changeBucketAggregationSetting({ bucketAgg, settingName: 'interval', newValue: value }));
|
||||
const handleIntervalChange = useCallback(
|
||||
({ value }: SelectableValue<string>) =>
|
||||
dispatch(changeBucketAggregationSetting({ bucketAgg, settingName: 'interval', newValue: value })),
|
||||
[bucketAgg, dispatch]
|
||||
);
|
||||
|
||||
const intervalType = getIntervalType(
|
||||
bucketAgg.settings?.interval || bucketAggregationConfig.date_histogram.defaultSettings?.interval
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<InlineField label="Interval" {...inlineFieldProps}>
|
||||
<InlineField
|
||||
label={intervalType === 'calendar' ? 'Calendar interval' : 'Fixed interval'}
|
||||
tooltip={
|
||||
intervalType === 'calendar'
|
||||
? 'Calendar-aware intervals adapt to varying day lengths, month durations, and leap seconds, considering the calendar context.'
|
||||
: 'Fixed intervals remain constant, always being multiples of SI units, independent of calendar changes.'
|
||||
}
|
||||
{...inlineFieldProps}
|
||||
>
|
||||
<Select
|
||||
inputId={uniqueId('es-date_histogram-interval')}
|
||||
isValidNewOption={isValidNewOption}
|
||||
@ -69,7 +93,6 @@ export const DateHistogramSettingsEditor = ({ bucketAgg }: Props) => {
|
||||
})}
|
||||
/>
|
||||
</InlineField>
|
||||
|
||||
<InlineField label="Min Doc Count" {...inlineFieldProps}>
|
||||
<Input
|
||||
id={`${baseId}-min_doc_count`}
|
||||
|
@ -15,7 +15,7 @@ import { TermsSettingsEditor } from './TermsSettingsEditor';
|
||||
import { useDescription } from './useDescription';
|
||||
|
||||
export const inlineFieldProps: Partial<ComponentProps<typeof InlineField>> = {
|
||||
labelWidth: 16,
|
||||
labelWidth: 18,
|
||||
};
|
||||
|
||||
interface Props {
|
||||
|
Loading…
Reference in New Issue
Block a user