From 107227797481286bac7f92dd8ff74dedcc881474 Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Thu, 9 Jan 2025 09:08:54 +0000 Subject: [PATCH] Remove unused code --- .../logs_shared/common/http_api/index.ts | 1 - .../logs_shared/common/http_api/latest.ts | 1 - .../http_api/log_entries/v1/highlights.ts | 70 ------ .../common/http_api/log_entries/v1/index.ts | 10 - .../common/http_api/log_entries/v1/summary.ts | 39 ---- .../log_entries/v1/summary_highlights.ts | 47 ---- .../shared/logs_shared/common/index.ts | 13 -- .../logs_shared/common/time/time_key.ts | 24 +- .../api/fetch_log_entries_highlights.ts | 30 --- .../api/fetch_log_summary_highlights.ts | 29 --- .../containers/logs/log_highlights/index.ts | 8 - .../log_highlights/log_entry_highlights.tsx | 104 --------- .../logs/log_highlights/log_highlights.tsx | 93 -------- .../log_highlights/log_summary_highlights.ts | 93 -------- .../logs/log_highlights/next_and_previous.tsx | 105 --------- .../logs/log_summary/api/fetch_log_summary.ts | 29 --- .../logs/log_summary/bucket_size.ts | 24 -- .../containers/logs/log_summary/index.ts | 9 - .../logs/log_summary/log_summary.test.tsx | 215 ------------------ .../logs/log_summary/log_summary.tsx | 74 ------ .../logs/log_summary/with_summary.ts | 43 ---- .../shared/logs_shared/public/index.ts | 6 - .../public/utils/log_entry/log_entry.ts | 23 -- .../logs_shared/public/utils/typed_react.tsx | 11 - .../public/utils/use_observable.ts | 25 +- .../log_entries/kibana_log_entries_adapter.ts | 148 ------------ .../log_entries_domain.mock.ts | 3 - .../log_entries_domain/log_entries_domain.ts | 214 ----------------- .../logs_shared/server/logs_shared_server.ts | 9 +- .../server/routes/log_entries/highlights.ts | 118 ---------- .../server/routes/log_entries/index.ts | 10 - .../server/routes/log_entries/summary.ts | 88 ------- .../routes/log_entries/summary_highlights.ts | 83 ------- .../plugins/infra/common/time/time_key.ts | 24 +- .../infra/public/hooks/use_observable.ts | 18 +- .../apis/logs_ui/log_entry_highlights.ts | 213 ----------------- .../apis/logs_ui/log_summary.ts | 79 ------- 37 files changed, 5 insertions(+), 2128 deletions(-) delete mode 100644 x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/highlights.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/index.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary_highlights.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_entries_highlights.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_summary_highlights.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/index.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_entry_highlights.tsx delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_highlights.tsx delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_summary_highlights.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/next_and_previous.tsx delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/api/fetch_log_summary.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/bucket_size.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/index.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.tsx delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/with_summary.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/public/utils/typed_react.tsx delete mode 100644 x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/highlights.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/index.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary.ts delete mode 100644 x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary_highlights.ts delete mode 100644 x-pack/test/api_integration/apis/logs_ui/log_entry_highlights.ts delete mode 100644 x-pack/test/api_integration/apis/logs_ui/log_summary.ts diff --git a/x-pack/platform/plugins/shared/logs_shared/common/http_api/index.ts b/x-pack/platform/plugins/shared/logs_shared/common/http_api/index.ts index 939f72786183b..25de1a66b6de6 100644 --- a/x-pack/platform/plugins/shared/logs_shared/common/http_api/index.ts +++ b/x-pack/platform/plugins/shared/logs_shared/common/http_api/index.ts @@ -9,5 +9,4 @@ * Exporting versioned APIs types */ export * from './latest'; -export * as logEntriesV1 from './log_entries/v1'; export * as logViewsV1 from './log_views/v1'; diff --git a/x-pack/platform/plugins/shared/logs_shared/common/http_api/latest.ts b/x-pack/platform/plugins/shared/logs_shared/common/http_api/latest.ts index 63f58bf4f92c0..84ece561371f6 100644 --- a/x-pack/platform/plugins/shared/logs_shared/common/http_api/latest.ts +++ b/x-pack/platform/plugins/shared/logs_shared/common/http_api/latest.ts @@ -5,5 +5,4 @@ * 2.0. */ -export * from './log_entries/v1'; export * from './log_views/v1'; diff --git a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/highlights.ts b/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/highlights.ts deleted file mode 100644 index f879ca3f87961..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/highlights.ts +++ /dev/null @@ -1,70 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as rt from 'io-ts'; -import { logEntryCursorRT, logEntryRT } from '../../../log_entry'; -import { logViewColumnConfigurationRT } from '../../../log_views'; -import { logViewReferenceRT } from '../../../log_views'; - -export const LOG_ENTRIES_HIGHLIGHTS_PATH = '/api/log_entries/highlights'; - -export const logEntriesHighlightsBaseRequestRT = rt.intersection([ - rt.type({ - logView: logViewReferenceRT, - startTimestamp: rt.number, - endTimestamp: rt.number, - highlightTerms: rt.array(rt.string), - }), - rt.partial({ - query: rt.union([rt.string, rt.null]), - size: rt.number, - columns: rt.array(logViewColumnConfigurationRT), - }), -]); - -export const logEntriesHighlightsBeforeRequestRT = rt.intersection([ - logEntriesHighlightsBaseRequestRT, - rt.type({ before: rt.union([logEntryCursorRT, rt.literal('last')]) }), -]); - -export const logEntriesHighlightsAfterRequestRT = rt.intersection([ - logEntriesHighlightsBaseRequestRT, - rt.type({ after: rt.union([logEntryCursorRT, rt.literal('first')]) }), -]); - -export const logEntriesHighlightsCenteredRequestRT = rt.intersection([ - logEntriesHighlightsBaseRequestRT, - rt.type({ center: logEntryCursorRT }), -]); - -export const logEntriesHighlightsRequestRT = rt.union([ - logEntriesHighlightsBaseRequestRT, - logEntriesHighlightsBeforeRequestRT, - logEntriesHighlightsAfterRequestRT, - logEntriesHighlightsCenteredRequestRT, -]); - -export type LogEntriesHighlightsRequest = rt.TypeOf; - -export const logEntriesHighlightsResponseRT = rt.type({ - data: rt.array( - rt.union([ - rt.type({ - topCursor: rt.null, - bottomCursor: rt.null, - entries: rt.array(logEntryRT), - }), - rt.type({ - topCursor: logEntryCursorRT, - bottomCursor: logEntryCursorRT, - entries: rt.array(logEntryRT), - }), - ]) - ), -}); - -export type LogEntriesHighlightsResponse = rt.TypeOf; diff --git a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/index.ts b/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/index.ts deleted file mode 100644 index 83d240ca8f273..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/index.ts +++ /dev/null @@ -1,10 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './highlights'; -export * from './summary'; -export * from './summary_highlights'; diff --git a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary.ts b/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary.ts deleted file mode 100644 index 318ff44b296c0..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary.ts +++ /dev/null @@ -1,39 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as rt from 'io-ts'; -import { logViewReferenceRT } from '../../../log_views'; - -export const LOG_ENTRIES_SUMMARY_PATH = '/api/log_entries/summary'; - -export const logEntriesSummaryRequestRT = rt.type({ - logView: logViewReferenceRT, - startTimestamp: rt.number, - endTimestamp: rt.number, - bucketSize: rt.number, - query: rt.union([rt.string, rt.undefined, rt.null]), -}); - -export type LogEntriesSummaryRequest = rt.TypeOf; - -export const logEntriesSummaryBucketRT = rt.type({ - start: rt.number, - end: rt.number, - entriesCount: rt.number, -}); - -export type LogEntriesSummaryBucket = rt.TypeOf; - -export const logEntriesSummaryResponseRT = rt.type({ - data: rt.type({ - start: rt.number, - end: rt.number, - buckets: rt.array(logEntriesSummaryBucketRT), - }), -}); - -export type LogEntriesSummaryResponse = rt.TypeOf; diff --git a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary_highlights.ts b/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary_highlights.ts deleted file mode 100644 index f12bc72fc12f5..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/common/http_api/log_entries/v1/summary_highlights.ts +++ /dev/null @@ -1,47 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as rt from 'io-ts'; -import { logEntryCursorRT } from '../../../log_entry'; -import { logEntriesSummaryRequestRT, logEntriesSummaryBucketRT } from './summary'; - -export const LOG_ENTRIES_SUMMARY_HIGHLIGHTS_PATH = '/api/log_entries/summary_highlights'; - -export const logEntriesSummaryHighlightsRequestRT = rt.intersection([ - logEntriesSummaryRequestRT, - rt.type({ - highlightTerms: rt.array(rt.string), - }), -]); - -export type LogEntriesSummaryHighlightsRequest = rt.TypeOf< - typeof logEntriesSummaryHighlightsRequestRT ->; - -export const logEntriesSummaryHighlightsBucketRT = rt.intersection([ - logEntriesSummaryBucketRT, - rt.type({ - representativeKey: logEntryCursorRT, - }), -]); - -export type LogEntriesSummaryHighlightsBucket = rt.TypeOf< - typeof logEntriesSummaryHighlightsBucketRT ->; - -export const logEntriesSummaryHighlightsResponseRT = rt.type({ - data: rt.array( - rt.type({ - start: rt.number, - end: rt.number, - buckets: rt.array(logEntriesSummaryHighlightsBucketRT), - }) - ), -}); -export type LogEntriesSummaryHighlightsResponse = rt.TypeOf< - typeof logEntriesSummaryHighlightsResponseRT ->; diff --git a/x-pack/platform/plugins/shared/logs_shared/common/index.ts b/x-pack/platform/plugins/shared/logs_shared/common/index.ts index d5287460b5de8..fab9fa213790d 100644 --- a/x-pack/platform/plugins/shared/logs_shared/common/index.ts +++ b/x-pack/platform/plugins/shared/logs_shared/common/index.ts @@ -47,19 +47,6 @@ export * from './log_entry'; export { convertISODateToNanoPrecision } from './utils'; -// Http types -export type { LogEntriesSummaryBucket, LogEntriesSummaryHighlightsBucket } from './http_api'; - -// Http runtime -export { - LOG_ENTRIES_HIGHLIGHTS_PATH, - LOG_ENTRIES_SUMMARY_PATH, - logEntriesHighlightsRequestRT, - logEntriesHighlightsResponseRT, - logEntriesSummaryRequestRT, - logEntriesSummaryResponseRT, -} from './http_api'; - // Locators export { type LogsLocatorParams, diff --git a/x-pack/platform/plugins/shared/logs_shared/common/time/time_key.ts b/x-pack/platform/plugins/shared/logs_shared/common/time/time_key.ts index 1ff661af69d0a..fa56f74590828 100644 --- a/x-pack/platform/plugins/shared/logs_shared/common/time/time_key.ts +++ b/x-pack/platform/plugins/shared/logs_shared/common/time/time_key.ts @@ -6,7 +6,7 @@ */ import type { TimeKey } from '@kbn/io-ts-utils'; -import { ascending, bisector } from 'd3-array'; +import { ascending } from 'd3-array'; export type Comparator = (firstValue: any, secondValue: any) => number; @@ -38,25 +38,3 @@ export const compareToTimeKey = (keyAccessor: (value: Value) => TimeKey, compareValues?: Comparator) => (value: Value, key: TimeKey) => compareTimeKeys(keyAccessor(value), key, compareValues); - -export const getIndexAtTimeKey = ( - keyAccessor: (value: Value) => TimeKey, - compareValues?: Comparator -) => { - const comparator = compareToTimeKey(keyAccessor, compareValues); - const collectionBisector = bisector(comparator); - - return (collection: Value[], key: TimeKey): number | null => { - const index = collectionBisector.left(collection, key); - - if (index >= collection.length) { - return null; - } - - if (comparator(collection[index], key) !== 0) { - return null; - } - - return index; - }; -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_entries_highlights.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_entries_highlights.ts deleted file mode 100644 index 91f418f943247..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_entries_highlights.ts +++ /dev/null @@ -1,30 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { HttpHandler } from '@kbn/core/public'; - -import { decodeOrThrow } from '../../../../../common/runtime_types'; - -import { - LOG_ENTRIES_HIGHLIGHTS_PATH, - LogEntriesHighlightsRequest, - logEntriesHighlightsRequestRT, - logEntriesHighlightsResponseRT, -} from '../../../../../common/http_api'; - -export const fetchLogEntriesHighlights = async ( - requestArgs: LogEntriesHighlightsRequest, - fetch: HttpHandler -) => { - const response = await fetch(LOG_ENTRIES_HIGHLIGHTS_PATH, { - method: 'POST', - body: JSON.stringify(logEntriesHighlightsRequestRT.encode(requestArgs)), - version: '1', - }); - - return decodeOrThrow(logEntriesHighlightsResponseRT)(response); -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_summary_highlights.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_summary_highlights.ts deleted file mode 100644 index 8753926fceb8d..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/api/fetch_log_summary_highlights.ts +++ /dev/null @@ -1,29 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { HttpHandler } from '@kbn/core/public'; -import { decodeOrThrow } from '../../../../../common/runtime_types'; - -import { - LOG_ENTRIES_SUMMARY_HIGHLIGHTS_PATH, - LogEntriesSummaryHighlightsRequest, - logEntriesSummaryHighlightsRequestRT, - logEntriesSummaryHighlightsResponseRT, -} from '../../../../../common/http_api'; - -export const fetchLogSummaryHighlights = async ( - requestArgs: LogEntriesSummaryHighlightsRequest, - fetch: HttpHandler -) => { - const response = await fetch(LOG_ENTRIES_SUMMARY_HIGHLIGHTS_PATH, { - method: 'POST', - body: JSON.stringify(logEntriesSummaryHighlightsRequestRT.encode(requestArgs)), - version: '1', - }); - - return decodeOrThrow(logEntriesSummaryHighlightsResponseRT)(response); -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/index.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/index.ts deleted file mode 100644 index e448689aa281f..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/index.ts +++ /dev/null @@ -1,8 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './log_highlights'; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_entry_highlights.tsx b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_entry_highlights.tsx deleted file mode 100644 index 117a78d619596..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_entry_highlights.tsx +++ /dev/null @@ -1,104 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { TimeKey } from '@kbn/io-ts-utils'; -import { useEffect, useMemo, useState } from 'react'; -import { LogViewReference } from '../../../../common'; -import { LogEntriesHighlightsResponse } from '../../../../common/http_api'; -import { LogEntry } from '../../../../common/log_entry'; -import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; -import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { fetchLogEntriesHighlights } from './api/fetch_log_entries_highlights'; - -export const useLogEntryHighlights = ( - logViewReference: LogViewReference, - sourceVersion: string | undefined, - startTimestamp: number | null, - endTimestamp: number | null, - centerPoint: TimeKey | null, - size: number, - filterQuery: string | null, - highlightTerms: string[] -) => { - const { services } = useKibanaContextForPlugin(); - const [logEntryHighlights, setLogEntryHighlights] = useState< - LogEntriesHighlightsResponse['data'] - >([]); - const [loadLogEntryHighlightsRequest, loadLogEntryHighlights] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - if (!startTimestamp || !endTimestamp || !centerPoint || !highlightTerms.length) { - throw new Error('Skipping request: Insufficient parameters'); - } - - return await fetchLogEntriesHighlights( - { - logView: logViewReference, - startTimestamp, - endTimestamp, - center: centerPoint, - size, - query: filterQuery || undefined, - highlightTerms, - }, - services.http.fetch - ); - }, - onResolve: (response) => { - setLogEntryHighlights(response.data); - }, - }, - [logViewReference, startTimestamp, endTimestamp, centerPoint, size, filterQuery, highlightTerms] - ); - - useEffect(() => { - setLogEntryHighlights([]); - }, [highlightTerms]); - - useEffect(() => { - if ( - highlightTerms.filter((highlightTerm) => highlightTerm.length > 0).length && - startTimestamp && - endTimestamp - ) { - loadLogEntryHighlights(); - } else { - setLogEntryHighlights([]); - } - }, [ - endTimestamp, - filterQuery, - highlightTerms, - loadLogEntryHighlights, - sourceVersion, - startTimestamp, - ]); - - const logEntryHighlightsById = useMemo( - () => - logEntryHighlights.reduce>( - (accumulatedLogEntryHighlightsById, highlightData) => { - return highlightData.entries.reduce((singleHighlightLogEntriesById, entry) => { - const highlightsForId = singleHighlightLogEntriesById[entry.id] || []; - return { - ...singleHighlightLogEntriesById, - [entry.id]: [...highlightsForId, entry], - }; - }, accumulatedLogEntryHighlightsById); - }, - {} - ), - [logEntryHighlights] - ); - - return { - logEntryHighlights, - logEntryHighlightsById, - loadLogEntryHighlightsRequest, - }; -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_highlights.tsx b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_highlights.tsx deleted file mode 100644 index 3317f02d034d3..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_highlights.tsx +++ /dev/null @@ -1,93 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import createContainer from 'constate'; -import { useState } from 'react'; -import useThrottle from 'react-use/lib/useThrottle'; -import { TimeKey } from '@kbn/io-ts-utils'; -import { LogViewReference } from '../../../../common'; -import { useLogEntryHighlights } from './log_entry_highlights'; -import { useLogSummaryHighlights } from './log_summary_highlights'; -import { useNextAndPrevious } from './next_and_previous'; -import { useLogPositionStateContext } from '../log_position'; - -const FETCH_THROTTLE_INTERVAL = 3000; - -interface UseLogHighlightsStateProps { - logViewReference: LogViewReference; - sourceVersion: string | undefined; - centerCursor: TimeKey | null; - size: number; - filterQuery: string | null; -} - -const useLogHighlightsState = ({ - logViewReference, - sourceVersion, - centerCursor, - size, - filterQuery, -}: UseLogHighlightsStateProps) => { - const [highlightTerms, setHighlightTerms] = useState([]); - const { visibleMidpoint, jumpToTargetPosition, startTimestamp, endTimestamp } = - useLogPositionStateContext(); - - const throttledStartTimestamp = useThrottle(startTimestamp, FETCH_THROTTLE_INTERVAL); - const throttledEndTimestamp = useThrottle(endTimestamp, FETCH_THROTTLE_INTERVAL); - - const { logEntryHighlights, logEntryHighlightsById, loadLogEntryHighlightsRequest } = - useLogEntryHighlights( - logViewReference, - sourceVersion, - throttledStartTimestamp, - throttledEndTimestamp, - centerCursor, - size, - filterQuery, - highlightTerms - ); - - const { logSummaryHighlights, loadLogSummaryHighlightsRequest } = useLogSummaryHighlights( - logViewReference, - sourceVersion, - throttledStartTimestamp, - throttledEndTimestamp, - filterQuery, - highlightTerms - ); - - const { - currentHighlightKey, - hasPreviousHighlight, - hasNextHighlight, - goToPreviousHighlight, - goToNextHighlight, - } = useNextAndPrevious({ - visibleMidpoint, - logEntryHighlights, - highlightTerms, - jumpToTargetPosition, - }); - - return { - highlightTerms, - setHighlightTerms, - logEntryHighlights, - logEntryHighlightsById, - logSummaryHighlights, - loadLogEntryHighlightsRequest, - loadLogSummaryHighlightsRequest, - currentHighlightKey, - hasPreviousHighlight, - hasNextHighlight, - goToPreviousHighlight, - goToNextHighlight, - }; -}; - -export const [LogHighlightsStateProvider, useLogHighlightsStateContext] = - createContainer(useLogHighlightsState); diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_summary_highlights.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_summary_highlights.ts deleted file mode 100644 index 61a1a02618e7a..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/log_summary_highlights.ts +++ /dev/null @@ -1,93 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useEffect, useMemo, useState } from 'react'; -import { debounce } from 'lodash'; - -import { LogViewReference } from '../../../../common'; -import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { fetchLogSummaryHighlights } from './api/fetch_log_summary_highlights'; -import { LogEntriesSummaryHighlightsResponse } from '../../../../common/http_api'; -import { useBucketSize } from '../log_summary/bucket_size'; -import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; - -export const useLogSummaryHighlights = ( - logViewReference: LogViewReference, - sourceVersion: string | undefined, - startTimestamp: number | null, - endTimestamp: number | null, - filterQuery: string | null, - highlightTerms: string[] -) => { - const { services } = useKibanaContextForPlugin(); - const [logSummaryHighlights, setLogSummaryHighlights] = useState< - LogEntriesSummaryHighlightsResponse['data'] - >([]); - - const bucketSize = useBucketSize(startTimestamp, endTimestamp); - - const [loadLogSummaryHighlightsRequest, loadLogSummaryHighlights] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - if (!startTimestamp || !endTimestamp || !bucketSize || !highlightTerms.length) { - throw new Error('Skipping request: Insufficient parameters'); - } - - return await fetchLogSummaryHighlights( - { - logView: logViewReference, - startTimestamp, - endTimestamp, - bucketSize, - query: filterQuery, - highlightTerms, - }, - services.http.fetch - ); - }, - onResolve: (response) => { - setLogSummaryHighlights(response.data); - }, - }, - [logViewReference, startTimestamp, endTimestamp, bucketSize, filterQuery, highlightTerms] - ); - - const debouncedLoadSummaryHighlights = useMemo( - () => debounce(loadLogSummaryHighlights, 275), - [loadLogSummaryHighlights] - ); - - useEffect(() => { - setLogSummaryHighlights([]); - }, [highlightTerms]); - - useEffect(() => { - if ( - highlightTerms.filter((highlightTerm) => highlightTerm.length > 0).length && - startTimestamp && - endTimestamp - ) { - debouncedLoadSummaryHighlights(); - } else { - setLogSummaryHighlights([]); - } - }, [ - bucketSize, - debouncedLoadSummaryHighlights, - filterQuery, - highlightTerms, - sourceVersion, - startTimestamp, - endTimestamp, - ]); - - return { - logSummaryHighlights, - loadLogSummaryHighlightsRequest, - }; -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/next_and_previous.tsx b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/next_and_previous.tsx deleted file mode 100644 index c76d66711b928..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_highlights/next_and_previous.tsx +++ /dev/null @@ -1,105 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { isNumber } from 'lodash'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { TimeKey, UniqueTimeKey } from '@kbn/io-ts-utils'; -import { - getLogEntryIndexAtTime, - getLogEntryIndexBeforeTime, - getUniqueLogEntryKey, -} from '../../../utils/log_entry'; -import { LogEntriesHighlightsResponse } from '../../../../common/http_api'; - -export const useNextAndPrevious = ({ - highlightTerms, - jumpToTargetPosition, - logEntryHighlights, - visibleMidpoint, -}: { - highlightTerms: string[]; - jumpToTargetPosition: (target: TimeKey) => void; - logEntryHighlights: LogEntriesHighlightsResponse['data'] | undefined; - visibleMidpoint: TimeKey | null; -}) => { - const [currentTimeKey, setCurrentTimeKey] = useState(null); - - const entries = useMemo( - // simplification, because we only support one highlight phrase for now - () => - logEntryHighlights && logEntryHighlights.length > 0 ? logEntryHighlights[0].entries : [], - [logEntryHighlights] - ); - - useEffect(() => { - setCurrentTimeKey(null); - }, [highlightTerms]); - - useEffect(() => { - if (currentTimeKey) { - jumpToTargetPosition(currentTimeKey); - } - }, [currentTimeKey, jumpToTargetPosition]); - - useEffect(() => { - if (currentTimeKey === null && entries.length > 0) { - const initialIndex = visibleMidpoint - ? clampValue(getLogEntryIndexBeforeTime(entries, visibleMidpoint), 0, entries.length - 1) - : 0; - const initialTimeKey = getUniqueLogEntryKey(entries[initialIndex]); - setCurrentTimeKey(initialTimeKey); - } - }, [currentTimeKey, entries, setCurrentTimeKey, visibleMidpoint]); - - const indexOfCurrentTimeKey = useMemo(() => { - if (currentTimeKey && entries.length > 0) { - return getLogEntryIndexAtTime(entries, currentTimeKey); - } else { - return null; - } - }, [currentTimeKey, entries]); - - const hasPreviousHighlight = useMemo( - () => isNumber(indexOfCurrentTimeKey) && indexOfCurrentTimeKey > 0, - [indexOfCurrentTimeKey] - ); - - const hasNextHighlight = useMemo( - () => - entries.length > 0 && - isNumber(indexOfCurrentTimeKey) && - indexOfCurrentTimeKey < entries.length - 1, - [indexOfCurrentTimeKey, entries] - ); - - const goToPreviousHighlight = useCallback(() => { - if (entries.length && isNumber(indexOfCurrentTimeKey)) { - const previousIndex = indexOfCurrentTimeKey - 1; - const entryTimeKey = getUniqueLogEntryKey(entries[previousIndex]); - setCurrentTimeKey(entryTimeKey); - } - }, [indexOfCurrentTimeKey, entries]); - - const goToNextHighlight = useCallback(() => { - if (entries.length > 0 && isNumber(indexOfCurrentTimeKey)) { - const nextIndex = indexOfCurrentTimeKey + 1; - const entryTimeKey = getUniqueLogEntryKey(entries[nextIndex]); - setCurrentTimeKey(entryTimeKey); - } - }, [indexOfCurrentTimeKey, entries]); - - return { - currentHighlightKey: currentTimeKey, - hasPreviousHighlight, - hasNextHighlight, - goToPreviousHighlight, - goToNextHighlight, - }; -}; - -const clampValue = (value: number, minValue: number, maxValue: number) => - Math.min(Math.max(value, minValue), maxValue); diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/api/fetch_log_summary.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/api/fetch_log_summary.ts deleted file mode 100644 index 5d89b50e6eaae..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/api/fetch_log_summary.ts +++ /dev/null @@ -1,29 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { HttpHandler } from '@kbn/core/public'; -import { decodeOrThrow } from '../../../../../common/runtime_types'; - -import { - LOG_ENTRIES_SUMMARY_PATH, - LogEntriesSummaryRequest, - logEntriesSummaryRequestRT, - logEntriesSummaryResponseRT, -} from '../../../../../common/http_api'; - -export const fetchLogSummary = async ( - requestArgs: LogEntriesSummaryRequest, - fetch: HttpHandler -) => { - const response = await fetch(LOG_ENTRIES_SUMMARY_PATH, { - method: 'POST', - body: JSON.stringify(logEntriesSummaryRequestRT.encode(requestArgs)), - version: '1', - }); - - return decodeOrThrow(logEntriesSummaryResponseRT)(response); -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/bucket_size.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/bucket_size.ts deleted file mode 100644 index ad048d2f8082e..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/bucket_size.ts +++ /dev/null @@ -1,24 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; - -const SUMMARY_BUCKET_COUNT = 100; - -export function useBucketSize( - startTimestamp: number | null, - endTimestamp: number | null -): number | null { - const bucketSize = useMemo(() => { - if (!startTimestamp || !endTimestamp) { - return null; - } - return (endTimestamp - startTimestamp) / SUMMARY_BUCKET_COUNT; - }, [startTimestamp, endTimestamp]); - - return bucketSize; -} diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/index.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/index.ts deleted file mode 100644 index 935bda868e23b..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/index.ts +++ /dev/null @@ -1,9 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './log_summary'; -export * from './with_summary'; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx deleted file mode 100644 index 8635df14731a5..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx +++ /dev/null @@ -1,215 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { waitFor, renderHook } from '@testing-library/react'; -// We are using this inside a `jest.mock` call. Jest requires dynamic dependencies to be prefixed with `mock` -import { coreMock as mockCoreMock } from '@kbn/core/public/mocks'; - -import { useLogSummary } from './log_summary'; - -import { fetchLogSummary } from './api/fetch_log_summary'; -import { datemathToEpochMillis } from '../../../utils/datemath'; - -const LOG_VIEW_REFERENCE = { type: 'log-view-reference' as const, logViewId: 'LOG_VIEW_ID' }; -const CHANGED_LOG_VIEW_REFERENCE = { - type: 'log-view-reference' as const, - logViewId: 'CHANGED_LOG_VIEW_ID', -}; - -// Typescript doesn't know that `fetchLogSummary` is a jest mock. -// We use a second variable with a type cast to help the compiler further down the line. -jest.mock('./api/fetch_log_summary', () => ({ fetchLogSummary: jest.fn() })); -const fetchLogSummaryMock = fetchLogSummary as jest.MockedFunction; - -jest.mock('../../../hooks/use_kibana', () => { - const services = mockCoreMock.createStart(); - return { - useKibanaContextForPlugin: () => ({ services }), - }; -}); - -describe('useLogSummary hook', () => { - beforeEach(() => { - fetchLogSummaryMock.mockClear(); - }); - - it('provides an empty list of buckets by default', () => { - const { result } = renderHook(() => useLogSummary(LOG_VIEW_REFERENCE, null, null, null)); - expect(result.current.buckets).toEqual([]); - }); - - it('queries for new summary buckets when the source id changes', async () => { - const { startTimestamp, endTimestamp } = createMockDateRange(); - - const firstMockResponse = createMockResponse([ - { start: startTimestamp, end: endTimestamp, entriesCount: 1 }, - ]); - const secondMockResponse = createMockResponse([ - { start: startTimestamp, end: endTimestamp, entriesCount: 2 }, - ]); - - fetchLogSummaryMock - .mockResolvedValueOnce(firstMockResponse) - .mockResolvedValueOnce(secondMockResponse); - - const { result, rerender } = renderHook( - ({ logViewReference }) => useLogSummary(logViewReference, startTimestamp, endTimestamp, null), - { - initialProps: { logViewReference: LOG_VIEW_REFERENCE }, - } - ); - - await waitFor(() => new Promise((resolve) => resolve(null))); - - expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); - expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( - expect.objectContaining({ - logView: LOG_VIEW_REFERENCE, - }), - expect.anything() - ); - expect(result.current.buckets).toEqual(firstMockResponse.data.buckets); - - rerender({ logViewReference: CHANGED_LOG_VIEW_REFERENCE }); - await waitFor(() => new Promise((resolve) => resolve(null))); - - expect(fetchLogSummaryMock).toHaveBeenCalledTimes(2); - expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( - expect.objectContaining({ - logView: CHANGED_LOG_VIEW_REFERENCE, - }), - expect.anything() - ); - expect(result.current.buckets).toEqual(secondMockResponse.data.buckets); - }); - - it('queries for new summary buckets when the filter query changes', async () => { - const { startTimestamp, endTimestamp } = createMockDateRange(); - - const firstMockResponse = createMockResponse([ - { start: startTimestamp, end: endTimestamp, entriesCount: 1 }, - ]); - const secondMockResponse = createMockResponse([ - { start: startTimestamp, end: endTimestamp, entriesCount: 2 }, - ]); - - fetchLogSummaryMock - .mockResolvedValueOnce(firstMockResponse) - .mockResolvedValueOnce(secondMockResponse); - - const { result, rerender } = renderHook( - ({ filterQuery }) => - useLogSummary(LOG_VIEW_REFERENCE, startTimestamp, endTimestamp, filterQuery), - { - initialProps: { filterQuery: 'INITIAL_FILTER_QUERY' }, - } - ); - - await waitFor(() => new Promise((resolve) => resolve(null))); - - expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); - expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( - expect.objectContaining({ - query: 'INITIAL_FILTER_QUERY', - }), - expect.anything() - ); - expect(result.current.buckets).toEqual(firstMockResponse.data.buckets); - - rerender({ filterQuery: 'CHANGED_FILTER_QUERY' }); - await waitFor(() => new Promise((resolve) => resolve(null))); - - expect(fetchLogSummaryMock).toHaveBeenCalledTimes(2); - expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( - expect.objectContaining({ - query: 'CHANGED_FILTER_QUERY', - }), - expect.anything() - ); - expect(result.current.buckets).toEqual(secondMockResponse.data.buckets); - }); - - it('queries for new summary buckets when the start and end date changes', async () => { - fetchLogSummaryMock - .mockResolvedValueOnce(createMockResponse([])) - .mockResolvedValueOnce(createMockResponse([])); - - const firstRange = createMockDateRange(); - const { rerender } = renderHook( - ({ startTimestamp, endTimestamp }) => - useLogSummary(LOG_VIEW_REFERENCE, startTimestamp, endTimestamp, null), - { - initialProps: firstRange, - } - ); - - await waitFor(() => new Promise((resolve) => resolve(null))); - expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); - expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( - expect.objectContaining({ - startTimestamp: firstRange.startTimestamp, - endTimestamp: firstRange.endTimestamp, - }), - expect.anything() - ); - - const secondRange = createMockDateRange('now-20s', 'now'); - - rerender(secondRange); - await waitFor(() => new Promise((resolve) => resolve(null))); - - expect(fetchLogSummaryMock).toHaveBeenCalledTimes(2); - expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( - expect.objectContaining({ - startTimestamp: secondRange.startTimestamp, - endTimestamp: secondRange.endTimestamp, - }), - expect.anything() - ); - }); - - it("doesn't query for new summary buckets when the previous request is still in flight", async () => { - fetchLogSummaryMock.mockResolvedValueOnce(createMockResponse([])); - - const firstRange = createMockDateRange(); - const { rerender } = renderHook( - ({ startTimestamp, endTimestamp }) => - useLogSummary(LOG_VIEW_REFERENCE, startTimestamp, endTimestamp, null), - { - initialProps: firstRange, - } - ); - - const secondRange = createMockDateRange('now-20s', 'now'); - - // intentionally don't wait for an update to test the throttling - rerender(secondRange); - await waitFor(() => new Promise((resolve) => resolve(null))); - - expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); - expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( - expect.objectContaining({ - startTimestamp: firstRange.startTimestamp, - endTimestamp: firstRange.endTimestamp, - }), - expect.anything() - ); - }); -}); - -const createMockResponse = ( - buckets: Array<{ start: number; end: number; entriesCount: number }> -) => ({ data: { buckets, start: Number.NEGATIVE_INFINITY, end: Number.POSITIVE_INFINITY } }); - -const createMockDateRange = (startDate = 'now-10s', endDate = 'now') => { - return { - startDate, - endDate, - startTimestamp: datemathToEpochMillis(startDate)!, - endTimestamp: datemathToEpochMillis(endDate, 'up')!, - }; -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.tsx b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.tsx deleted file mode 100644 index 0360d6d381ada..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/log_summary.tsx +++ /dev/null @@ -1,74 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useEffect } from 'react'; -import { exhaustMap, map, Observable } from 'rxjs'; -import { HttpHandler } from '@kbn/core-http-browser'; -import { LogViewReference } from '../../../../common'; -import { useObservableState, useReplaySubject } from '../../../utils/use_observable'; -import { fetchLogSummary } from './api/fetch_log_summary'; -import { LogEntriesSummaryRequest, LogEntriesSummaryResponse } from '../../../../common/http_api'; -import { useBucketSize } from './bucket_size'; -import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; - -export type LogSummaryBuckets = LogEntriesSummaryResponse['data']['buckets']; - -export const useLogSummary = ( - logViewReference: LogViewReference, - startTimestamp: number | null, - endTimestamp: number | null, - filterQuery: string | null -) => { - const { services } = useKibanaContextForPlugin(); - const bucketSize = useBucketSize(startTimestamp, endTimestamp); - - const [logSummaryBuckets$, pushLogSummaryBucketsArgs] = useReplaySubject(fetchLogSummary$); - const { latestValue: logSummaryBuckets } = useObservableState(logSummaryBuckets$, NO_BUCKETS); - - useEffect(() => { - if (startTimestamp === null || endTimestamp === null || bucketSize === null) { - return; - } - - pushLogSummaryBucketsArgs([ - { - logView: logViewReference, - startTimestamp, - endTimestamp, - bucketSize, - query: filterQuery, - }, - services.http.fetch, - ]); - }, [ - bucketSize, - endTimestamp, - filterQuery, - pushLogSummaryBucketsArgs, - services.http.fetch, - logViewReference, - startTimestamp, - ]); - - return { - buckets: logSummaryBuckets, - start: startTimestamp, - end: endTimestamp, - }; -}; - -const NO_BUCKETS: LogSummaryBuckets = []; - -type FetchLogSummaryArgs = [args: LogEntriesSummaryRequest, fetch: HttpHandler]; - -const fetchLogSummary$ = ( - fetchArguments$: Observable -): Observable => - fetchArguments$.pipe( - exhaustMap(([args, fetch]) => fetchLogSummary(args, fetch)), - map(({ data: { buckets } }) => buckets) - ); diff --git a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/with_summary.ts b/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/with_summary.ts deleted file mode 100644 index bb8fe69d4356e..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/containers/logs/log_summary/with_summary.ts +++ /dev/null @@ -1,43 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import useThrottle from 'react-use/lib/useThrottle'; -import { useLogPositionStateContext, useLogViewContext } from '../../..'; -import { RendererFunction } from '../../../utils/typed_react'; -import { LogSummaryBuckets, useLogSummary } from './log_summary'; - -const FETCH_THROTTLE_INTERVAL = 3000; - -export interface WithSummaryProps { - serializedParsedQuery: string | null; - children: RendererFunction<{ - buckets: LogSummaryBuckets; - start: number | null; - end: number | null; - }>; -} - -export const WithSummary = ({ serializedParsedQuery, children }: WithSummaryProps) => { - const { logViewReference } = useLogViewContext(); - const { startTimestamp, endTimestamp } = useLogPositionStateContext(); - - // Keep it reasonably updated for the `now` case, but don't reload all the time when the user scrolls - const throttledStartTimestamp = useThrottle(startTimestamp, FETCH_THROTTLE_INTERVAL); - const throttledEndTimestamp = useThrottle(endTimestamp, FETCH_THROTTLE_INTERVAL); - - const { buckets, start, end } = useLogSummary( - logViewReference, - throttledStartTimestamp, - throttledEndTimestamp, - serializedParsedQuery - ); - - return children({ buckets, start, end }); -}; - -// eslint-disable-next-line import/no-default-export -export default WithSummary; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/index.ts b/x-pack/platform/plugins/shared/logs_shared/public/index.ts index 3d601c9936f2d..be05abd06a69e 100644 --- a/x-pack/platform/plugins/shared/logs_shared/public/index.ts +++ b/x-pack/platform/plugins/shared/logs_shared/public/index.ts @@ -28,11 +28,6 @@ export { LogPositionStateProvider, useLogPositionStateContext, } from './containers/logs/log_position'; -export { - LogHighlightsStateProvider, - useLogHighlightsStateContext, -} from './containers/logs/log_highlights'; -export type { LogSummaryBuckets, WithSummaryProps } from './containers/logs/log_summary'; // Shared components export type { LogAIAssistantDocument } from './components/log_ai_assistant/log_ai_assistant'; @@ -52,7 +47,6 @@ export type { } from './components/logging/log_text_stream/scrollable_log_text_stream_view'; export type { LogsOverviewProps } from './components/logs_overview'; -export const WithSummary = dynamic(() => import('./containers/logs/log_summary/with_summary')); export const LogEntryFlyout = dynamic( () => import('./components/logging/log_entry_flyout/log_entry_flyout') ); diff --git a/x-pack/platform/plugins/shared/logs_shared/public/utils/log_entry/log_entry.ts b/x-pack/platform/plugins/shared/logs_shared/public/utils/log_entry/log_entry.ts index e1027aeeb5799..fa49d3ba27a6b 100644 --- a/x-pack/platform/plugins/shared/logs_shared/public/utils/log_entry/log_entry.ts +++ b/x-pack/platform/plugins/shared/logs_shared/public/utils/log_entry/log_entry.ts @@ -5,11 +5,7 @@ * 2.0. */ -import type { TimeKey, UniqueTimeKey } from '@kbn/io-ts-utils'; -import { bisector } from 'd3-array'; -import { compareToTimeKey, getIndexAtTimeKey } from '../../../common/time'; import { - LogEntry, LogColumn, LogTimestampColumn, LogFieldColumn, @@ -19,25 +15,6 @@ import { LogMessageConstantPart, } from '../../../common/log_entry'; -export const getLogEntryKey = (entry: { cursor: TimeKey }) => entry.cursor; - -export const getUniqueLogEntryKey = (entry: { id: string; cursor: TimeKey }): UniqueTimeKey => ({ - ...entry.cursor, - gid: entry.id, -}); - -const logEntryTimeBisector = bisector(compareToTimeKey(getLogEntryKey)); - -export const getLogEntryIndexBeforeTime = logEntryTimeBisector.left; -export const getLogEntryIndexAfterTime = logEntryTimeBisector.right; -export const getLogEntryIndexAtTime = getIndexAtTimeKey(getLogEntryKey); - -export const getLogEntryAtTime = (entries: LogEntry[], time: TimeKey) => { - const entryIndex = getLogEntryIndexAtTime(entries, time); - - return entryIndex !== null ? entries[entryIndex] : null; -}; - export const isTimestampColumn = (column: LogColumn): column is LogTimestampColumn => column != null && 'time' in column; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/utils/typed_react.tsx b/x-pack/platform/plugins/shared/logs_shared/public/utils/typed_react.tsx deleted file mode 100644 index 664894e1bf05c..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/public/utils/typed_react.tsx +++ /dev/null @@ -1,11 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -export type RendererResult = React.ReactElement | null; -export type RendererFunction = (args: RenderArgs) => Result; diff --git a/x-pack/platform/plugins/shared/logs_shared/public/utils/use_observable.ts b/x-pack/platform/plugins/shared/logs_shared/public/utils/use_observable.ts index 2634a156be986..2899d9f50b764 100644 --- a/x-pack/platform/plugins/shared/logs_shared/public/utils/use_observable.ts +++ b/x-pack/platform/plugins/shared/logs_shared/public/utils/use_observable.ts @@ -6,14 +6,7 @@ */ import { useEffect, useRef, useState } from 'react'; -import { - BehaviorSubject, - Observable, - OperatorFunction, - PartialObserver, - ReplaySubject, - Subscription, -} from 'rxjs'; +import { BehaviorSubject, Observable, OperatorFunction, PartialObserver, Subscription } from 'rxjs'; import { switchMap } from 'rxjs'; export const useLatest = (value: Value) => { @@ -58,22 +51,6 @@ export const useBehaviorSubject = < return [output$, next] as const; }; -export const useReplaySubject = < - InputValue, - OutputValue, - OutputObservable extends Observable ->( - deriveObservableOnce: (input$: Observable) => OutputObservable -) => { - const [[subject$, next], _] = useState(() => { - const newSubject$ = new ReplaySubject(); - const newNext = newSubject$.next.bind(newSubject$); - return [newSubject$, newNext] as const; - }); - const [output$] = useState(() => deriveObservableOnce(subject$)); - return [output$, next] as const; -}; - export const useObservableState = ( state$: Observable, initialState: InitialState | (() => InitialState) diff --git a/x-pack/platform/plugins/shared/logs_shared/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts b/x-pack/platform/plugins/shared/logs_shared/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts index f8102e8f0dffa..9760eab9687b9 100644 --- a/x-pack/platform/plugins/shared/logs_shared/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts +++ b/x-pack/platform/plugins/shared/logs_shared/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts @@ -5,11 +5,6 @@ * 2.0. */ -import { timeMilliseconds } from 'd3-time'; -import { fold, map } from 'fp-ts/lib/Either'; -import { constant, identity } from 'fp-ts/lib/function'; -import { pipe } from 'fp-ts/lib/pipeable'; -import * as runtimeTypes from 'io-ts'; import { JsonArray } from '@kbn/utility-types'; import { compact } from 'lodash'; import type { LogsSharedPluginRequestHandlerContext } from '../../../types'; @@ -18,7 +13,6 @@ import { LogEntriesParams, LogEntryDocument, LogEntryQuery, - LogSummaryBucket, LOG_ENTRIES_PAGE_SIZE, } from '../../domains/log_entries_domain'; import { SortedSearchHit } from '../framework'; @@ -28,21 +22,6 @@ import { TIMESTAMP_FIELD, TIEBREAKER_FIELD } from '../../../../common/constants' const TIMESTAMP_FORMAT = 'epoch_millis'; -const MAX_BUCKETS = 1000; - -function getBucketIntervalStarts( - startTimestamp: number, - endTimestamp: number, - bucketSize: number -): Date[] { - // estimated number of buckets - const bucketCount = Math.ceil((endTimestamp - startTimestamp) / bucketSize); - if (bucketCount > MAX_BUCKETS) { - throw new Error(`Requested too many buckets: ${bucketCount} > ${MAX_BUCKETS}`); - } - return timeMilliseconds(new Date(startTimestamp), new Date(endTimestamp), bucketSize); -} - export class LogsSharedKibanaLogEntriesAdapter implements LogEntriesAdapter { constructor(private readonly framework: KibanaFramework) {} @@ -140,86 +119,6 @@ export class LogsSharedKibanaLogEntriesAdapter implements LogEntriesAdapter { hasMoreAfter: sortDirection === 'asc' ? hasMore : undefined, }; } - - public async getContainedLogSummaryBuckets( - requestContext: LogsSharedPluginRequestHandlerContext, - resolvedLogView: ResolvedLogView, - startTimestamp: number, - endTimestamp: number, - bucketSize: number, - filterQuery?: LogEntryQuery - ): Promise { - const bucketIntervalStarts = getBucketIntervalStarts(startTimestamp, endTimestamp, bucketSize); - - const query = { - allow_no_indices: true, - index: resolvedLogView.indices, - ignore_unavailable: true, - body: { - aggregations: { - count_by_date: { - date_range: { - field: TIMESTAMP_FIELD, - format: TIMESTAMP_FORMAT, - ranges: bucketIntervalStarts.map((bucketIntervalStart) => ({ - from: bucketIntervalStart.getTime(), - to: bucketIntervalStart.getTime() + bucketSize, - })), - }, - aggregations: { - top_hits_by_key: { - top_hits: { - size: 1, - sort: [ - { - [TIMESTAMP_FIELD]: { - order: 'asc', - format: 'strict_date_optional_time_nanos', - numeric_type: 'date_nanos', - }, - }, - { [TIEBREAKER_FIELD]: 'asc' }, - ], - _source: false, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - ...createQueryFilterClauses(filterQuery), - { - range: { - [TIMESTAMP_FIELD]: { - gte: startTimestamp, - lte: endTimestamp, - format: TIMESTAMP_FORMAT, - }, - }, - }, - ], - }, - }, - runtime_mappings: resolvedLogView.runtimeMappings, - size: 0, - track_total_hits: false, - }, - }; - - const response = await this.framework.callWithRequest(requestContext, 'search', query); - - return pipe( - LogSummaryResponseRuntimeType.decode(response), - map((logSummaryResponse) => - logSummaryResponse.aggregations.count_by_date.buckets.map( - convertDateRangeBucketToSummaryBucket - ) - ), - fold(constant([]), identity) - ); - } } function mapHitsToLogEntryDocuments(hits: SortedSearchHit[], fields: string[]): LogEntryDocument[] { @@ -245,18 +144,6 @@ function mapHitsToLogEntryDocuments(hits: SortedSearchHit[], fields: string[]): }); } -const convertDateRangeBucketToSummaryBucket = ( - bucket: LogSummaryDateRangeBucket -): LogSummaryBucket => ({ - entriesCount: bucket.doc_count, - start: bucket.from || 0, - end: bucket.to || 0, - topEntryKeys: bucket.top_hits_by_key.hits.hits.map((hit) => ({ - tiebreaker: hit.sort[1], - time: hit.sort[0], - })), -}); - const createHighlightQuery = ( highlightTerm: string | undefined, fields: string[] @@ -284,9 +171,6 @@ const createFilterClauses = ( return compact([filterQuery, highlightQuery]) as LogEntryQuery[]; }; -const createQueryFilterClauses = (filterQuery: LogEntryQuery | undefined) => - filterQuery ? [filterQuery] : []; - function processCursor(cursor: LogEntriesParams['cursor']): { sortDirection: 'asc' | 'desc'; searchAfterClause: { search_after?: readonly [string, number] }; @@ -310,35 +194,3 @@ function processCursor(cursor: LogEntriesParams['cursor']): { return { sortDirection: 'asc', searchAfterClause: {} }; } - -const LogSummaryDateRangeBucketRuntimeType = runtimeTypes.intersection([ - runtimeTypes.type({ - doc_count: runtimeTypes.number, - key: runtimeTypes.string, - top_hits_by_key: runtimeTypes.type({ - hits: runtimeTypes.type({ - hits: runtimeTypes.array( - runtimeTypes.type({ - sort: runtimeTypes.tuple([runtimeTypes.string, runtimeTypes.number]), - }) - ), - }), - }), - }), - runtimeTypes.partial({ - from: runtimeTypes.number, - to: runtimeTypes.number, - }), -]); - -export type LogSummaryDateRangeBucket = runtimeTypes.TypeOf< - typeof LogSummaryDateRangeBucketRuntimeType ->; - -const LogSummaryResponseRuntimeType = runtimeTypes.type({ - aggregations: runtimeTypes.type({ - count_by_date: runtimeTypes.type({ - buckets: runtimeTypes.array(LogSummaryDateRangeBucketRuntimeType), - }), - }), -}); diff --git a/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.mock.ts b/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.mock.ts index 74509f11ae4a7..dd739de03f4a9 100644 --- a/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.mock.ts +++ b/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.mock.ts @@ -10,10 +10,7 @@ import { ILogsSharedLogEntriesDomain } from './log_entries_domain'; export const createLogsSharedLogEntriesDomainMock = (): jest.Mocked => { return { - getLogEntriesAround: jest.fn(), getLogEntries: jest.fn(), - getLogSummaryBucketsBetween: jest.fn(), - getLogSummaryHighlightBucketsBetween: jest.fn(), getLogEntryDatasets: jest.fn(), }; }; diff --git a/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts index f3cbfb57b09c4..e10d7d87fd0bf 100644 --- a/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/platform/plugins/shared/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -7,11 +7,6 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { JsonObject } from '@kbn/utility-types'; -import { subtractMillisecondsFromDate } from '../../../../common/utils'; -import { - LogEntriesSummaryBucket, - LogEntriesSummaryHighlightsBucket, -} from '../../../../common/http_api'; import { LogColumn, LogEntry, LogEntryCursor } from '../../../../common/log_entry'; import { LogViewColumnConfiguration, @@ -45,15 +40,6 @@ export interface LogEntriesParams { highlightTerm?: string; } -export interface LogEntriesAroundParams { - startTimestamp: number; - endTimestamp: number; - size?: number; - center: LogEntryCursor; - query?: JsonObject; - highlightTerm?: string; -} - export const LOG_ENTRIES_PAGE_SIZE = 200; const FIELDS_FROM_CONTEXT = ['log.file.path', 'host.name', 'container.id'] as const; @@ -61,35 +47,12 @@ const FIELDS_FROM_CONTEXT = ['log.file.path', 'host.name', 'container.id'] as co const COMPOSITE_AGGREGATION_BATCH_SIZE = 1000; export interface ILogsSharedLogEntriesDomain { - getLogEntriesAround( - requestContext: LogsSharedPluginRequestHandlerContext, - logView: LogViewReference, - params: LogEntriesAroundParams, - columnOverrides?: LogViewColumnConfiguration[] - ): Promise<{ entries: LogEntry[]; hasMoreBefore?: boolean; hasMoreAfter?: boolean }>; getLogEntries( requestContext: LogsSharedPluginRequestHandlerContext, logView: LogViewReference, params: LogEntriesParams, columnOverrides?: LogViewColumnConfiguration[] ): Promise<{ entries: LogEntry[]; hasMoreBefore?: boolean; hasMoreAfter?: boolean }>; - getLogSummaryBucketsBetween( - requestContext: LogsSharedPluginRequestHandlerContext, - logView: LogViewReference, - start: number, - end: number, - bucketSize: number, - filterQuery?: LogEntryQuery - ): Promise; - getLogSummaryHighlightBucketsBetween( - requestContext: LogsSharedPluginRequestHandlerContext, - logView: LogViewReference, - startTimestamp: number, - endTimestamp: number, - bucketSize: number, - highlightQueries: string[], - filterQuery?: LogEntryQuery - ): Promise; getLogEntryDatasets( requestContext: LogsSharedPluginRequestHandlerContext, timestampField: string, @@ -106,66 +69,6 @@ export class LogsSharedLogEntriesDomain implements ILogsSharedLogEntriesDomain { private readonly libs: Pick ) {} - public async getLogEntriesAround( - requestContext: LogsSharedPluginRequestHandlerContext, - logView: LogViewReference, - params: LogEntriesAroundParams, - columnOverrides?: LogViewColumnConfiguration[] - ): Promise<{ entries: LogEntry[]; hasMoreBefore?: boolean; hasMoreAfter?: boolean }> { - const { startTimestamp, endTimestamp, center, query, size, highlightTerm } = params; - - /* - * For odd sizes we will round this value down for the first half, and up - * for the second. This keeps the center cursor right in the center. - * - * For even sizes the half before is one entry bigger than the half after. - * [1, 2, 3, 4, 5, *6*, 7, 8, 9, 10] - * | 5 entries | |4 entries| - */ - const halfSize = (size || LOG_ENTRIES_PAGE_SIZE) / 2; - - const { entries: entriesBefore, hasMoreBefore } = await this.getLogEntries( - requestContext, - logView, - { - startTimestamp, - endTimestamp, - query, - cursor: { before: center }, - size: Math.floor(halfSize), - highlightTerm, - }, - columnOverrides - ); - - /* - * Elasticsearch's `search_after` returns documents after the specified cursor. - * - If we have documents before the center, we search after the last of - * those. The first document of the new group is the center. - * - If there were no documents, we search one milisecond before the - * center. It then becomes the first document. - */ - const cursorAfter = - entriesBefore.length > 0 - ? entriesBefore[entriesBefore.length - 1].cursor - : { time: subtractMillisecondsFromDate(center.time, 1), tiebreaker: 0 }; - - const { entries: entriesAfter, hasMoreAfter } = await this.getLogEntries( - requestContext, - logView, - { - startTimestamp, - endTimestamp, - query, - cursor: { after: cursorAfter }, - size: Math.ceil(halfSize), - highlightTerm, - } - ); - - return { entries: [...entriesBefore, ...entriesAfter], hasMoreBefore, hasMoreAfter }; - } - public async getLogEntries( requestContext: LogsSharedPluginRequestHandlerContext, logView: LogViewReference, @@ -227,86 +130,6 @@ export class LogsSharedLogEntriesDomain implements ILogsSharedLogEntriesDomain { return { entries, hasMoreBefore, hasMoreAfter }; } - public async getLogSummaryBucketsBetween( - requestContext: LogsSharedPluginRequestHandlerContext, - logView: LogViewReference, - start: number, - end: number, - bucketSize: number, - filterQuery?: LogEntryQuery - ): Promise { - const [, { logsDataAccess }, { logViews }] = await this.libs.getStartServices(); - const { savedObjects, elasticsearch } = await requestContext.core; - const logSourcesService = logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService( - savedObjects.client - ); - const resolvedLogView = await logViews - .getClient(savedObjects.client, elasticsearch.client.asCurrentUser, logSourcesService) - .getResolvedLogView(logView); - - const dateRangeBuckets = await this.adapter.getContainedLogSummaryBuckets( - requestContext, - resolvedLogView, - start, - end, - bucketSize, - filterQuery - ); - return dateRangeBuckets; - } - - public async getLogSummaryHighlightBucketsBetween( - requestContext: LogsSharedPluginRequestHandlerContext, - logView: LogViewReference, - startTimestamp: number, - endTimestamp: number, - bucketSize: number, - highlightQueries: string[], - filterQuery?: LogEntryQuery - ): Promise { - const [, { logsDataAccess }, { logViews }] = await this.libs.getStartServices(); - const { savedObjects, elasticsearch } = await requestContext.core; - const logSourcesService = logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService( - savedObjects.client - ); - - const resolvedLogView = await logViews - .getClient(savedObjects.client, elasticsearch.client.asCurrentUser, logSourcesService) - .getResolvedLogView(logView); - - const messageFormattingRules = compileFormattingRules( - getBuiltinRules(resolvedLogView.messageField) - ); - const requiredFields = getRequiredFields(resolvedLogView, messageFormattingRules); - - const summaries = await Promise.all( - highlightQueries.map(async (highlightQueryPhrase) => { - const highlightQuery = createHighlightQueryDsl(highlightQueryPhrase, requiredFields); - const query = filterQuery - ? { - bool: { - must: [filterQuery, highlightQuery], - }, - } - : highlightQuery; - const summaryBuckets = await this.adapter.getContainedLogSummaryBuckets( - requestContext, - resolvedLogView, - startTimestamp, - endTimestamp, - bucketSize, - query - ); - const summaryHighlightBuckets = summaryBuckets - .filter(logSummaryBucketHasEntries) - .map(convertLogSummaryBucketToSummaryHighlightBucket); - return summaryHighlightBuckets; - }) - ); - - return summaries; - } - public async getLogEntryDatasets( requestContext: LogsSharedPluginRequestHandlerContext, timestampField: string, @@ -356,15 +179,6 @@ export interface LogEntriesAdapter { fields: string[], params: LogEntriesParams ): Promise<{ documents: LogEntryDocument[]; hasMoreBefore?: boolean; hasMoreAfter?: boolean }>; - - getContainedLogSummaryBuckets( - requestContext: LogsSharedPluginRequestHandlerContext, - resolvedLogView: ResolvedLogView, - startTimestamp: number, - endTimestamp: number, - bucketSize: number, - filterQuery?: LogEntryQuery - ): Promise; } export type LogEntryQuery = JsonObject; @@ -377,25 +191,6 @@ export interface LogEntryDocument { cursor: LogEntryCursor; } -export interface LogSummaryBucket { - entriesCount: number; - start: number; - end: number; - topEntryKeys: LogEntryCursor[]; -} - -const logSummaryBucketHasEntries = (bucket: LogSummaryBucket) => - bucket.entriesCount > 0 && bucket.topEntryKeys.length > 0; - -const convertLogSummaryBucketToSummaryHighlightBucket = ( - bucket: LogSummaryBucket -): LogEntriesSummaryHighlightsBucket => ({ - entriesCount: bucket.entriesCount, - start: bucket.start, - end: bucket.end, - representativeKey: bucket.topEntryKeys[0], -}); - const getRequiredFields = ( configuration: ResolvedLogView, messageFormattingRules: CompiledLogMessageFormattingRule @@ -416,15 +211,6 @@ const getRequiredFields = ( ); }; -const createHighlightQueryDsl = (phrase: string, fields: string[]) => ({ - multi_match: { - fields, - lenient: true, - query: phrase, - type: 'phrase', - }, -}); - const getContextFromDoc = (doc: LogEntryDocument): LogEntry['context'] => { // Get all context fields, then test for the presence and type of the ones that go together const containerId = doc.fields['container.id']?.[0]; diff --git a/x-pack/platform/plugins/shared/logs_shared/server/logs_shared_server.ts b/x-pack/platform/plugins/shared/logs_shared/server/logs_shared_server.ts index 9bb643c8dd617..d49904866a489 100644 --- a/x-pack/platform/plugins/shared/logs_shared/server/logs_shared_server.ts +++ b/x-pack/platform/plugins/shared/logs_shared/server/logs_shared_server.ts @@ -6,18 +6,11 @@ */ import { LogsSharedBackendLibs } from './lib/logs_shared_types'; -import { - initLogEntriesHighlightsRoute, - initLogEntriesSummaryHighlightsRoute, - initLogEntriesSummaryRoute, -} from './routes/log_entries'; + import { initLogViewRoutes } from './routes/log_views'; import { initMigrateLogViewSettingsRoute } from './routes/deprecations'; export const initLogsSharedServer = (libs: LogsSharedBackendLibs) => { - initLogEntriesHighlightsRoute(libs); - initLogEntriesSummaryRoute(libs); - initLogEntriesSummaryHighlightsRoute(libs); initLogViewRoutes(libs); initMigrateLogViewSettingsRoute(libs); }; diff --git a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/highlights.ts b/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/highlights.ts deleted file mode 100644 index dedf3ced27f28..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/highlights.ts +++ /dev/null @@ -1,118 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import Boom from '@hapi/boom'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { fold } from 'fp-ts/lib/Either'; -import { identity } from 'fp-ts/lib/function'; -import { schema } from '@kbn/config-schema'; - -import { i18n } from '@kbn/i18n'; -import { logEntriesV1 } from '../../../common/http_api'; -import { throwErrors } from '../../../common/runtime_types'; - -import { LogsSharedBackendLibs } from '../../lib/logs_shared_types'; - -import { parseFilterQuery } from '../../utils/serialized_query'; -import { LogEntriesParams } from '../../lib/domains/log_entries_domain'; - -const escapeHatch = schema.object({}, { unknowns: 'allow' }); - -export const initLogEntriesHighlightsRoute = ({ framework, logEntries }: LogsSharedBackendLibs) => { - framework - .registerVersionedRoute({ - access: 'internal', - method: 'post', - path: logEntriesV1.LOG_ENTRIES_HIGHLIGHTS_PATH, - }) - .addVersion( - { - version: '1', - validate: { request: { body: escapeHatch } }, - options: { - deprecated: { - documentationUrl: '', - severity: 'warning', - message: i18n.translate( - 'xpack.logsShared.deprecations.postLogEntriesHighlightsRoute.message', - { - defaultMessage: - 'Given the deprecation of the LogStream feature, this API will not return reliable data in upcoming versions of Kibana.', - } - ), - reason: { type: 'deprecate' }, - }, - }, - }, - async (requestContext, request, response) => { - const payload = pipe( - logEntriesV1.logEntriesHighlightsRequestRT.decode(request.body), - fold(throwErrors(Boom.badRequest), identity) - ); - - const { startTimestamp, endTimestamp, logView, query, size, highlightTerms } = payload; - - let entriesPerHighlightTerm; - - if ('center' in payload) { - entriesPerHighlightTerm = await Promise.all( - highlightTerms.map((highlightTerm) => - logEntries.getLogEntriesAround(requestContext, logView, { - startTimestamp, - endTimestamp, - query: parseFilterQuery(query), - center: payload.center, - size, - highlightTerm, - }) - ) - ); - } else { - let cursor: LogEntriesParams['cursor']; - if ('before' in payload) { - cursor = { before: payload.before }; - } else if ('after' in payload) { - cursor = { after: payload.after }; - } - - entriesPerHighlightTerm = await Promise.all( - highlightTerms.map((highlightTerm) => - logEntries.getLogEntries(requestContext, logView, { - startTimestamp, - endTimestamp, - query: parseFilterQuery(query), - cursor, - size, - highlightTerm, - }) - ) - ); - } - - return response.ok({ - body: logEntriesV1.logEntriesHighlightsResponseRT.encode({ - data: entriesPerHighlightTerm.map(({ entries }) => { - if (entries.length > 0) { - return { - entries, - topCursor: entries[0].cursor, - bottomCursor: entries[entries.length - 1].cursor, - }; - } else { - return { - entries, - topCursor: null, - bottomCursor: null, - }; - } - }), - }), - }); - } - ); -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/index.ts b/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/index.ts deleted file mode 100644 index 83d240ca8f273..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/index.ts +++ /dev/null @@ -1,10 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './highlights'; -export * from './summary'; -export * from './summary_highlights'; diff --git a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary.ts b/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary.ts deleted file mode 100644 index 68c9d5ea0e166..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary.ts +++ /dev/null @@ -1,88 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import Boom from '@hapi/boom'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { fold } from 'fp-ts/lib/Either'; -import { identity } from 'fp-ts/lib/function'; -import { schema } from '@kbn/config-schema'; - -import { i18n } from '@kbn/i18n'; -import { logEntriesV1 } from '../../../common/http_api'; -import { throwErrors } from '../../../common/runtime_types'; - -import { LogsSharedBackendLibs } from '../../lib/logs_shared_types'; - -import { parseFilterQuery } from '../../utils/serialized_query'; - -const escapeHatch = schema.object({}, { unknowns: 'allow' }); - -export const initLogEntriesSummaryRoute = ({ - framework, - logEntries, - getUsageCollector, -}: LogsSharedBackendLibs) => { - framework - .registerVersionedRoute({ - access: 'internal', - method: 'post', - path: logEntriesV1.LOG_ENTRIES_SUMMARY_PATH, - }) - .addVersion( - { - version: '1', - validate: { request: { body: escapeHatch } }, - options: { - deprecated: { - documentationUrl: '', - severity: 'warning', - message: i18n.translate( - 'xpack.logsShared.deprecations.postLogEntriesSummaryRoute.message', - { - defaultMessage: - 'Given the deprecation of the LogStream feature, this API will not return reliable data in upcoming versions of Kibana.', - } - ), - reason: { type: 'deprecate' }, - }, - }, - }, - async (requestContext, request, response) => { - const payload = pipe( - logEntriesV1.logEntriesSummaryRequestRT.decode(request.body), - fold(throwErrors(Boom.badRequest), identity) - ); - const { logView, startTimestamp, endTimestamp, bucketSize, query } = payload; - - const usageCollector = getUsageCollector(); - - const buckets = await logEntries.getLogSummaryBucketsBetween( - requestContext, - logView, - startTimestamp, - endTimestamp, - bucketSize, - parseFilterQuery(query) - ); - - if (typeof usageCollector.countLogs === 'function') { - usageCollector.countLogs(); - } - - return response.ok({ - body: logEntriesV1.logEntriesSummaryResponseRT.encode({ - data: { - start: startTimestamp, - end: endTimestamp, - buckets, - }, - }), - }); - } - ); -}; diff --git a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary_highlights.ts b/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary_highlights.ts deleted file mode 100644 index b8f030b91b715..0000000000000 --- a/x-pack/platform/plugins/shared/logs_shared/server/routes/log_entries/summary_highlights.ts +++ /dev/null @@ -1,83 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import Boom from '@hapi/boom'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { fold } from 'fp-ts/lib/Either'; -import { identity } from 'fp-ts/lib/function'; -import { schema } from '@kbn/config-schema'; - -import { i18n } from '@kbn/i18n'; -import { logEntriesV1 } from '../../../common/http_api'; -import { throwErrors } from '../../../common/runtime_types'; - -import { LogsSharedBackendLibs } from '../../lib/logs_shared_types'; - -import { parseFilterQuery } from '../../utils/serialized_query'; - -const escapeHatch = schema.object({}, { unknowns: 'allow' }); - -export const initLogEntriesSummaryHighlightsRoute = ({ - framework, - logEntries, -}: LogsSharedBackendLibs) => { - framework - .registerVersionedRoute({ - access: 'internal', - method: 'post', - path: logEntriesV1.LOG_ENTRIES_SUMMARY_HIGHLIGHTS_PATH, - }) - .addVersion( - { - version: '1', - validate: { request: { body: escapeHatch } }, - options: { - deprecated: { - documentationUrl: '', - severity: 'warning', - message: i18n.translate( - 'xpack.logsShared.deprecations.postLogEntriesSummaryHighlightsRoute.message', - { - defaultMessage: - 'Given the deprecation of the LogStream feature, this API will not return reliable data in upcoming versions of Kibana.', - } - ), - reason: { type: 'deprecate' }, - }, - }, - }, - async (requestContext, request, response) => { - const payload = pipe( - logEntriesV1.logEntriesSummaryHighlightsRequestRT.decode(request.body), - fold(throwErrors(Boom.badRequest), identity) - ); - const { logView, startTimestamp, endTimestamp, bucketSize, query, highlightTerms } = - payload; - - const bucketsPerHighlightTerm = await logEntries.getLogSummaryHighlightBucketsBetween( - requestContext, - logView, - startTimestamp, - endTimestamp, - bucketSize, - highlightTerms, - parseFilterQuery(query) - ); - - return response.ok({ - body: logEntriesV1.logEntriesSummaryHighlightsResponseRT.encode({ - data: bucketsPerHighlightTerm.map((buckets) => ({ - start: startTimestamp, - end: endTimestamp, - buckets, - })), - }), - }); - } - ); -}; diff --git a/x-pack/solutions/observability/plugins/infra/common/time/time_key.ts b/x-pack/solutions/observability/plugins/infra/common/time/time_key.ts index 7acbef8b25025..9cfa14357255c 100644 --- a/x-pack/solutions/observability/plugins/infra/common/time/time_key.ts +++ b/x-pack/solutions/observability/plugins/infra/common/time/time_key.ts @@ -6,7 +6,7 @@ */ import { DateFromStringOrNumber } from '@kbn/io-ts-utils'; -import { ascending, bisector } from 'd3-array'; +import { ascending } from 'd3-array'; import * as rt from 'io-ts'; import { pick } from 'lodash'; @@ -69,28 +69,6 @@ export const compareToTimeKey = (value: Value, key: TimeKey) => compareTimeKeys(keyAccessor(value), key, compareValues); -export const getIndexAtTimeKey = ( - keyAccessor: (value: Value) => TimeKey, - compareValues?: Comparator -) => { - const comparator = compareToTimeKey(keyAccessor, compareValues); - const collectionBisector = bisector(comparator); - - return (collection: Value[], key: TimeKey): number | null => { - const index = collectionBisector.left(collection, key); - - if (index >= collection.length) { - return null; - } - - if (comparator(collection[index], key) !== 0) { - return null; - } - - return index; - }; -}; - export const timeKeyIsBetween = (min: TimeKey, max: TimeKey, operand: TimeKey) => compareTimeKeys(min, operand) <= 0 && compareTimeKeys(max, operand) >= 0; diff --git a/x-pack/solutions/observability/plugins/infra/public/hooks/use_observable.ts b/x-pack/solutions/observability/plugins/infra/public/hooks/use_observable.ts index 167f55dfea546..d75acb84160a0 100644 --- a/x-pack/solutions/observability/plugins/infra/public/hooks/use_observable.ts +++ b/x-pack/solutions/observability/plugins/infra/public/hooks/use_observable.ts @@ -7,7 +7,7 @@ import { useEffect, useRef, useState } from 'react'; import type { OperatorFunction, PartialObserver, Subscription } from 'rxjs'; -import { BehaviorSubject, Observable, ReplaySubject } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; import { switchMap } from 'rxjs'; export const useLatest = (value: Value) => { @@ -52,22 +52,6 @@ export const useBehaviorSubject = < return [output$, next] as const; }; -export const useReplaySubject = < - InputValue, - OutputValue, - OutputObservable extends Observable ->( - deriveObservableOnce: (input$: Observable) => OutputObservable -) => { - const [[subject$, next], _] = useState(() => { - const newSubject$ = new ReplaySubject(); - const newNext = newSubject$.next.bind(newSubject$); - return [newSubject$, newNext] as const; - }); - const [output$] = useState(() => deriveObservableOnce(subject$)); - return [output$, next] as const; -}; - export const useObservableState = ( state$: Observable, initialState: InitialState | (() => InitialState) diff --git a/x-pack/test/api_integration/apis/logs_ui/log_entry_highlights.ts b/x-pack/test/api_integration/apis/logs_ui/log_entry_highlights.ts deleted file mode 100644 index aa0796c584c77..0000000000000 --- a/x-pack/test/api_integration/apis/logs_ui/log_entry_highlights.ts +++ /dev/null @@ -1,213 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; - -import semver from 'semver'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { identity } from 'fp-ts/lib/function'; -import { fold } from 'fp-ts/lib/Either'; - -import { createPlainError, throwErrors } from '@kbn/io-ts-utils'; - -import { - LOG_ENTRIES_HIGHLIGHTS_PATH, - logEntriesHighlightsRequestRT, - logEntriesHighlightsResponseRT, -} from '@kbn/logs-shared-plugin/common'; - -import moment from 'moment'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -const KEY_BEFORE_START = { - time: new Date('2000-01-01T00:00:00.000Z').valueOf(), - tiebreaker: -1, -}; -const KEY_AFTER_END = { - time: new Date('2000-01-01T00:00:09.001Z').valueOf(), - tiebreaker: 0, -}; - -const COMMON_HEADERS = { - 'kbn-xsrf': 'some-xsrf-token', - 'Elastic-Api-Version': '1', -}; - -export default function ({ getService }: FtrProviderContext) { - const es = getService('es'); - const esArchiver = getService('esArchiver'); - const supertest = getService('supertest'); - const kibanaServer = getService('kibanaServer'); - - describe('log highlight apis', () => { - before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/simple_logs')); - after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/simple_logs')); - - describe('/log_entries/highlights', () => { - describe('with the default source', () => { - before(() => kibanaServer.savedObjects.cleanStandardList()); - after(() => kibanaServer.savedObjects.cleanStandardList()); - - it('Handles empty responses', async () => { - const { body } = await supertest - .post(LOG_ENTRIES_HIGHLIGHTS_PATH) - .set(COMMON_HEADERS) - .send( - logEntriesHighlightsRequestRT.encode({ - logView: { type: 'log-view-reference', logViewId: 'default' }, - startTimestamp: KEY_BEFORE_START.time, - endTimestamp: KEY_AFTER_END.time, - highlightTerms: ['some string that does not exist'], - }) - ) - .expect(200); - - const logEntriesHighlightsResponse = pipe( - logEntriesHighlightsResponseRT.decode(body), - fold(throwErrors(createPlainError), identity) - ); - - expect(logEntriesHighlightsResponse.data).to.have.length(1); - - const data = logEntriesHighlightsResponse.data[0]; - - expect(data.entries).to.have.length(0); - expect(data.topCursor).to.be(null); - expect(data.bottomCursor).to.be(null); - }); - - it('highlights built-in message column', async () => { - const esInfo = await es.info(); - const highlightTerms = 'message of document 0'; - const { body } = await supertest - .post(LOG_ENTRIES_HIGHLIGHTS_PATH) - .set(COMMON_HEADERS) - .send( - logEntriesHighlightsRequestRT.encode({ - logView: { type: 'log-view-reference', logViewId: 'default' }, - startTimestamp: KEY_BEFORE_START.time, - endTimestamp: KEY_AFTER_END.time, - highlightTerms: [highlightTerms], - }) - ) - .expect(200); - - const logEntriesHighlightsResponse = pipe( - logEntriesHighlightsResponseRT.decode(body), - fold(throwErrors(createPlainError), identity) - ); - - expect(logEntriesHighlightsResponse.data).to.have.length(1); - - const data = logEntriesHighlightsResponse.data[0]; - const entries = data.entries; - const firstEntry = entries[0]; - const lastEntry = entries[entries.length - 1]; - - // Finds expected entries - expect(entries).to.have.length(10); - - // Cursors are set correctly - expect(firstEntry.cursor).to.eql(data.topCursor); - expect(lastEntry.cursor).to.eql(data.bottomCursor); - - // Entries fall within range - // @kbn/expect doesn't have a `lessOrEqualThan` or `moreOrEqualThan` comparators - expect(firstEntry.cursor.time >= moment(KEY_BEFORE_START.time).toISOString()).to.be(true); - expect(lastEntry.cursor.time <= moment(KEY_AFTER_END.time).toISOString()).to.be(true); - - // All entries contain the highlights - entries.forEach((entry) => { - entry.columns.forEach((column) => { - if ('message' in column && 'highlights' in column.message[0]) { - const expectation = semver.gte(esInfo.version.number, '8.10.0') - ? [highlightTerms] - : highlightTerms.split(' '); - expect(column.message[0].highlights).to.eql(expectation); - } - }); - }); - }); - - it('highlights field columns', async () => { - const { body } = await supertest - .post(LOG_ENTRIES_HIGHLIGHTS_PATH) - .set(COMMON_HEADERS) - .send( - logEntriesHighlightsRequestRT.encode({ - logView: { type: 'log-view-reference', logViewId: 'default' }, - startTimestamp: KEY_BEFORE_START.time, - endTimestamp: KEY_AFTER_END.time, - highlightTerms: ['generate_test_data/simple_logs'], - }) - ) - .expect(200); - - const logEntriesHighlightsResponse = pipe( - logEntriesHighlightsResponseRT.decode(body), - fold(throwErrors(createPlainError), identity) - ); - - expect(logEntriesHighlightsResponse.data).to.have.length(1); - - const entries = logEntriesHighlightsResponse.data[0].entries; - - // Finds expected entries - expect(entries).to.have.length(50); - - // All entries contain the highlights - entries.forEach((entry) => { - entry.columns.forEach((column) => { - if ('field' in column && 'highlights' in column && column.highlights.length > 0) { - expect(column.highlights).to.eql(['generate_test_data/simple_logs']); - } - }); - }); - }); - - it('applies the query as well as the highlight', async () => { - const { body } = await supertest - .post(LOG_ENTRIES_HIGHLIGHTS_PATH) - .set(COMMON_HEADERS) - .send( - logEntriesHighlightsRequestRT.encode({ - logView: { type: 'log-view-reference', logViewId: 'default' }, - startTimestamp: KEY_BEFORE_START.time, - endTimestamp: KEY_AFTER_END.time, - query: JSON.stringify({ - multi_match: { query: 'host-a', type: 'phrase', lenient: true }, - }), - highlightTerms: ['message'], - }) - ) - .expect(200); - - const logEntriesHighlightsResponse = pipe( - logEntriesHighlightsResponseRT.decode(body), - fold(throwErrors(createPlainError), identity) - ); - - expect(logEntriesHighlightsResponse.data).to.have.length(1); - - const entries = logEntriesHighlightsResponse.data[0].entries; - - // Finds expected entries - expect(entries).to.have.length(25); - - // All entries contain the highlights - entries.forEach((entry) => { - entry.columns.forEach((column) => { - if ('message' in column && 'highlights' in column.message[0]) { - expect(column.message[0].highlights).to.eql(['message', 'message']); - } - }); - }); - }); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/logs_ui/log_summary.ts b/x-pack/test/api_integration/apis/logs_ui/log_summary.ts deleted file mode 100644 index 8a02dad1f1c5b..0000000000000 --- a/x-pack/test/api_integration/apis/logs_ui/log_summary.ts +++ /dev/null @@ -1,79 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; - -import { pairs } from 'd3-array'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { identity } from 'fp-ts/lib/function'; -import { fold } from 'fp-ts/lib/Either'; - -import { createPlainError, throwErrors } from '@kbn/io-ts-utils'; - -import { - LOG_ENTRIES_SUMMARY_PATH, - logEntriesSummaryRequestRT, - logEntriesSummaryResponseRT, -} from '@kbn/logs-shared-plugin/common'; - -import { FtrProviderContext } from '../../ftr_provider_context'; - -const EARLIEST_TIME_WITH_DATA = new Date('2018-10-17T19:42:22.000Z').valueOf(); -const LATEST_TIME_WITH_DATA = new Date('2018-10-17T19:57:21.611Z').valueOf(); - -const COMMON_HEADERS = { - 'kbn-xsrf': 'some-xsrf-token', - 'Elastic-Api-Version': '1', -}; - -export default function ({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const supertest = getService('supertest'); - - describe('logSummaryBetween', () => { - before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - - it('should return empty and non-empty consecutive buckets', async () => { - const startTimestamp = EARLIEST_TIME_WITH_DATA; - const endTimestamp = - LATEST_TIME_WITH_DATA + (LATEST_TIME_WITH_DATA - EARLIEST_TIME_WITH_DATA); - const bucketSize = Math.ceil((endTimestamp - startTimestamp) / 10); - - const { body } = await supertest - .post(LOG_ENTRIES_SUMMARY_PATH) - .set(COMMON_HEADERS) - .send( - logEntriesSummaryRequestRT.encode({ - logView: { type: 'log-view-reference', logViewId: 'default' }, - startTimestamp, - endTimestamp, - bucketSize, - query: null, - }) - ) - .expect(200); - - const logSummaryResponse = pipe( - logEntriesSummaryResponseRT.decode(body), - fold(throwErrors(createPlainError), identity) - ); - - expect(logSummaryResponse.data.buckets).to.have.length(10); - expect( - logSummaryResponse.data.buckets.filter((bucket: any) => bucket.entriesCount > 0) - ).to.have.length(5); - expect( - pairs( - logSummaryResponse.data.buckets, - (first: any, second: any) => first.end === second.start - ).every((pair) => pair) - ).to.equal(true); - }); - }); -}