From 5c9af91664bc928ae4370f409f7335c282d8910c Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 27 Jan 2022 16:12:50 +0300 Subject: [PATCH 1/3] [TSVB] Fix shard failures are not reported (#123474) * [TSVB] Fix shard failures are not reported #122944 Closes: #122944 * fix PR comments * Update ui_settings.ts Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> (cherry picked from commit 7e1b7806724d611b734b6c19346c4077f65e5382) # Conflicts: # src/plugins/vis_types/timeseries/kibana.json # src/plugins/vis_types/timeseries/public/metrics_type.ts --- src/plugins/data/public/index.ts | 1 + src/plugins/data/public/search/index.ts | 1 + .../adapters/request/request_responder.ts | 2 +- .../common/adapters/request/types.ts | 1 + .../vis_types/timeseries/common/constants.ts | 1 + .../timeseries/common/types/index.ts | 10 +++- .../timeseries/common/types/vis_data.ts | 32 ++++++++----- src/plugins/vis_types/timeseries/kibana.json | 4 +- .../application/components/annotation_row.tsx | 4 +- .../field_text_select.tsx | 2 +- .../index_pattern_select.tsx | 2 +- .../vis_types/timeseries/public/metrics_fn.ts | 7 ++- .../timeseries/public/metrics_type.ts | 5 +- .../timeseries/public/request_handler.ts | 26 ++++++++-- .../server/lib/search_strategies/index.ts | 1 + .../abstract_search_strategy.test.ts | 6 +-- .../strategies/abstract_search_strategy.ts | 35 ++++++++++++-- .../strategies/rollup_search_strategy.ts | 9 ++-- .../annotations/get_request_params.ts | 15 ++++-- .../server/lib/vis_data/get_annotations.ts | 28 ++++++----- .../server/lib/vis_data/get_series_data.ts | 12 +++-- .../server/lib/vis_data/get_table_data.ts | 48 +++++++++++-------- .../lib/vis_data/series/get_request_params.ts | 15 ++++-- .../timeseries/server/ui_settings.ts | 14 ++++++ test/functional/apps/visualize/_tsvb_chart.ts | 4 +- .../metrics/kibana_metrics_adapter.ts | 4 +- 26 files changed, 209 insertions(+), 80 deletions(-) diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 0b749d90f7152..0b7bf32b92a25 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -203,6 +203,7 @@ export { isEsError, SearchSessionState, SortDirection, + handleResponse, } from './search'; export type { diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index 821f16e0cf68a..d963e08f8477b 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -52,6 +52,7 @@ export { waitUntilNextSessionCompletes$, } from './session'; export { getEsPreference } from './es_search'; +export { handleResponse } from './fetch'; export type { SearchInterceptorDeps } from './search_interceptor'; export { SearchInterceptor } from './search_interceptor'; diff --git a/src/plugins/inspector/common/adapters/request/request_responder.ts b/src/plugins/inspector/common/adapters/request/request_responder.ts index 1b8da2e57e7f2..1d3a999e4834d 100644 --- a/src/plugins/inspector/common/adapters/request/request_responder.ts +++ b/src/plugins/inspector/common/adapters/request/request_responder.ts @@ -51,7 +51,7 @@ export class RequestResponder { } public finish(status: RequestStatus, response: Response): void { - this.request.time = Date.now() - this.request.startTime; + this.request.time = response.time ?? Date.now() - this.request.startTime; this.request.status = status; this.request.response = response; this.onChange(); diff --git a/src/plugins/inspector/common/adapters/request/types.ts b/src/plugins/inspector/common/adapters/request/types.ts index a204a7aa00a4a..4e6a8d324559f 100644 --- a/src/plugins/inspector/common/adapters/request/types.ts +++ b/src/plugins/inspector/common/adapters/request/types.ts @@ -53,4 +53,5 @@ export interface RequestStatistic { export interface Response { json?: object; + time?: number; } diff --git a/src/plugins/vis_types/timeseries/common/constants.ts b/src/plugins/vis_types/timeseries/common/constants.ts index 4f15cea7faad3..30fb814990925 100644 --- a/src/plugins/vis_types/timeseries/common/constants.ts +++ b/src/plugins/vis_types/timeseries/common/constants.ts @@ -9,6 +9,7 @@ export const UI_SETTINGS = { MAX_BUCKETS_SETTING: 'metrics:max_buckets', ALLOW_STRING_INDICES: 'metrics:allowStringIndices', + ALLOW_CHECKING_FOR_FAILED_SHARDS: 'metrics:allowCheckingForFailedShards', }; export const INDEXES_SEPARATOR = ','; export const AUTO_INTERVAL = 'auto'; diff --git a/src/plugins/vis_types/timeseries/common/types/index.ts b/src/plugins/vis_types/timeseries/common/types/index.ts index 5e04fee0d015c..6266a4c2bc997 100644 --- a/src/plugins/vis_types/timeseries/common/types/index.ts +++ b/src/plugins/vis_types/timeseries/common/types/index.ts @@ -10,7 +10,15 @@ import { Filter, IndexPattern, Query } from '../../../../data/common'; import { Panel } from './panel_model'; export type { Metric, Series, Panel, MetricType } from './panel_model'; -export type { TimeseriesVisData, PanelData, SeriesData, TableData } from './vis_data'; +export type { + TimeseriesVisData, + PanelData, + SeriesData, + TableData, + DataResponseMeta, + TrackedEsSearches, + PanelSeries, +} from './vis_data'; export interface FetchedIndexPattern { indexPattern: IndexPattern | undefined | null; diff --git a/src/plugins/vis_types/timeseries/common/types/vis_data.ts b/src/plugins/vis_types/timeseries/common/types/vis_data.ts index 1a7be0b467004..07c078a6e8aae 100644 --- a/src/plugins/vis_types/timeseries/common/types/vis_data.ts +++ b/src/plugins/vis_types/timeseries/common/types/vis_data.ts @@ -7,30 +7,38 @@ */ import { PANEL_TYPES } from '../enums'; -import { TimeseriesUIRestrictions } from '../ui_restrictions'; +import type { TimeseriesUIRestrictions } from '../ui_restrictions'; export type TimeseriesVisData = SeriesData | TableData; -export interface TableData { - type: PANEL_TYPES.TABLE; +export type TrackedEsSearches = Record< + string, + { + body: Record; + label?: string; + time: number; + response?: Record; + } +>; + +export interface DataResponseMeta { + type: PANEL_TYPES; uiRestrictions: TimeseriesUIRestrictions; + trackedEsSearches: TrackedEsSearches; +} + +export interface TableData extends DataResponseMeta { series?: PanelData[]; pivot_label?: string; } // series data is not fully typed yet -export type SeriesData = { - type: Exclude; - uiRestrictions: TimeseriesUIRestrictions; +export type SeriesData = DataResponseMeta & { error?: string; -} & { - [key: string]: PanelSeries; -}; +} & Record; export interface PanelSeries { - annotations: { - [key: string]: Annotation[]; - }; + annotations: Record; id: string; series: PanelData[]; error?: string; diff --git a/src/plugins/vis_types/timeseries/kibana.json b/src/plugins/vis_types/timeseries/kibana.json index 5cc425e4edf71..bf6aa68dcc869 100644 --- a/src/plugins/vis_types/timeseries/kibana.json +++ b/src/plugins/vis_types/timeseries/kibana.json @@ -4,8 +4,8 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["charts", "data", "expressions", "visualizations", "visualize"], - "optionalPlugins": ["usageCollection"], + "requiredPlugins": ["charts", "data", "expressions", "visualizations", "visualize", "inspector"], + "optionalPlugins": ["home","usageCollection"], "requiredBundles": ["kibanaUtils", "kibanaReact", "fieldFormats"], "owner": { "name": "Vis Editors", diff --git a/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx b/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx index bc408aef7092a..856948cb7601e 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx @@ -80,7 +80,9 @@ export const AnnotationRow = ({ try { fetchedIndexPattern = index - ? await fetchIndexPattern(index, indexPatterns) + ? await fetchIndexPattern(index, indexPatterns, { + fetchKibanaIndexForStringIndexes: true, + }) : { ...fetchedIndexPattern, defaultIndex: await indexPatterns.getDefault(), diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index 86d1758932301..682279d5639e5 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -37,7 +37,7 @@ export const FieldTextSelect = ({ useDebounce( () => { - if (inputValue !== indexPatternString) { + if ((inputValue ?? '') !== (indexPatternString ?? '')) { onIndexChange(inputValue); } }, diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 840787e2af1af..6c095a9074bb7 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -111,7 +111,7 @@ export const IndexPatternSelect = ({ label={indexPatternLabel} helpText={fetchedIndex.defaultIndex && getIndexPatternHelpText(useKibanaIndices)} labelAppend={ - fetchedIndex.indexPatternString && !fetchedIndex.indexPattern ? ( + !useKibanaIndices && fetchedIndex.indexPatternString && !fetchedIndex.indexPattern ? ( ({ help: '', }, }, - async fn(input, args, { getSearchSessionId, isSyncColorsEnabled, getExecutionContext }) { + async fn( + input, + args, + { getSearchSessionId, isSyncColorsEnabled, getExecutionContext, inspectorAdapters } + ) { const visParams: TimeseriesVisParams = JSON.parse(args.params); const uiState = JSON.parse(args.uiState); const syncColors = isSyncColorsEnabled?.() ?? false; @@ -65,6 +69,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({ uiState, searchSessionId: getSearchSessionId(), executionContext: getExecutionContext(), + inspectorAdapters, }); return { diff --git a/src/plugins/vis_types/timeseries/public/metrics_type.ts b/src/plugins/vis_types/timeseries/public/metrics_type.ts index 30474758e2799..505f8f88d38fe 100644 --- a/src/plugins/vis_types/timeseries/public/metrics_type.ts +++ b/src/plugins/vis_types/timeseries/public/metrics_type.ts @@ -22,6 +22,7 @@ import { } from '../../../visualizations/public'; import { getDataStart } from './services'; import type { TimeseriesVisDefaultParams, TimeseriesVisParams } from './types'; +import { RequestAdapter } from '../../../inspector/public'; export const withReplacedIds = ( vis: Vis @@ -118,7 +119,9 @@ export const metricsVisDefinition: VisTypeDefinition< } return []; }, - inspectorAdapters: {}, + inspectorAdapters: () => ({ + requests: new RequestAdapter(), + }), requiresSearch: true, getUsedIndexPattern: async (params: VisParams) => { const { indexPatterns } = getDataStart(); diff --git a/src/plugins/vis_types/timeseries/public/request_handler.ts b/src/plugins/vis_types/timeseries/public/request_handler.ts index e9037c0b84a5e..bb15f32886cdc 100644 --- a/src/plugins/vis_types/timeseries/public/request_handler.ts +++ b/src/plugins/vis_types/timeseries/public/request_handler.ts @@ -6,13 +6,14 @@ * Side Public License, v 1. */ import type { KibanaExecutionContext } from 'src/core/public'; +import type { Adapters } from 'src/plugins/inspector'; import { getTimezone } from './application/lib/get_timezone'; import { getUISettings, getDataStart, getCoreStart } from './services'; -import { ROUTES } from '../common/constants'; +import { ROUTES, UI_SETTINGS } from '../common/constants'; +import { KibanaContext, handleResponse } from '../../../data/public'; import type { TimeseriesVisParams } from './types'; import type { TimeseriesVisData } from '../common/types'; -import type { KibanaContext } from '../../../data/public'; interface MetricsRequestHandlerParams { input: KibanaContext | null; @@ -20,6 +21,7 @@ interface MetricsRequestHandlerParams { visParams: TimeseriesVisParams; searchSessionId?: string; executionContext?: KibanaExecutionContext; + inspectorAdapters?: Adapters; } export const metricsRequestHandler = async ({ @@ -28,9 +30,11 @@ export const metricsRequestHandler = async ({ visParams, searchSessionId, executionContext, + inspectorAdapters, }: MetricsRequestHandlerParams): Promise => { const config = getUISettings(); const data = getDataStart(); + const theme = getCoreStart().theme; const timezone = getTimezone(config); const uiStateObj = uiState[visParams.type] ?? {}; @@ -48,7 +52,8 @@ export const metricsRequestHandler = async ({ try { const searchSessionOptions = dataSearch.session.getSearchOptions(searchSessionId); - return await getCoreStart().http.post(ROUTES.VIS_DATA, { + + const visData: TimeseriesVisData = await getCoreStart().http.post(ROUTES.VIS_DATA, { body: JSON.stringify({ timerange: { timezone, @@ -64,6 +69,21 @@ export const metricsRequestHandler = async ({ }), context: executionContext, }); + + inspectorAdapters?.requests?.reset(); + + Object.entries(visData.trackedEsSearches || {}).forEach(([key, query]) => { + inspectorAdapters?.requests + ?.start(query.label ?? key, { searchSessionId }) + .json(query.body) + .ok({ time: query.time }); + + if (query.response && config.get(UI_SETTINGS.ALLOW_CHECKING_FOR_FAILED_SHARDS)) { + handleResponse({ body: query.body }, { rawResponse: query.response }, theme); + } + }); + + return visData; } finally { if (untrackSearch && dataSearch.session.isCurrentSession(searchSessionId)) { // untrack if this search still belongs to current session diff --git a/src/plugins/vis_types/timeseries/server/lib/search_strategies/index.ts b/src/plugins/vis_types/timeseries/server/lib/search_strategies/index.ts index ca0c50a79564a..721e1dad473f0 100644 --- a/src/plugins/vis_types/timeseries/server/lib/search_strategies/index.ts +++ b/src/plugins/vis_types/timeseries/server/lib/search_strategies/index.ts @@ -11,6 +11,7 @@ import { AbstractSearchStrategy } from './strategies'; export { SearchStrategyRegistry } from './search_strategy_registry'; export { AbstractSearchStrategy, RollupSearchStrategy, DefaultSearchStrategy } from './strategies'; +export type { EsSearchRequest } from './strategies/abstract_search_strategy'; export type SearchCapabilities = DefaultSearchCapabilities; export type SearchStrategy = AbstractSearchStrategy; diff --git a/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts b/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts index 6216bce00fc7d..1a52132612f71 100644 --- a/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts +++ b/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts @@ -9,7 +9,7 @@ import { IndexPatternsService } from '../../../../../../data/common'; import { from } from 'rxjs'; -import { AbstractSearchStrategy } from './abstract_search_strategy'; +import { AbstractSearchStrategy, EsSearchRequest } from './abstract_search_strategy'; import type { FieldSpec } from '../../../../../../data/common'; import type { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; import type { @@ -64,7 +64,7 @@ describe('AbstractSearchStrategy', () => { }); test('should return response', async () => { - const searches = [{ body: 'body', index: 'index' }]; + const searches: EsSearchRequest[] = [{ body: {}, index: 'index' }]; const responses = await abstractSearchStrategy.search( requestContext, @@ -84,7 +84,7 @@ describe('AbstractSearchStrategy', () => { expect(requestContext.search.search).toHaveBeenCalledWith( { params: { - body: 'body', + body: {}, index: 'index', }, indexType: undefined, diff --git a/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index bce07d2cdb300..1d3650ccedbd3 100644 --- a/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -6,40 +6,67 @@ * Side Public License, v 1. */ +import { tap } from 'rxjs/operators'; +import { omit } from 'lodash'; import { IndexPatternsService } from '../../../../../../data/server'; import { toSanitizedFieldType } from '../../../../common/fields_utils'; -import type { FetchedIndexPattern } from '../../../../common/types'; +import type { FetchedIndexPattern, TrackedEsSearches } from '../../../../common/types'; import type { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; +export interface EsSearchRequest { + body: Record; + index?: string; + trackingEsSearchMeta?: { + requestId: string; + requestLabel?: string; + }; +} + export abstract class AbstractSearchStrategy { async search( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesVisDataRequest, - bodies: any[], + esRequests: EsSearchRequest[], + trackedEsSearches?: TrackedEsSearches, indexType?: string ) { const requests: any[] = []; - bodies.forEach((body) => { + esRequests.forEach(({ body, index, trackingEsSearchMeta }) => { + const startTime = Date.now(); requests.push( requestContext.search .search( { indexType, params: { - ...body, + body, + index, }, }, req.body.searchSession ) + .pipe( + tap((data) => { + if (trackingEsSearchMeta?.requestId && trackedEsSearches) { + trackedEsSearches[trackingEsSearchMeta.requestId] = { + body, + time: Date.now() - startTime, + label: trackingEsSearchMeta.requestLabel, + response: omit(data.rawResponse, 'aggregations'), + }; + } + }) + ) .toPromise() ); }); + return Promise.all(requests); } diff --git a/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts b/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts index e3ede57774224..2508c68066017 100644 --- a/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts +++ b/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts @@ -10,10 +10,10 @@ import { getCapabilitiesForRollupIndices, IndexPatternsService, } from '../../../../../../data/server'; -import { AbstractSearchStrategy } from './abstract_search_strategy'; +import { AbstractSearchStrategy, EsSearchRequest } from './abstract_search_strategy'; import { RollupSearchCapabilities } from '../capabilities/rollup_search_capabilities'; -import type { FetchedIndexPattern } from '../../../../common/types'; +import type { FetchedIndexPattern, TrackedEsSearches } from '../../../../common/types'; import type { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; import type { VisTypeTimeseriesRequest, @@ -29,9 +29,10 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { async search( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesVisDataRequest, - bodies: any[] + esRequests: EsSearchRequest[], + trackedEsSearches?: TrackedEsSearches ) { - return super.search(requestContext, req, bodies, 'rollup'); + return super.search(requestContext, req, esRequests, trackedEsSearches, 'rollup'); } async getRollupData( diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/annotations/get_request_params.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/annotations/get_request_params.ts index 1973e3b85b966..41f7e7c86708f 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/annotations/get_request_params.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/annotations/get_request_params.ts @@ -5,7 +5,7 @@ * 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 { Annotation, Panel } from '../../../../common/types'; import { buildAnnotationRequest } from './build_request_body'; import type { @@ -13,7 +13,7 @@ import type { VisTypeTimeseriesRequestServices, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import type { SearchStrategy, SearchCapabilities } from '../../search_strategies'; +import type { SearchStrategy, SearchCapabilities, EsSearchRequest } from '../../search_strategies'; export type AnnotationServices = VisTypeTimeseriesRequestServices & { capabilities: SearchCapabilities; @@ -32,7 +32,7 @@ export async function getAnnotationRequestParams( uiSettings, cachedIndexPatternFetcher, }: AnnotationServices -) { +): Promise { const annotationIndex = await cachedIndexPatternFetcher(annotation.index_pattern); const request = await buildAnnotationRequest({ @@ -52,5 +52,14 @@ export async function getAnnotationRequestParams( runtime_mappings: annotationIndex.indexPattern?.getComputedFields().runtimeFields ?? {}, timeout: esShardTimeout > 0 ? `${esShardTimeout}ms` : undefined, }, + trackingEsSearchMeta: { + requestId: annotation.id, + requestLabel: i18n.translate('visTypeTimeseries.annotationRequest.label', { + defaultMessage: 'Annotation: {id}', + values: { + id: annotation.id, + }, + }), + }, }; } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_annotations.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_annotations.ts index 8a005deccaea9..481ddc7891817 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_annotations.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_annotations.ts @@ -10,8 +10,7 @@ import { handleAnnotationResponse } from './response_processors/annotations'; import { AnnotationServices, getAnnotationRequestParams } from './annotations/get_request_params'; import { getLastSeriesTimestamp } from './helpers/timestamp'; import type { VisTypeTimeseriesVisDataRequest } from '../../types'; -import type { Annotation, Panel } from '../../../common/types'; -import type { PanelSeries } from '../../../common/types/vis_data'; +import type { Annotation, Panel, TrackedEsSearches, PanelSeries } from '../../../common/types'; function validAnnotation(annotation: Annotation) { return annotation.fields && annotation.icon && annotation.template && !annotation.hidden; @@ -22,26 +21,33 @@ interface GetAnnotationsParams { panel: Panel; series: Array; services: AnnotationServices; + trackedEsSearches: TrackedEsSearches; } -export async function getAnnotations({ req, panel, series, services }: GetAnnotationsParams) { +export async function getAnnotations({ + req, + panel, + series, + services, + trackedEsSearches, +}: GetAnnotationsParams) { const annotations = panel.annotations!.filter(validAnnotation); const lastSeriesTimestamp = getLastSeriesTimestamp(series); const handleAnnotationResponseBy = handleAnnotationResponse(lastSeriesTimestamp); - const bodiesPromises = annotations.map((annotation) => - getAnnotationRequestParams(req, panel, annotation, services) - ); - - const searches = (await Promise.all(bodiesPromises)).reduce( - (acc, items) => acc.concat(items as any), - [] + const searches = await Promise.all( + annotations.map((annotation) => getAnnotationRequestParams(req, panel, annotation, services)) ); if (!searches.length) return { responses: [] }; try { - const data = await services.searchStrategy.search(services.requestContext, req, searches); + const data = await services.searchStrategy.search( + services.requestContext, + req, + searches, + trackedEsSearches + ); return annotations.reduce((acc, annotation, index) => { acc[annotation.id] = handleAnnotationResponseBy(data[index].rawResponse, annotation); diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_series_data.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_series_data.ts index 757aaf560de43..c321ace7c9c25 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_series_data.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_series_data.ts @@ -20,7 +20,7 @@ import type { VisTypeTimeseriesVisDataRequest, VisTypeTimeseriesRequestServices, } from '../../types'; -import type { Panel } from '../../../common/types'; +import type { Panel, DataResponseMeta } from '../../../common/types'; import { PANEL_TYPES } from '../../../common/enums'; export async function getSeriesData( @@ -52,13 +52,14 @@ export async function getSeriesData( } const { searchStrategy, capabilities } = strategy; - const meta = { + const handleError = handleErrorResponse(panel); + + const meta: DataResponseMeta = { type: panel.type, uiRestrictions: capabilities.uiRestrictions, + trackedEsSearches: {}, }; - const handleError = handleErrorResponse(panel); - try { const bodiesPromises = getActiveSeries(panel).map((series) => { if (isEntireTimeRangeMode(panel, series)) { @@ -83,7 +84,7 @@ export async function getSeriesData( ); const searches = await Promise.all(bodiesPromises); - const data = await searchStrategy.search(requestContext, req, searches); + const data = await searchStrategy.search(requestContext, req, searches, meta.trackedEsSearches); const series = await Promise.all( data.map( @@ -104,6 +105,7 @@ export async function getSeriesData( searchStrategy, capabilities, }, + trackedEsSearches: meta.trackedEsSearches, }); } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts index d23820045990d..c6c28e8a9df19 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts @@ -23,7 +23,8 @@ import type { VisTypeTimeseriesRequestServices, VisTypeTimeseriesVisDataRequest, } from '../../types'; -import type { Panel } from '../../../common/types'; +import type { Panel, DataResponseMeta } from '../../../common/types'; +import type { EsSearchRequest } from '../search_strategies'; export async function getTableData( requestContext: VisTypeTimeseriesRequestHandlerContext, @@ -68,11 +69,11 @@ export async function getTableData( return panel.pivot_id; }; - const meta = { + const meta: DataResponseMeta = { type: panel.type, uiRestrictions: capabilities.uiRestrictions, + trackedEsSearches: {}, }; - const handleError = handleErrorResponse(panel); try { @@ -82,29 +83,38 @@ export async function getTableData( }); } - const body = await buildTableRequest({ - req, - panel, - esQueryConfig: services.esQueryConfig, - seriesIndex: panelIndex, - capabilities, - uiSettings: services.uiSettings, - buildSeriesMetaParams: () => - services.buildSeriesMetaParams(panelIndex, Boolean(panel.use_kibana_indexes)), - }); - - const [resp] = await searchStrategy.search(requestContext, req, [ + const searches: EsSearchRequest[] = [ { + index: panelIndex.indexPatternString, body: { - ...body, + ...(await buildTableRequest({ + req, + panel, + esQueryConfig: services.esQueryConfig, + seriesIndex: panelIndex, + capabilities, + uiSettings: services.uiSettings, + buildSeriesMetaParams: () => + services.buildSeriesMetaParams(panelIndex, Boolean(panel.use_kibana_indexes)), + })), runtime_mappings: panelIndex.indexPattern?.getComputedFields().runtimeFields ?? {}, }, - index: panelIndex.indexPatternString, + trackingEsSearchMeta: { + requestId: panel.id, + requestLabel: i18n.translate('visTypeTimeseries.tableRequest.label', { + defaultMessage: 'Table: {id}', + values: { + id: panel.id, + }, + }), + }, }, - ]); + ]; + + const data = await searchStrategy.search(requestContext, req, searches, meta.trackedEsSearches); const buckets = get( - resp.rawResponse ? resp.rawResponse : resp, + data[0].rawResponse ? data[0].rawResponse : data[0], 'aggregations.pivot.buckets', [] ); diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/series/get_request_params.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/series/get_request_params.ts index 046b207050ca0..d176eb8b99392 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/series/get_request_params.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/series/get_request_params.ts @@ -5,7 +5,7 @@ * 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 { buildRequestBody } from './build_request_body'; import type { FetchedIndexPattern, Panel, Series } from '../../../../common/types'; @@ -13,7 +13,7 @@ import type { VisTypeTimeseriesRequestServices, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import type { SearchCapabilities } from '../../search_strategies'; +import type { SearchCapabilities, EsSearchRequest } from '../../search_strategies'; export async function getSeriesRequestParams( req: VisTypeTimeseriesVisDataRequest, @@ -28,7 +28,7 @@ export async function getSeriesRequestParams( cachedIndexPatternFetcher, buildSeriesMetaParams, }: VisTypeTimeseriesRequestServices -) { +): Promise { let seriesIndex = panelIndex; if (series.override_index_pattern) { @@ -53,5 +53,14 @@ export async function getSeriesRequestParams( runtime_mappings: seriesIndex.indexPattern?.getComputedFields().runtimeFields ?? {}, timeout: esShardTimeout > 0 ? `${esShardTimeout}ms` : undefined, }, + trackingEsSearchMeta: { + requestId: series.id, + requestLabel: i18n.translate('visTypeTimeseries.seriesRequest.label', { + defaultMessage: 'Series: {id}', + values: { + id: series.id, + }, + }), + }, }; } diff --git a/src/plugins/vis_types/timeseries/server/ui_settings.ts b/src/plugins/vis_types/timeseries/server/ui_settings.ts index 2adbc31482f04..c64d5771479b6 100644 --- a/src/plugins/vis_types/timeseries/server/ui_settings.ts +++ b/src/plugins/vis_types/timeseries/server/ui_settings.ts @@ -36,4 +36,18 @@ export const getUiSettings: () => Record = () => ({ }), schema: schema.boolean(), }, + [UI_SETTINGS.ALLOW_CHECKING_FOR_FAILED_SHARDS]: { + name: i18n.translate('visTypeTimeseries.advancedSettings.allowCheckingForFailedShardsTitle', { + defaultMessage: 'Show TSVB request shard failures', + }), + value: true, + description: i18n.translate( + 'visTypeTimeseries.advancedSettings.allowCheckingForFailedShardsText', + { + defaultMessage: + 'Show warning message for partial data in TSVB charts if the request succeeds for some shards but fails for others.', + } + ), + schema: schema.boolean(), + }, }); diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index bbe40d6e2d7d5..d29d43312052d 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -52,8 +52,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await visualBuilder.clickDataTab('metric'); }); - it('should not have inspector enabled', async () => { - await inspector.expectIsNotEnabled(); + it('should have inspector enabled', async () => { + await inspector.expectIsEnabled(); }); it('should show correct data', async () => { diff --git a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts index e05a5b647ad2b..2a87c9cbca994 100644 --- a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts @@ -6,8 +6,8 @@ */ import { i18n } from '@kbn/i18n'; -import { flatten, get } from 'lodash'; import { KibanaRequest } from 'src/core/server'; +import { flatten, get } from 'lodash'; import { TIMESTAMP_FIELD } from '../../../../common/constants'; import { NodeDetailsMetricData } from '../../../../common/http_api/node_details_api'; import { KibanaFramework } from '../framework/kibana_framework_adapter'; @@ -63,7 +63,7 @@ export class KibanaMetricsAdapter implements InfraMetricsAdapter { .then((results) => { return results.filter(isVisSeriesData).map((result) => { const metricIds = Object.keys(result).filter( - (k) => !['type', 'uiRestrictions'].includes(k) + (k) => !['type', 'uiRestrictions', 'trackedEsSearches'].includes(k) ); return metricIds.map((id: string) => { From be538e72dfb3895bf6fb19c2dd6b8be3183aacd2 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 9 Feb 2022 10:24:01 +0100 Subject: [PATCH 2/3] fix --- src/plugins/vis_types/timeseries/public/request_handler.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/vis_types/timeseries/public/request_handler.ts b/src/plugins/vis_types/timeseries/public/request_handler.ts index bb15f32886cdc..ffb7a13a3400a 100644 --- a/src/plugins/vis_types/timeseries/public/request_handler.ts +++ b/src/plugins/vis_types/timeseries/public/request_handler.ts @@ -34,7 +34,6 @@ export const metricsRequestHandler = async ({ }: MetricsRequestHandlerParams): Promise => { const config = getUISettings(); const data = getDataStart(); - const theme = getCoreStart().theme; const timezone = getTimezone(config); const uiStateObj = uiState[visParams.type] ?? {}; @@ -79,7 +78,7 @@ export const metricsRequestHandler = async ({ .ok({ time: query.time }); if (query.response && config.get(UI_SETTINGS.ALLOW_CHECKING_FOR_FAILED_SHARDS)) { - handleResponse({ body: query.body }, { rawResponse: query.response }, theme); + handleResponse({ body: query.body }, { rawResponse: query.response }); } }); From 9af7ebdcf3054fd5d75e0d8741fbca5f4ca11c63 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 9 Feb 2022 14:42:17 +0100 Subject: [PATCH 3/3] fix telemetry --- .../server/collectors/management/schema.ts | 4 ++++ .../server/collectors/management/types.ts | 1 + src/plugins/telemetry/schema/oss_plugins.json | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index 356aaf60b423c..66dae4b5f8413 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -284,6 +284,10 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'metrics:allowCheckingForFailedShards': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, 'query:allowLeadingWildcards': { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 69287d37dfa28..fbf595528eeb0 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -94,6 +94,7 @@ export interface UsageStats { 'savedObjects:listingLimit': number; 'query:queryString:options': string; 'metrics:max_buckets': number; + 'metrics:allowCheckingForFailedShards': boolean; 'metrics:allowStringIndices': boolean; 'query:allowLeadingWildcards': boolean; metaFields: string[]; diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index a3f61bf49c372..6a5b1349a1666 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -7577,6 +7577,12 @@ "description": "Non-default value of setting." } }, + "metrics:allowCheckingForFailedShards": { + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } + }, "query:allowLeadingWildcards": { "type": "boolean", "_meta": {