[TSVB] Fix TSVB is not reporting all categories of Elasticsearch error (#102926)
* [TSVB] Fix TSVB is not reporting all categories of Elasticsearch error Closes: #94182 * move validation to server side Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b92d955b56
commit
790bd35ea7
|
@ -25,7 +25,7 @@ export class FieldNotFoundError extends Error {
|
|||
return this.constructor.name;
|
||||
}
|
||||
|
||||
public get body() {
|
||||
public get errBody() {
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,20 +7,29 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { GTE_INTERVAL_RE } from '../../../common/interval_regexp';
|
||||
import { search } from '../../../../../plugins/data/public';
|
||||
import { GTE_INTERVAL_RE } from './interval_regexp';
|
||||
import { parseInterval, TimeRangeBounds } from '../../data/common';
|
||||
|
||||
import type { TimeRangeBounds } from '../../../../data/common';
|
||||
import type { TimeseriesVisParams } from '../../types';
|
||||
export class ValidateIntervalError extends Error {
|
||||
constructor() {
|
||||
super(
|
||||
i18n.translate('visTypeTimeseries.validateInterval.notifier.maxBucketsExceededErrorMessage', {
|
||||
defaultMessage:
|
||||
'Your query attempted to fetch too much data. Reducing the time range or changing the interval used usually fixes the issue.',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const { parseInterval } = search.aggs;
|
||||
public get name() {
|
||||
return this.constructor.name;
|
||||
}
|
||||
|
||||
export function validateInterval(
|
||||
bounds: TimeRangeBounds,
|
||||
panel: TimeseriesVisParams,
|
||||
maxBuckets: number
|
||||
) {
|
||||
const { interval } = panel;
|
||||
public get errBody() {
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
|
||||
export function validateInterval(bounds: TimeRangeBounds, interval: string, maxBuckets: number) {
|
||||
const { min, max } = bounds;
|
||||
// No need to check auto it will return around 100
|
||||
if (!interval) return;
|
||||
|
@ -33,15 +42,7 @@ export function validateInterval(
|
|||
const span = max!.valueOf() - min!.valueOf();
|
||||
const buckets = Math.floor(span / duration.asMilliseconds());
|
||||
if (buckets > maxBuckets) {
|
||||
throw new Error(
|
||||
i18n.translate(
|
||||
'visTypeTimeseries.validateInterval.notifier.maxBucketsExceededErrorMessage',
|
||||
{
|
||||
defaultMessage:
|
||||
'Your query attempted to fetch too much data. Reducing the time range or changing the interval used usually fixes the issue.',
|
||||
}
|
||||
)
|
||||
);
|
||||
throw new ValidateIntervalError();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,6 @@ import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
|
|||
import { PersistedState } from 'src/plugins/visualizations/public';
|
||||
import { PaletteRegistry } from 'src/plugins/charts/public';
|
||||
|
||||
// @ts-expect-error
|
||||
import { ErrorComponent } from './error';
|
||||
import { TimeseriesVisTypes } from './vis_types';
|
||||
import type { TimeseriesVisData, PanelData } from '../../../common/types';
|
||||
import { isVisSeriesData } from '../../../common/vis_data_utils';
|
||||
|
@ -147,16 +145,6 @@ function TimeseriesVisualization({
|
|||
handlers.done();
|
||||
});
|
||||
|
||||
// Show the error panel
|
||||
const error = isVisSeriesData(visData) && visData[model.id]?.error;
|
||||
if (error) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<ErrorComponent error={error} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const VisComponent = TimeseriesVisTypes[model.type];
|
||||
|
||||
const isLastValueMode =
|
||||
|
|
|
@ -159,8 +159,8 @@ export class VisEditor extends Component<TimeseriesEditorProps, TimeseriesEditor
|
|||
this.setState({ autoApply: event.target.checked });
|
||||
};
|
||||
|
||||
onDataChange = ({ visData }: { visData: TimeseriesVisData }) => {
|
||||
this.visDataSubject.next(visData);
|
||||
onDataChange = (data: { visData?: TimeseriesVisData }) => {
|
||||
this.visDataSubject.next(data?.visData);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { KibanaContext } from '../../data/public';
|
||||
|
||||
import { getTimezone } from './application/lib/get_timezone';
|
||||
import { validateInterval } from './application/lib/validate_interval';
|
||||
import { getUISettings, getDataStart, getCoreStart } from './services';
|
||||
import { MAX_BUCKETS_SETTING, ROUTES } from '../common/constants';
|
||||
import { TimeseriesVisParams } from './types';
|
||||
import { ROUTES } from '../common/constants';
|
||||
|
||||
import type { TimeseriesVisParams } from './types';
|
||||
import type { TimeseriesVisData } from '../common/types';
|
||||
import type { KibanaContext } from '../../data/public';
|
||||
|
||||
interface MetricsRequestHandlerParams {
|
||||
input: KibanaContext | null;
|
||||
|
@ -37,10 +36,6 @@ export const metricsRequestHandler = async ({
|
|||
const parsedTimeRange = data.query.timefilter.timefilter.calculateBounds(input?.timeRange!);
|
||||
|
||||
if (visParams && visParams.id && !visParams.isModelInvalid) {
|
||||
const maxBuckets = config.get<number>(MAX_BUCKETS_SETTING);
|
||||
|
||||
validateInterval(parsedTimeRange, visParams, maxBuckets);
|
||||
|
||||
const untrackSearch =
|
||||
dataSearch.session.isCurrentSession(searchSessionId) &&
|
||||
dataSearch.session.trackSearch({
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import _ from 'lodash';
|
||||
|
||||
import { Framework } from '../plugin';
|
||||
import type { TimeseriesVisData } from '../../common/types';
|
||||
import type { TimeseriesVisData, FetchedIndexPattern, Series } from '../../common/types';
|
||||
import { PANEL_TYPES } from '../../common/enums';
|
||||
import type {
|
||||
VisTypeTimeseriesVisDataRequest,
|
||||
|
@ -20,6 +20,8 @@ import { getSeriesData } from './vis_data/get_series_data';
|
|||
import { getTableData } from './vis_data/get_table_data';
|
||||
import { getEsQueryConfig } from './vis_data/helpers/get_es_query_uisettings';
|
||||
import { getCachedIndexPatternFetcher } from './search_strategies/lib/cached_index_pattern_fetcher';
|
||||
import { MAX_BUCKETS_SETTING } from '../../common/constants';
|
||||
import { getIntervalAndTimefield } from './vis_data/get_interval_and_timefield';
|
||||
|
||||
export async function getVisData(
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext,
|
||||
|
@ -32,15 +34,41 @@ export async function getVisData(
|
|||
const esQueryConfig = await getEsQueryConfig(uiSettings);
|
||||
|
||||
const promises = request.body.panels.map((panel) => {
|
||||
const cachedIndexPatternFetcher = getCachedIndexPatternFetcher(indexPatternsService, {
|
||||
fetchKibanaIndexForStringIndexes: Boolean(panel.use_kibana_indexes),
|
||||
});
|
||||
const services: VisTypeTimeseriesRequestServices = {
|
||||
esQueryConfig,
|
||||
esShardTimeout,
|
||||
indexPatternsService,
|
||||
uiSettings,
|
||||
cachedIndexPatternFetcher,
|
||||
searchStrategyRegistry: framework.searchStrategyRegistry,
|
||||
cachedIndexPatternFetcher: getCachedIndexPatternFetcher(indexPatternsService, {
|
||||
fetchKibanaIndexForStringIndexes: Boolean(panel.use_kibana_indexes),
|
||||
}),
|
||||
buildSeriesMetaParams: async (
|
||||
index: FetchedIndexPattern,
|
||||
useKibanaIndexes: boolean,
|
||||
series?: Series
|
||||
) => {
|
||||
/** This part of code is required to try to get the default timefield for string indices.
|
||||
* The rest of the functionality available for Kibana indexes should not be active **/
|
||||
if (!useKibanaIndexes && index.indexPatternString) {
|
||||
index = await cachedIndexPatternFetcher(index.indexPatternString, true);
|
||||
}
|
||||
|
||||
const maxBuckets = await uiSettings.get<number>(MAX_BUCKETS_SETTING);
|
||||
const { min, max } = request.body.timerange;
|
||||
|
||||
return getIntervalAndTimefield(
|
||||
panel,
|
||||
index,
|
||||
{
|
||||
min,
|
||||
max,
|
||||
maxBuckets,
|
||||
},
|
||||
series
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
return panel.type === PANEL_TYPES.TABLE
|
||||
|
|
|
@ -11,12 +11,17 @@ import { FetchedIndexPattern, Panel, Series } from '../../../common/types';
|
|||
|
||||
describe('getIntervalAndTimefield(panel, series)', () => {
|
||||
const index: FetchedIndexPattern = {} as FetchedIndexPattern;
|
||||
const params = {
|
||||
min: '2017-01-01T00:00:00Z',
|
||||
max: '2017-01-01T01:00:00Z',
|
||||
maxBuckets: 1000,
|
||||
};
|
||||
|
||||
test('returns the panel interval and timefield', () => {
|
||||
const panel = { time_field: '@timestamp', interval: 'auto' } as Panel;
|
||||
const series = {} as Series;
|
||||
|
||||
expect(getIntervalAndTimefield(panel, index, series)).toEqual({
|
||||
expect(getIntervalAndTimefield(panel, index, params, series)).toEqual({
|
||||
timeField: '@timestamp',
|
||||
interval: 'auto',
|
||||
});
|
||||
|
@ -30,7 +35,7 @@ describe('getIntervalAndTimefield(panel, series)', () => {
|
|||
series_time_field: 'time',
|
||||
} as unknown) as Series;
|
||||
|
||||
expect(getIntervalAndTimefield(panel, index, series)).toEqual({
|
||||
expect(getIntervalAndTimefield(panel, index, params, series)).toEqual({
|
||||
timeField: 'time',
|
||||
interval: '1m',
|
||||
});
|
||||
|
|
|
@ -5,13 +5,25 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import { AUTO_INTERVAL } from '../../../common/constants';
|
||||
import { validateField } from '../../../common/fields_utils';
|
||||
import { validateInterval } from '../../../common/validate_interval';
|
||||
|
||||
import type { FetchedIndexPattern, Panel, Series } from '../../../common/types';
|
||||
|
||||
export function getIntervalAndTimefield(panel: Panel, index: FetchedIndexPattern, series?: Series) {
|
||||
interface IntervalParams {
|
||||
min: string;
|
||||
max: string;
|
||||
maxBuckets: number;
|
||||
}
|
||||
|
||||
export function getIntervalAndTimefield(
|
||||
panel: Panel,
|
||||
index: FetchedIndexPattern,
|
||||
{ min, max, maxBuckets }: IntervalParams,
|
||||
series?: Series
|
||||
) {
|
||||
const timeField =
|
||||
(series?.override_index_pattern ? series.series_time_field : panel.time_field) ||
|
||||
index.indexPattern?.timeFieldName;
|
||||
|
@ -28,6 +40,15 @@ export function getIntervalAndTimefield(panel: Panel, index: FetchedIndexPattern
|
|||
maxBars = series.series_max_bars;
|
||||
}
|
||||
|
||||
validateInterval(
|
||||
{
|
||||
min: moment.utc(min),
|
||||
max: moment.utc(max),
|
||||
},
|
||||
interval,
|
||||
maxBuckets
|
||||
);
|
||||
|
||||
return {
|
||||
maxBars,
|
||||
timeField,
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
// not typed yet
|
||||
// @ts-expect-error
|
||||
import { handleErrorResponse } from './handle_error_response';
|
||||
import { getAnnotations } from './get_annotations';
|
||||
import { handleResponseBody } from './series/handle_response_body';
|
||||
|
@ -51,6 +49,8 @@ export async function getSeriesData(
|
|||
uiRestrictions: capabilities.uiRestrictions,
|
||||
};
|
||||
|
||||
const handleError = handleErrorResponse(panel);
|
||||
|
||||
try {
|
||||
const bodiesPromises = getActiveSeries(panel).map((series) =>
|
||||
getSeriesRequestParams(req, panel, panelIndex, series, capabilities, services)
|
||||
|
@ -97,14 +97,9 @@ export async function getSeriesData(
|
|||
},
|
||||
};
|
||||
} catch (err) {
|
||||
if (err.body) {
|
||||
err.response = err.body;
|
||||
|
||||
return {
|
||||
...meta,
|
||||
...handleErrorResponse(panel)(err),
|
||||
};
|
||||
}
|
||||
return meta;
|
||||
return {
|
||||
...meta,
|
||||
...handleError(err),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,20 +12,19 @@ import { get } from 'lodash';
|
|||
// not typed yet
|
||||
// @ts-expect-error
|
||||
import { buildRequestBody } from './table/build_request_body';
|
||||
// @ts-expect-error
|
||||
import { handleErrorResponse } from './handle_error_response';
|
||||
// @ts-expect-error
|
||||
import { processBucket } from './table/process_bucket';
|
||||
|
||||
import { createFieldsFetcher } from '../search_strategies/lib/fields_fetcher';
|
||||
import { extractFieldLabel } from '../../../common/fields_utils';
|
||||
|
||||
import type {
|
||||
VisTypeTimeseriesRequestHandlerContext,
|
||||
VisTypeTimeseriesRequestServices,
|
||||
VisTypeTimeseriesVisDataRequest,
|
||||
} from '../../types';
|
||||
import type { Panel } from '../../../common/types';
|
||||
import { getIntervalAndTimefield } from './get_interval_and_timefield';
|
||||
|
||||
export async function getTableData(
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext,
|
||||
|
@ -67,23 +66,13 @@ export async function getTableData(
|
|||
return panel.pivot_id;
|
||||
};
|
||||
|
||||
const buildSeriesMetaParams = async () => {
|
||||
let index = panelIndex;
|
||||
|
||||
/** This part of code is required to try to get the default timefield for string indices.
|
||||
* The rest of the functionality available for Kibana indexes should not be active **/
|
||||
if (!panel.use_kibana_indexes && index.indexPatternString) {
|
||||
index = await services.cachedIndexPatternFetcher(index.indexPatternString, true);
|
||||
}
|
||||
|
||||
return getIntervalAndTimefield(panel, index);
|
||||
};
|
||||
|
||||
const meta = {
|
||||
type: panel.type,
|
||||
uiRestrictions: capabilities.uiRestrictions,
|
||||
};
|
||||
|
||||
const handleError = handleErrorResponse(panel);
|
||||
|
||||
try {
|
||||
const body = await buildRequestBody(
|
||||
req,
|
||||
|
@ -92,7 +81,7 @@ export async function getTableData(
|
|||
panelIndex,
|
||||
capabilities,
|
||||
services.uiSettings,
|
||||
buildSeriesMetaParams
|
||||
() => services.buildSeriesMetaParams(panelIndex, Boolean(panel.use_kibana_indexes))
|
||||
);
|
||||
|
||||
const [resp] = await searchStrategy.search(requestContext, req, [
|
||||
|
@ -121,14 +110,9 @@ export async function getTableData(
|
|||
series,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err.body) {
|
||||
err.response = err.body;
|
||||
|
||||
return {
|
||||
...meta,
|
||||
...handleErrorResponse(panel)(err),
|
||||
};
|
||||
}
|
||||
return meta;
|
||||
return {
|
||||
...meta,
|
||||
...handleError(err),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const handleErrorResponse = (panel) => (error) => {
|
||||
if (error.isBoom && error.status === 401) throw error;
|
||||
const result = {};
|
||||
let errorResponse;
|
||||
try {
|
||||
errorResponse = JSON.parse(error.response);
|
||||
} catch (e) {
|
||||
errorResponse = error.response;
|
||||
}
|
||||
if (!errorResponse && !(error.name === 'KQLSyntaxError')) {
|
||||
errorResponse = {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
};
|
||||
}
|
||||
if (error.name === 'KQLSyntaxError') {
|
||||
errorResponse = {
|
||||
message: error.shortMessage,
|
||||
stack: error.stack,
|
||||
};
|
||||
}
|
||||
result[panel.id] = {
|
||||
id: panel.id,
|
||||
statusCode: error.statusCode,
|
||||
error: errorResponse,
|
||||
series: [],
|
||||
};
|
||||
return result;
|
||||
};
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Panel } from '../../../common/types';
|
||||
import { handleErrorResponse, ErrorResponse } from './handle_error_response';
|
||||
|
||||
describe('handleErrorResponse', () => {
|
||||
const handleError = handleErrorResponse(({
|
||||
id: 'test_panel',
|
||||
} as unknown) as Panel);
|
||||
|
||||
test('should only handle errors that contain errBody', () => {
|
||||
expect(handleError(new Error('Test Error'))).toMatchInlineSnapshot(`Object {}`);
|
||||
|
||||
expect(handleError({ errBody: 'test' } as ErrorResponse)).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"test_panel": Object {
|
||||
"error": "test",
|
||||
"id": "test_panel",
|
||||
"series": Array [],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('should set as error the last value of caused_by', () => {
|
||||
expect(
|
||||
handleError({
|
||||
errBody: {
|
||||
error: {
|
||||
reason: 'wrong 0',
|
||||
caused_by: {
|
||||
reason: 'wrong 1',
|
||||
caused_by: {
|
||||
caused_by: 'ok',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ErrorResponse)
|
||||
).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"test_panel": Object {
|
||||
"error": "ok",
|
||||
"id": "test_panel",
|
||||
"series": Array [],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('should use the previous error message if the actual value is empty', () => {
|
||||
expect(
|
||||
handleError({
|
||||
errBody: {
|
||||
error: {
|
||||
reason: 'ok',
|
||||
caused_by: {
|
||||
reason: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ErrorResponse)
|
||||
).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"test_panel": Object {
|
||||
"error": "ok",
|
||||
"id": "test_panel",
|
||||
"series": Array [],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('shouldn not return empty error message', () => {
|
||||
expect(
|
||||
handleError({
|
||||
errBody: {
|
||||
error: {
|
||||
reason: '',
|
||||
},
|
||||
},
|
||||
} as ErrorResponse)
|
||||
).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"test_panel": Object {
|
||||
"error": "Unexpected error",
|
||||
"id": "test_panel",
|
||||
"series": Array [],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { Panel } from '../../../common/types';
|
||||
|
||||
type ErrorType =
|
||||
| {
|
||||
reason: string;
|
||||
caused_by?: ErrorType;
|
||||
}
|
||||
| string;
|
||||
|
||||
export type ErrorResponse = Error &
|
||||
Partial<{
|
||||
errBody:
|
||||
| {
|
||||
error: ErrorType;
|
||||
}
|
||||
| string;
|
||||
}>;
|
||||
|
||||
const getErrorMessage = (errBody: ErrorType, defaultMessage?: string): string | undefined => {
|
||||
if (typeof errBody === 'string') {
|
||||
return errBody;
|
||||
} else {
|
||||
if (errBody.caused_by) {
|
||||
return getErrorMessage(errBody.caused_by, errBody.reason);
|
||||
}
|
||||
return errBody.reason || defaultMessage;
|
||||
}
|
||||
};
|
||||
|
||||
export const handleErrorResponse = (panel: Panel) => (error: ErrorResponse) => {
|
||||
const result: Record<string, unknown> = {};
|
||||
|
||||
if (error.errBody) {
|
||||
const errorResponse =
|
||||
typeof error.errBody === 'string' ? error.errBody : getErrorMessage(error.errBody.error);
|
||||
|
||||
result[panel.id] = {
|
||||
id: panel.id,
|
||||
error:
|
||||
errorResponse ??
|
||||
i18n.translate('visTypeTimeseries.handleErrorResponse.unexpectedError', {
|
||||
defaultMessage: 'Unexpected error',
|
||||
}),
|
||||
series: [],
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
|
@ -47,7 +47,16 @@ describe('dateHistogram(req, panel, series)', () => {
|
|||
get: async (key) => (key === UI_SETTINGS.HISTOGRAM_MAX_BARS ? 100 : 50),
|
||||
};
|
||||
buildSeriesMetaParams = jest.fn(async () => {
|
||||
return getIntervalAndTimefield(panel, indexPattern, series);
|
||||
return getIntervalAndTimefield(
|
||||
panel,
|
||||
indexPattern,
|
||||
{
|
||||
min: '2017-01-01T00:00:00Z',
|
||||
max: '2017-01-01T01:00:00Z',
|
||||
maxBuckets: 1000,
|
||||
},
|
||||
series
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import { buildRequestBody } from './build_request_body';
|
||||
import { getIntervalAndTimefield } from '../get_interval_and_timefield';
|
||||
|
||||
import type { FetchedIndexPattern, Panel, Series } from '../../../../common/types';
|
||||
import type {
|
||||
|
@ -27,6 +26,7 @@ export async function getSeriesRequestParams(
|
|||
esShardTimeout,
|
||||
uiSettings,
|
||||
cachedIndexPatternFetcher,
|
||||
buildSeriesMetaParams,
|
||||
}: VisTypeTimeseriesRequestServices
|
||||
) {
|
||||
let seriesIndex = panelIndex;
|
||||
|
@ -35,18 +35,6 @@ export async function getSeriesRequestParams(
|
|||
seriesIndex = await cachedIndexPatternFetcher(series.series_index_pattern ?? '');
|
||||
}
|
||||
|
||||
const buildSeriesMetaParams = async () => {
|
||||
let index = seriesIndex;
|
||||
|
||||
/** This part of code is required to try to get the default timefield for string indices.
|
||||
* The rest of the functionality available for Kibana indexes should not be active **/
|
||||
if (!panel.use_kibana_indexes && index.indexPatternString) {
|
||||
index = await cachedIndexPatternFetcher(index.indexPatternString, true);
|
||||
}
|
||||
|
||||
return getIntervalAndTimefield(panel, index, series);
|
||||
};
|
||||
|
||||
const request = await buildRequestBody(
|
||||
req,
|
||||
panel,
|
||||
|
@ -55,7 +43,7 @@ export async function getSeriesRequestParams(
|
|||
seriesIndex,
|
||||
capabilities,
|
||||
uiSettings,
|
||||
buildSeriesMetaParams
|
||||
() => buildSeriesMetaParams(seriesIndex, Boolean(panel.use_kibana_indexes), series)
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -6,17 +6,18 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { SharedGlobalConfig } from 'kibana/server';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { SharedGlobalConfig } from 'kibana/server';
|
||||
import type { IRouter, IUiSettingsClient, KibanaRequest } from 'src/core/server';
|
||||
import type {
|
||||
DataRequestHandlerContext,
|
||||
EsQueryConfig,
|
||||
IndexPatternsService,
|
||||
} from '../../data/server';
|
||||
import type { VisPayload } from '../common/types';
|
||||
import type { Series, VisPayload } from '../common/types';
|
||||
import type { SearchStrategyRegistry } from './lib/search_strategies';
|
||||
import type { CachedIndexPatternFetcher } from './lib/search_strategies/lib/cached_index_pattern_fetcher';
|
||||
import type { FetchedIndexPattern } from '../common/types';
|
||||
|
||||
export type ConfigObservable = Observable<SharedGlobalConfig>;
|
||||
|
||||
|
@ -35,4 +36,13 @@ export interface VisTypeTimeseriesRequestServices {
|
|||
indexPatternsService: IndexPatternsService;
|
||||
searchStrategyRegistry: SearchStrategyRegistry;
|
||||
cachedIndexPatternFetcher: CachedIndexPatternFetcher;
|
||||
buildSeriesMetaParams: (
|
||||
index: FetchedIndexPattern,
|
||||
useKibanaIndexes: boolean,
|
||||
series?: Series
|
||||
) => Promise<{
|
||||
maxBars: number;
|
||||
timeField?: string;
|
||||
interval: string;
|
||||
}>;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue