mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
remove unneeded usages of isErrorResponse (#164609)
`data.search` uses [poll_search](https://github.com/elastic/kibana/blob/main/src/plugins/data/common/search/poll_search.ts) to fetch data. `poll_search` checks for `isErrorResponse` and throws when`isErrorResponse` is true. **Note** `searchSource.search` uses `data.search` to perform searches. ```javascript return from(search()).pipe( expand(() => { const elapsedTime = Date.now() - startTime; return timer(getPollInterval(elapsedTime)).pipe(switchMap(search)); }), tap((response) => { if (isErrorResponse(response)) { throw response ? new Error('Received partial response') : new AbortError(); } }), takeWhile<Response>(isPartialResponse, true), takeUntil<Response>(aborted$) ); ``` Subscribers to `data.search` and `searchSource.search` do not need to check for `isErrorResponse` in `next`. `poll_search` has already thrown then the response is `isErrorResponse` so these checks are dead code blocks that are never executed. This PR removes these dead code blocks. Breaking this change out of https://github.com/elastic/kibana/pull/164506 so that it can be reviewed in isolated. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
5724d01536
commit
0113eb74c8
30 changed files with 56 additions and 257 deletions
|
@ -30,7 +30,6 @@ import {
|
||||||
DataPublicPluginStart,
|
DataPublicPluginStart,
|
||||||
IKibanaSearchResponse,
|
IKibanaSearchResponse,
|
||||||
isCompleteResponse,
|
isCompleteResponse,
|
||||||
isErrorResponse,
|
|
||||||
} from '@kbn/data-plugin/public';
|
} from '@kbn/data-plugin/public';
|
||||||
import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types';
|
import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types';
|
||||||
import type { DataView, DataViewField } from '@kbn/data-views-plugin/public';
|
import type { DataView, DataViewField } from '@kbn/data-views-plugin/public';
|
||||||
|
@ -247,9 +246,6 @@ export const SearchExamplesApp = ({
|
||||||
text: toMountPoint(res.warning),
|
text: toMountPoint(res.warning),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (isErrorResponse(res)) {
|
|
||||||
// TODO: Make response error status clearer
|
|
||||||
notifications.toasts.addDanger('An error has occurred');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (e) => {
|
error: (e) => {
|
||||||
|
@ -401,10 +397,6 @@ export const SearchExamplesApp = ({
|
||||||
title: 'Query result',
|
title: 'Query result',
|
||||||
text: 'Query finished',
|
text: 'Query finished',
|
||||||
});
|
});
|
||||||
} else if (isErrorResponse(res)) {
|
|
||||||
setIsLoading(false);
|
|
||||||
// TODO: Make response error status clearer
|
|
||||||
notifications.toasts.addWarning('An error has occurred');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (e) => {
|
error: (e) => {
|
||||||
|
|
|
@ -40,7 +40,6 @@ import {
|
||||||
IEsSearchRequest,
|
IEsSearchRequest,
|
||||||
IEsSearchResponse,
|
IEsSearchResponse,
|
||||||
isCompleteResponse,
|
isCompleteResponse,
|
||||||
isErrorResponse,
|
|
||||||
QueryState,
|
QueryState,
|
||||||
SearchSessionState,
|
SearchSessionState,
|
||||||
} from '@kbn/data-plugin/public';
|
} from '@kbn/data-plugin/public';
|
||||||
|
@ -724,8 +723,6 @@ function doSearch(
|
||||||
title: 'Query result',
|
title: 'Query result',
|
||||||
text: mountReactNode(message),
|
text: mountReactNode(message),
|
||||||
});
|
});
|
||||||
} else if (isErrorResponse(res)) {
|
|
||||||
notifications.toasts.addWarning('An error has occurred');
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
map((res) => ({ response: res, request: req, tookMs: performance.now() - startTs })),
|
map((res) => ({ response: res, request: req, tookMs: performance.now() - startTs })),
|
||||||
|
|
|
@ -27,7 +27,6 @@ import {
|
||||||
DataPublicPluginStart,
|
DataPublicPluginStart,
|
||||||
IKibanaSearchResponse,
|
IKibanaSearchResponse,
|
||||||
isCompleteResponse,
|
isCompleteResponse,
|
||||||
isErrorResponse,
|
|
||||||
} from '@kbn/data-plugin/public';
|
} from '@kbn/data-plugin/public';
|
||||||
import {
|
import {
|
||||||
SQL_SEARCH_STRATEGY,
|
SQL_SEARCH_STRATEGY,
|
||||||
|
@ -70,10 +69,6 @@ export const SqlSearchExampleApp = ({ notifications, data }: SearchExamplesAppDe
|
||||||
if (isCompleteResponse(res)) {
|
if (isCompleteResponse(res)) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setResponse(res);
|
setResponse(res);
|
||||||
} else if (isErrorResponse(res)) {
|
|
||||||
setIsLoading(false);
|
|
||||||
setResponse(res);
|
|
||||||
notifications.toasts.addDanger('An error has occurred');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (e) => {
|
error: (e) => {
|
||||||
|
|
|
@ -1105,32 +1105,6 @@ describe('SearchSource', () => {
|
||||||
expect(complete2).toBeCalledTimes(1);
|
expect(complete2).toBeCalledTimes(1);
|
||||||
expect(searchSourceDependencies.search).toHaveBeenCalledTimes(1);
|
expect(searchSourceDependencies.search).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should emit error on empty response', async () => {
|
|
||||||
searchSourceDependencies.search = mockSearchMethod = jest
|
|
||||||
.fn()
|
|
||||||
.mockReturnValue(
|
|
||||||
of({ rawResponse: { test: 1 }, isPartial: true, isRunning: true }, undefined)
|
|
||||||
);
|
|
||||||
|
|
||||||
searchSource = new SearchSource({ index: indexPattern }, searchSourceDependencies);
|
|
||||||
const options = {};
|
|
||||||
|
|
||||||
const next = jest.fn();
|
|
||||||
const error = jest.fn();
|
|
||||||
const complete = jest.fn();
|
|
||||||
const res$ = searchSource.fetch$(options);
|
|
||||||
res$.subscribe({ next, error, complete });
|
|
||||||
await firstValueFrom(res$).catch((_) => {});
|
|
||||||
|
|
||||||
expect(next).toBeCalledTimes(1);
|
|
||||||
expect(error).toBeCalledTimes(1);
|
|
||||||
expect(complete).toBeCalledTimes(0);
|
|
||||||
expect(next.mock.calls[0][0].rawResponse).toStrictEqual({
|
|
||||||
test: 1,
|
|
||||||
});
|
|
||||||
expect(error.mock.calls[0][0]).toBe(undefined);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('inspector', () => {
|
describe('inspector', () => {
|
||||||
|
|
|
@ -106,7 +106,6 @@ import { getRequestInspectorStats, getResponseInspectorStats } from './inspect';
|
||||||
import {
|
import {
|
||||||
getEsQueryConfig,
|
getEsQueryConfig,
|
||||||
IKibanaSearchResponse,
|
IKibanaSearchResponse,
|
||||||
isErrorResponse,
|
|
||||||
isPartialResponse,
|
isPartialResponse,
|
||||||
isCompleteResponse,
|
isCompleteResponse,
|
||||||
UI_SETTINGS,
|
UI_SETTINGS,
|
||||||
|
@ -547,9 +546,7 @@ export class SearchSource {
|
||||||
// For testing timeout messages in UI, uncomment the next line
|
// For testing timeout messages in UI, uncomment the next line
|
||||||
// response.rawResponse.timed_out = true;
|
// response.rawResponse.timed_out = true;
|
||||||
return new Observable<IKibanaSearchResponse<unknown>>((obs) => {
|
return new Observable<IKibanaSearchResponse<unknown>>((obs) => {
|
||||||
if (isErrorResponse(response)) {
|
if (isPartialResponse(response)) {
|
||||||
obs.error(response);
|
|
||||||
} else if (isPartialResponse(response)) {
|
|
||||||
obs.next(this.postFlightTransform(response));
|
obs.next(this.postFlightTransform(response));
|
||||||
} else {
|
} else {
|
||||||
if (!this.hasPostFlightRequests()) {
|
if (!this.hasPostFlightRequests()) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import { cloneDeep, get } from 'lodash';
|
import { cloneDeep, get } from 'lodash';
|
||||||
import { useRef, useCallback, useMemo } from 'react';
|
import { useRef, useCallback, useMemo } from 'react';
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public';
|
import { isCompleteResponse } from '@kbn/data-plugin/public';
|
||||||
import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
|
import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
|
||||||
|
|
||||||
import { createRandomSamplerWrapper } from '@kbn/ml-random-sampler-utils';
|
import { createRandomSamplerWrapper } from '@kbn/ml-random-sampler-utils';
|
||||||
|
@ -110,8 +110,6 @@ export function useCategorizeRequest() {
|
||||||
next: (result) => {
|
next: (result) => {
|
||||||
if (isCompleteResponse(result)) {
|
if (isCompleteResponse(result)) {
|
||||||
resolve(processCategoryResults(result, field, unwrap));
|
resolve(processCategoryResults(result, field, unwrap));
|
||||||
} else if (isErrorResponse(result)) {
|
|
||||||
reject(result);
|
|
||||||
} else {
|
} else {
|
||||||
// partial results
|
// partial results
|
||||||
// Ignore partial results for now.
|
// Ignore partial results for now.
|
||||||
|
|
|
@ -6,11 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useCallback, useRef, useState } from 'react';
|
import { useCallback, useRef, useState } from 'react';
|
||||||
import {
|
import { type IKibanaSearchResponse, isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
type IKibanaSearchResponse,
|
|
||||||
isCompleteResponse,
|
|
||||||
isErrorResponse,
|
|
||||||
} from '@kbn/data-plugin/common';
|
|
||||||
import { tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
import { useAiopsAppContext } from './use_aiops_app_context';
|
import { useAiopsAppContext } from './use_aiops_app_context';
|
||||||
|
|
||||||
|
@ -38,8 +34,6 @@ export function useCancellableSearch() {
|
||||||
if (isCompleteResponse(result)) {
|
if (isCompleteResponse(result)) {
|
||||||
setIsFetching(false);
|
setIsFetching(false);
|
||||||
resolve(result);
|
resolve(result);
|
||||||
} else if (isErrorResponse(result)) {
|
|
||||||
reject(result);
|
|
||||||
} else {
|
} else {
|
||||||
// partial results
|
// partial results
|
||||||
// Ignore partial results for now.
|
// Ignore partial results for now.
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { useDispatch } from 'react-redux';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import type {
|
import type {
|
||||||
Inspect,
|
Inspect,
|
||||||
PaginationInputPaginated,
|
PaginationInputPaginated,
|
||||||
|
@ -32,8 +32,6 @@ import type { RunTimeMappings } from '../../store/sourcerer/model';
|
||||||
import { TimelineEventsQueries } from '../../../../common/search_strategy';
|
import { TimelineEventsQueries } from '../../../../common/search_strategy';
|
||||||
import type { KueryFilterQueryKind } from '../../../../common/types';
|
import type { KueryFilterQueryKind } from '../../../../common/types';
|
||||||
import type { ESQuery } from '../../../../common/typed_json';
|
import type { ESQuery } from '../../../../common/typed_json';
|
||||||
import { useAppToasts } from '../../hooks/use_app_toasts';
|
|
||||||
import { ERROR_TIMELINE_EVENTS } from './translations';
|
|
||||||
import type { AlertWorkflowStatus } from '../../types';
|
import type { AlertWorkflowStatus } from '../../types';
|
||||||
import { getSearchTransactionName, useStartTransaction } from '../../lib/apm/use_start_transaction';
|
import { getSearchTransactionName, useStartTransaction } from '../../lib/apm/use_start_transaction';
|
||||||
export type InspectResponse = Inspect & { response: string[] };
|
export type InspectResponse = Inspect & { response: string[] };
|
||||||
|
@ -220,7 +218,6 @@ export const useTimelineEventsHandler = ({
|
||||||
loadPage: wrappedLoadPage,
|
loadPage: wrappedLoadPage,
|
||||||
updatedAt: 0,
|
updatedAt: 0,
|
||||||
});
|
});
|
||||||
const { addWarning } = useAppToasts();
|
|
||||||
|
|
||||||
const timelineSearch = useCallback(
|
const timelineSearch = useCallback(
|
||||||
(request: TimelineRequest<typeof language> | null, onNextHandler?: OnNextResponseHandler) => {
|
(request: TimelineRequest<typeof language> | null, onNextHandler?: OnNextResponseHandler) => {
|
||||||
|
@ -233,7 +230,7 @@ export const useTimelineEventsHandler = ({
|
||||||
abortCtrl.current = new AbortController();
|
abortCtrl.current = new AbortController();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (data && data.search) {
|
if (data && data.search) {
|
||||||
const { endTracking } = startTracking();
|
startTracking();
|
||||||
const abortSignal = abortCtrl.current.signal;
|
const abortSignal = abortCtrl.current.signal;
|
||||||
searchSubscription$.current = data.search
|
searchSubscription$.current = data.search
|
||||||
.search<TimelineRequest<typeof language>, TimelineResponse<typeof language>>(
|
.search<TimelineRequest<typeof language>, TimelineResponse<typeof language>>(
|
||||||
|
@ -270,11 +267,6 @@ export const useTimelineEventsHandler = ({
|
||||||
setFilterStatus(request.filterStatus);
|
setFilterStatus(request.filterStatus);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
endTracking('invalid');
|
|
||||||
addWarning(ERROR_TIMELINE_EVENTS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -292,7 +284,7 @@ export const useTimelineEventsHandler = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[skip, data, entityType, dataViewId, addWarning, startTracking, dispatch, id, prevFilterStatus]
|
[skip, data, entityType, dataViewId, startTracking, dispatch, id, prevFilterStatus]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type { Observable } from 'rxjs';
|
||||||
import { filter } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
|
|
||||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||||
import { isErrorResponse, isCompleteResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import type {
|
import type {
|
||||||
CtiEventEnrichmentRequestOptions,
|
CtiEventEnrichmentRequestOptions,
|
||||||
CtiEventEnrichmentStrategyResponse,
|
CtiEventEnrichmentStrategyResponse,
|
||||||
|
@ -46,6 +46,4 @@ export const getEventEnrichment = ({
|
||||||
export const getEventEnrichmentComplete = (
|
export const getEventEnrichmentComplete = (
|
||||||
props: GetEventEnrichmentProps
|
props: GetEventEnrichmentProps
|
||||||
): Observable<CtiEventEnrichmentStrategyResponse> =>
|
): Observable<CtiEventEnrichmentStrategyResponse> =>
|
||||||
getEventEnrichment(props).pipe(
|
getEventEnrichment(props).pipe(filter((response) => isCompleteResponse(response)));
|
||||||
filter((response) => isErrorResponse(response) || isCompleteResponse(response))
|
|
||||||
);
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { noop } from 'lodash/fp';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import type { inputsModel } from '../../../store';
|
import type { inputsModel } from '../../../store';
|
||||||
import { useKibana } from '../../../lib/kibana';
|
import { useKibana } from '../../../lib/kibana';
|
||||||
import type {
|
import type {
|
||||||
|
@ -59,7 +59,7 @@ export const useTimelineLastEventTime = ({
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
errorMessage: undefined,
|
errorMessage: undefined,
|
||||||
});
|
});
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const timelineLastEventTimeSearch = useCallback(
|
const timelineLastEventTimeSearch = useCallback(
|
||||||
(request: TimelineEventsLastEventTimeRequestOptions) => {
|
(request: TimelineEventsLastEventTimeRequestOptions) => {
|
||||||
|
@ -85,9 +85,6 @@ export const useTimelineLastEventTime = ({
|
||||||
lastSeen: response.lastSeen,
|
lastSeen: response.lastSeen,
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
}));
|
}));
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_LAST_EVENT_TIME);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -107,7 +104,7 @@ export const useTimelineLastEventTime = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning]
|
[data.search, addError]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -7,13 +7,6 @@
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
|
||||||
export const ERROR_LAST_EVENT_TIME = i18n.translate(
|
|
||||||
'xpack.securitySolution.lastEventTime.errorSearchDescription',
|
|
||||||
{
|
|
||||||
defaultMessage: `An error has occurred on last event time search`,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const FAIL_LAST_EVENT_TIME = i18n.translate(
|
export const FAIL_LAST_EVENT_TIME = i18n.translate(
|
||||||
'xpack.securitySolution.lastEventTime.failSearchDescription',
|
'xpack.securitySolution.lastEventTime.failSearchDescription',
|
||||||
{
|
{
|
||||||
|
|
|
@ -190,19 +190,6 @@ describe('useMatrixHistogram', () => {
|
||||||
expect(mockEndTracking).toHaveBeenCalledWith('success');
|
expect(mockEndTracking).toHaveBeenCalledWith('success');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should end tracking error when the partial request is invalid', () => {
|
|
||||||
(useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({
|
|
||||||
subscribe: ({ next }: { next: Function }) => next(null),
|
|
||||||
});
|
|
||||||
|
|
||||||
renderHook(useMatrixHistogram, {
|
|
||||||
initialProps: props,
|
|
||||||
wrapper: TestProviders,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(mockEndTracking).toHaveBeenCalledWith('invalid');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should end tracking error when the request fails', () => {
|
it('should end tracking error when the request fails', () => {
|
||||||
(useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({
|
(useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({
|
||||||
subscribe: ({ error }: { error: Function }) => error('some error'),
|
subscribe: ({ error }: { error: Function }) => error('some error'),
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { getOr, noop } from 'lodash/fp';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isErrorResponse, isCompleteResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import type { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types';
|
import type { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types';
|
||||||
import type { inputsModel } from '../../store';
|
import type { inputsModel } from '../../store';
|
||||||
import { createFilter } from '../helpers';
|
import { createFilter } from '../helpers';
|
||||||
|
@ -92,7 +92,7 @@ export const useMatrixHistogram = ({
|
||||||
...(isPtrIncluded != null ? { isPtrIncluded } : {}),
|
...(isPtrIncluded != null ? { isPtrIncluded } : {}),
|
||||||
...(includeMissingData != null ? { includeMissingData } : {}),
|
...(includeMissingData != null ? { includeMissingData } : {}),
|
||||||
});
|
});
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const [matrixHistogramResponse, setMatrixHistogramResponse] = useState<UseMatrixHistogramArgs>({
|
const [matrixHistogramResponse, setMatrixHistogramResponse] = useState<UseMatrixHistogramArgs>({
|
||||||
data: [],
|
data: [],
|
||||||
|
@ -138,11 +138,6 @@ export const useMatrixHistogram = ({
|
||||||
}));
|
}));
|
||||||
endTracking('success');
|
endTracking('success');
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_MATRIX_HISTOGRAM);
|
|
||||||
endTracking('invalid');
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -160,7 +155,7 @@ export const useMatrixHistogram = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, histogramType, addWarning, addError, errorMessage, startTracking]
|
[data.search, histogramType, addError, errorMessage, startTracking]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -273,14 +273,18 @@ describe('useSearchStrategy', () => {
|
||||||
expect(mockEndTracking).toBeCalledWith('success');
|
expect(mockEndTracking).toBeCalledWith('success');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should track invalid search result', () => {
|
it('should handle search error', () => {
|
||||||
mockResponse.mockReturnValueOnce({}); // mock invalid empty response
|
mockResponse.mockImplementation(() => {
|
||||||
|
throw new Error(
|
||||||
|
'simulated search response error, which could be 1) undefined response, 2) response without rawResponse, or 3) partial response'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const { result } = renderHook(() => useSearch<FactoryQueryTypes>(factoryQueryType));
|
const { result } = renderHook(() => useSearch<FactoryQueryTypes>(factoryQueryType));
|
||||||
result.current({ request, abortSignal: new AbortController().signal });
|
result.current({ request, abortSignal: new AbortController().signal });
|
||||||
|
|
||||||
expect(mockStartTracking).toBeCalledTimes(1);
|
expect(mockStartTracking).toBeCalledTimes(1);
|
||||||
expect(mockEndTracking).toBeCalledWith('invalid');
|
expect(mockEndTracking).toBeCalledWith('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should track error search result', () => {
|
it('should track error search result', () => {
|
||||||
|
@ -310,14 +314,5 @@ describe('useSearchStrategy', () => {
|
||||||
expect(mockEndTracking).toBeCalledTimes(1);
|
expect(mockEndTracking).toBeCalledTimes(1);
|
||||||
expect(mockEndTracking).toBeCalledWith('aborted');
|
expect(mockEndTracking).toBeCalledWith('aborted');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show toast warning when the API returns partial invalid response', () => {
|
|
||||||
mockResponse.mockReturnValueOnce({}); // mock invalid empty response
|
|
||||||
|
|
||||||
const { result } = renderHook(() => useSearch<FactoryQueryTypes>(factoryQueryType));
|
|
||||||
result.current({ request, abortSignal: new AbortController().signal });
|
|
||||||
|
|
||||||
expect(mockAddToastWarning).toBeCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,7 +47,6 @@ export const useSearch = <QueryType extends FactoryQueryTypes>(
|
||||||
factoryQueryType: QueryType
|
factoryQueryType: QueryType
|
||||||
): UseSearchFunction<QueryType> => {
|
): UseSearchFunction<QueryType> => {
|
||||||
const { data } = useKibana().services;
|
const { data } = useKibana().services;
|
||||||
const { addWarning } = useAppToasts();
|
|
||||||
const { startTracking } = useTrackHttpRequest();
|
const { startTracking } = useTrackHttpRequest();
|
||||||
|
|
||||||
const search = useCallback<UseSearchFunction<QueryType>>(
|
const search = useCallback<UseSearchFunction<QueryType>>(
|
||||||
|
@ -65,16 +64,11 @@ export const useSearch = <QueryType extends FactoryQueryTypes>(
|
||||||
abortSignal,
|
abortSignal,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.pipe(filter((response) => isErrorResponse(response) || isCompleteResponse(response)));
|
.pipe(filter((response) => isCompleteResponse(response)));
|
||||||
|
|
||||||
observable.subscribe({
|
observable.subscribe({
|
||||||
next: (response) => {
|
next: (response) => {
|
||||||
if (isErrorResponse(response)) {
|
endTracking('success');
|
||||||
addWarning(i18n.INVALID_RESPONSE_WARNING_SEARCH_STRATEGY(factoryQueryType));
|
|
||||||
endTracking('invalid');
|
|
||||||
} else {
|
|
||||||
endTracking('success');
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
error: () => {
|
error: () => {
|
||||||
endTracking(abortSignal.aborted ? 'aborted' : 'error');
|
endTracking(abortSignal.aborted ? 'aborted' : 'error');
|
||||||
|
@ -83,7 +77,7 @@ export const useSearch = <QueryType extends FactoryQueryTypes>(
|
||||||
|
|
||||||
return observable;
|
return observable;
|
||||||
},
|
},
|
||||||
[addWarning, data.search, factoryQueryType, startTracking]
|
[data.search, factoryQueryType, startTracking]
|
||||||
);
|
);
|
||||||
|
|
||||||
return search;
|
return search;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { noop } from 'lodash/fp';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
||||||
import type { inputsModel } from '../../../../../common/store';
|
import type { inputsModel } from '../../../../../common/store';
|
||||||
import { createFilter } from '../../../../../common/containers/helpers';
|
import { createFilter } from '../../../../../common/containers/helpers';
|
||||||
|
@ -69,7 +69,7 @@ export const useNetworkKpiDns = ({
|
||||||
isInspected: false,
|
isInspected: false,
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
});
|
});
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const networkKpiDnsSearch = useCallback(
|
const networkKpiDnsSearch = useCallback(
|
||||||
(request: NetworkKpiDnsRequestOptions | null) => {
|
(request: NetworkKpiDnsRequestOptions | null) => {
|
||||||
|
@ -97,10 +97,6 @@ export const useNetworkKpiDns = ({
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
}));
|
}));
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_NETWORK_KPI_DNS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -117,7 +113,7 @@ export const useNetworkKpiDns = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning, skip]
|
[data.search, addError, skip]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { noop } from 'lodash/fp';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
||||||
import type { inputsModel } from '../../../../../common/store';
|
import type { inputsModel } from '../../../../../common/store';
|
||||||
import { createFilter } from '../../../../../common/containers/helpers';
|
import { createFilter } from '../../../../../common/containers/helpers';
|
||||||
|
@ -70,7 +70,7 @@ export const useNetworkKpiNetworkEvents = ({
|
||||||
isInspected: false,
|
isInspected: false,
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
});
|
});
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const networkKpiNetworkEventsSearch = useCallback(
|
const networkKpiNetworkEventsSearch = useCallback(
|
||||||
(request: NetworkKpiNetworkEventsRequestOptions | null) => {
|
(request: NetworkKpiNetworkEventsRequestOptions | null) => {
|
||||||
|
@ -101,10 +101,6 @@ export const useNetworkKpiNetworkEvents = ({
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
}));
|
}));
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_NETWORK_KPI_NETWORK_EVENTS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -121,7 +117,7 @@ export const useNetworkKpiNetworkEvents = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning, skip]
|
[data.search, addError, skip]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { noop } from 'lodash/fp';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
||||||
import type { inputsModel } from '../../../../../common/store';
|
import type { inputsModel } from '../../../../../common/store';
|
||||||
import { createFilter } from '../../../../../common/containers/helpers';
|
import { createFilter } from '../../../../../common/containers/helpers';
|
||||||
|
@ -70,7 +70,7 @@ export const useNetworkKpiTlsHandshakes = ({
|
||||||
isInspected: false,
|
isInspected: false,
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
});
|
});
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const networkKpiTlsHandshakesSearch = useCallback(
|
const networkKpiTlsHandshakesSearch = useCallback(
|
||||||
(request: NetworkKpiTlsHandshakesRequestOptions | null) => {
|
(request: NetworkKpiTlsHandshakesRequestOptions | null) => {
|
||||||
|
@ -100,10 +100,6 @@ export const useNetworkKpiTlsHandshakes = ({
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
}));
|
}));
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_NETWORK_KPI_TLS_HANDSHAKES);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -120,7 +116,7 @@ export const useNetworkKpiTlsHandshakes = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning, skip]
|
[data.search, addError, skip]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { noop } from 'lodash/fp';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
||||||
import type { inputsModel } from '../../../../../common/store';
|
import type { inputsModel } from '../../../../../common/store';
|
||||||
import { createFilter } from '../../../../../common/containers/helpers';
|
import { createFilter } from '../../../../../common/containers/helpers';
|
||||||
|
@ -70,7 +70,7 @@ export const useNetworkKpiUniqueFlows = ({
|
||||||
isInspected: false,
|
isInspected: false,
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
});
|
});
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const networkKpiUniqueFlowsSearch = useCallback(
|
const networkKpiUniqueFlowsSearch = useCallback(
|
||||||
(request: NetworkKpiUniqueFlowsRequestOptions | null) => {
|
(request: NetworkKpiUniqueFlowsRequestOptions | null) => {
|
||||||
|
@ -100,10 +100,6 @@ export const useNetworkKpiUniqueFlows = ({
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
}));
|
}));
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_NETWORK_KPI_UNIQUE_FLOWS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -120,7 +116,7 @@ export const useNetworkKpiUniqueFlows = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning, skip]
|
[data.search, addError, skip]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { noop } from 'lodash/fp';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
import { useAppToasts } from '../../../../../common/hooks/use_app_toasts';
|
||||||
import type { inputsModel } from '../../../../../common/store';
|
import type { inputsModel } from '../../../../../common/store';
|
||||||
import { createFilter } from '../../../../../common/containers/helpers';
|
import { createFilter } from '../../../../../common/containers/helpers';
|
||||||
|
@ -77,7 +77,7 @@ export const useNetworkKpiUniquePrivateIps = ({
|
||||||
isInspected: false,
|
isInspected: false,
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
});
|
});
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const networkKpiUniquePrivateIpsSearch = useCallback(
|
const networkKpiUniquePrivateIpsSearch = useCallback(
|
||||||
(request: NetworkKpiUniquePrivateIpsRequestOptions | null) => {
|
(request: NetworkKpiUniquePrivateIpsRequestOptions | null) => {
|
||||||
|
@ -112,10 +112,6 @@ export const useNetworkKpiUniquePrivateIps = ({
|
||||||
refetch: refetch.current,
|
refetch: refetch.current,
|
||||||
}));
|
}));
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_NETWORK_KPI_UNIQUE_PRIVATE_IPS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -132,7 +128,7 @@ export const useNetworkKpiUniquePrivateIps = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning, skip]
|
[data.search, addError, skip]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { filter } from 'rxjs/operators';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useObservable, withOptionalSignal } from '@kbn/securitysolution-hook-utils';
|
import { useObservable, withOptionalSignal } from '@kbn/securitysolution-hook-utils';
|
||||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public';
|
import { isCompleteResponse } from '@kbn/data-plugin/public';
|
||||||
import { useKibana } from '../../../common/lib/kibana';
|
import { useKibana } from '../../../common/lib/kibana';
|
||||||
import type {
|
import type {
|
||||||
Bucket,
|
Bucket,
|
||||||
|
@ -51,7 +51,7 @@ export const getTiDataSourcesComplete = (
|
||||||
): Observable<CtiDataSourceStrategyResponse> => {
|
): Observable<CtiDataSourceStrategyResponse> => {
|
||||||
return getTiDataSources(props).pipe(
|
return getTiDataSources(props).pipe(
|
||||||
filter((response) => {
|
filter((response) => {
|
||||||
return isErrorResponse(response) || isCompleteResponse(response);
|
return isCompleteResponse(response);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ import ReactDOM from 'react-dom';
|
||||||
import deepEqual from 'fast-deep-equal';
|
import deepEqual from 'fast-deep-equal';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import { EntityType } from '@kbn/timelines-plugin/common';
|
import { EntityType } from '@kbn/timelines-plugin/common';
|
||||||
import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
|
import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
|
||||||
import { useKibana } from '../../../common/lib/kibana';
|
import { useKibana } from '../../../common/lib/kibana';
|
||||||
|
@ -62,7 +62,7 @@ export const useTimelineEventsDetails = ({
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [timelineDetailsRequest, setTimelineDetailsRequest] =
|
const [timelineDetailsRequest, setTimelineDetailsRequest] =
|
||||||
useState<TimelineEventsDetailsRequestOptions | null>(null);
|
useState<TimelineEventsDetailsRequestOptions | null>(null);
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const [timelineDetailsResponse, setTimelineDetailsResponse] =
|
const [timelineDetailsResponse, setTimelineDetailsResponse] =
|
||||||
useState<EventsArgs['detailsData']>(null);
|
useState<EventsArgs['detailsData']>(null);
|
||||||
|
@ -99,10 +99,6 @@ export const useTimelineEventsDetails = ({
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.FAIL_TIMELINE_DETAILS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -117,7 +113,7 @@ export const useTimelineEventsDetails = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning, skip]
|
[data.search, addError, skip]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { useDispatch } from 'react-redux';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import type { DataView } from '@kbn/data-plugin/common';
|
import type { DataView } from '@kbn/data-plugin/common';
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import type { ESQuery } from '../../../common/typed_json';
|
import type { ESQuery } from '../../../common/typed_json';
|
||||||
|
|
||||||
import type { inputsModel } from '../../common/store';
|
import type { inputsModel } from '../../common/store';
|
||||||
|
@ -32,7 +32,6 @@ import type {
|
||||||
} from '../../../common/search_strategy';
|
} from '../../../common/search_strategy';
|
||||||
import { Direction, TimelineEventsQueries } from '../../../common/search_strategy';
|
import { Direction, TimelineEventsQueries } from '../../../common/search_strategy';
|
||||||
import type { InspectResponse } from '../../types';
|
import type { InspectResponse } from '../../types';
|
||||||
import * as i18n from './translations';
|
|
||||||
import type { KueryFilterQueryKind } from '../../../common/types/timeline';
|
import type { KueryFilterQueryKind } from '../../../common/types/timeline';
|
||||||
import { TimelineId } from '../../../common/types/timeline';
|
import { TimelineId } from '../../../common/types/timeline';
|
||||||
import { useRouteSpy } from '../../common/utils/route/use_route_spy';
|
import { useRouteSpy } from '../../common/utils/route/use_route_spy';
|
||||||
|
@ -42,7 +41,6 @@ import type {
|
||||||
TimelineEqlRequestOptions,
|
TimelineEqlRequestOptions,
|
||||||
TimelineEqlResponse,
|
TimelineEqlResponse,
|
||||||
} from '../../../common/search_strategy/timeline/events/eql';
|
} from '../../../common/search_strategy/timeline/events/eql';
|
||||||
import { useAppToasts } from '../../common/hooks/use_app_toasts';
|
|
||||||
import { useTrackHttpRequest } from '../../common/lib/apm/use_track_http_request';
|
import { useTrackHttpRequest } from '../../common/lib/apm/use_track_http_request';
|
||||||
import { APP_UI_ID } from '../../../common/constants';
|
import { APP_UI_ID } from '../../../common/constants';
|
||||||
|
|
||||||
|
@ -221,8 +219,6 @@ export const useTimelineEventsHandler = ({
|
||||||
}
|
}
|
||||||
}, [setUpdated, timelineResponse.updatedAt]);
|
}, [setUpdated, timelineResponse.updatedAt]);
|
||||||
|
|
||||||
const { addWarning } = useAppToasts();
|
|
||||||
|
|
||||||
const timelineSearch = useCallback(
|
const timelineSearch = useCallback(
|
||||||
async (
|
async (
|
||||||
request: TimelineRequest<typeof language> | null,
|
request: TimelineRequest<typeof language> | null,
|
||||||
|
@ -275,11 +271,6 @@ export const useTimelineEventsHandler = ({
|
||||||
return newTimelineResponse;
|
return newTimelineResponse;
|
||||||
});
|
});
|
||||||
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
endTracking('invalid');
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.ERROR_TIMELINE_EVENTS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -335,17 +326,7 @@ export const useTimelineEventsHandler = ({
|
||||||
await asyncSearch();
|
await asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[
|
[pageName, skip, id, startTracking, data.search, dataViewId, refetchGrid, wrappedLoadPage]
|
||||||
pageName,
|
|
||||||
skip,
|
|
||||||
id,
|
|
||||||
startTracking,
|
|
||||||
data.search,
|
|
||||||
dataViewId,
|
|
||||||
addWarning,
|
|
||||||
refetchGrid,
|
|
||||||
wrappedLoadPage,
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import deepEqual from 'fast-deep-equal';
|
import deepEqual from 'fast-deep-equal';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public';
|
import { isCompleteResponse } from '@kbn/data-plugin/public';
|
||||||
import type { inputsModel } from '../../../common/store';
|
import type { inputsModel } from '../../../common/store';
|
||||||
import { useKibana } from '../../../common/lib/kibana';
|
import { useKibana } from '../../../common/lib/kibana';
|
||||||
import type {
|
import type {
|
||||||
|
@ -46,7 +46,7 @@ export const useTimelineKpis = ({
|
||||||
);
|
);
|
||||||
const [timelineKpiResponse, setTimelineKpiResponse] =
|
const [timelineKpiResponse, setTimelineKpiResponse] =
|
||||||
useState<TimelineKpiStrategyResponse | null>(null);
|
useState<TimelineKpiStrategyResponse | null>(null);
|
||||||
const { addError, addWarning } = useAppToasts();
|
const { addError } = useAppToasts();
|
||||||
|
|
||||||
const timelineKpiSearch = useCallback(
|
const timelineKpiSearch = useCallback(
|
||||||
(request: TimelineKpiStrategyRequest | null) => {
|
(request: TimelineKpiStrategyRequest | null) => {
|
||||||
|
@ -68,10 +68,6 @@ export const useTimelineKpis = ({
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setTimelineKpiResponse(response);
|
setTimelineKpiResponse(response);
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
setLoading(false);
|
|
||||||
addWarning(i18n.FAIL_TIMELINE_KPI_DETAILS);
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
@ -86,7 +82,7 @@ export const useTimelineKpis = ({
|
||||||
asyncSearch();
|
asyncSearch();
|
||||||
refetch.current = asyncSearch;
|
refetch.current = asyncSearch;
|
||||||
},
|
},
|
||||||
[data.search, addError, addWarning]
|
[data.search, addError]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import {
|
||||||
IEsSearchRequest,
|
IEsSearchRequest,
|
||||||
IKibanaSearchResponse,
|
IKibanaSearchResponse,
|
||||||
isCompleteResponse,
|
isCompleteResponse,
|
||||||
isErrorResponse,
|
|
||||||
} from '@kbn/data-plugin/common';
|
} from '@kbn/data-plugin/common';
|
||||||
import { ISearchStart } from '@kbn/data-plugin/public';
|
import { ISearchStart } from '@kbn/data-plugin/public';
|
||||||
import { RequestAdapter } from '@kbn/inspector-plugin/common';
|
import { RequestAdapter } from '@kbn/inspector-plugin/common';
|
||||||
|
@ -97,9 +96,6 @@ export const search = async <TResponse, T = {}>(
|
||||||
if (isCompleteResponse(response)) {
|
if (isCompleteResponse(response)) {
|
||||||
inspect.recordRequestCompletion(searchRequest, response);
|
inspect.recordRequestCompletion(searchRequest, response);
|
||||||
resolve(response.rawResponse);
|
resolve(response.rawResponse);
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
inspect.recordRequestError(response);
|
|
||||||
reject(response);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (requestError) => {
|
error: (requestError) => {
|
||||||
|
|
|
@ -33569,7 +33569,6 @@
|
||||||
"xpack.securitySolution.kubernetes.columnPod": "Pod",
|
"xpack.securitySolution.kubernetes.columnPod": "Pod",
|
||||||
"xpack.securitySolution.kubernetes.columnSessionStart": "Date de démarrage",
|
"xpack.securitySolution.kubernetes.columnSessionStart": "Date de démarrage",
|
||||||
"xpack.securitySolution.landing.threatHunting.hostsDescription": "Aperçu complet de tous les hôtes et événements de sécurité des hôtes.",
|
"xpack.securitySolution.landing.threatHunting.hostsDescription": "Aperçu complet de tous les hôtes et événements de sécurité des hôtes.",
|
||||||
"xpack.securitySolution.lastEventTime.errorSearchDescription": "Une erreur s'est produite sur la recherche de dernière heure de l'événement",
|
|
||||||
"xpack.securitySolution.lastEventTime.failSearchDescription": "Impossible de lancer une recherche sur la dernière heure de l'événement",
|
"xpack.securitySolution.lastEventTime.failSearchDescription": "Impossible de lancer une recherche sur la dernière heure de l'événement",
|
||||||
"xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "Aucune donnée à afficher",
|
"xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "Aucune donnée à afficher",
|
||||||
"xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "Votre licence ne prend pas en charge le Machine Learning. Veuillez mettre votre licence à niveau.",
|
"xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "Votre licence ne prend pas en charge le Machine Learning. Veuillez mettre votre licence à niveau.",
|
||||||
|
|
|
@ -33568,7 +33568,6 @@
|
||||||
"xpack.securitySolution.kubernetes.columnPod": "ポッド",
|
"xpack.securitySolution.kubernetes.columnPod": "ポッド",
|
||||||
"xpack.securitySolution.kubernetes.columnSessionStart": "開始日",
|
"xpack.securitySolution.kubernetes.columnSessionStart": "開始日",
|
||||||
"xpack.securitySolution.landing.threatHunting.hostsDescription": "すべてのホストとホスト関連のセキュリティイベントに関する包括的な概要。",
|
"xpack.securitySolution.landing.threatHunting.hostsDescription": "すべてのホストとホスト関連のセキュリティイベントに関する包括的な概要。",
|
||||||
"xpack.securitySolution.lastEventTime.errorSearchDescription": "前回のイベント時刻検索でエラーが発生しました。",
|
|
||||||
"xpack.securitySolution.lastEventTime.failSearchDescription": "前回のイベント時刻で検索を実行できませんでした",
|
"xpack.securitySolution.lastEventTime.failSearchDescription": "前回のイベント時刻で検索を実行できませんでした",
|
||||||
"xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "表示するデータがありません",
|
"xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "表示するデータがありません",
|
||||||
"xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "ご使用のライセンスは機械翻訳をサポートしていません。ライセンスをアップグレードしてください。",
|
"xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "ご使用のライセンスは機械翻訳をサポートしていません。ライセンスをアップグレードしてください。",
|
||||||
|
|
|
@ -33564,7 +33564,6 @@
|
||||||
"xpack.securitySolution.kubernetes.columnPod": "Pod",
|
"xpack.securitySolution.kubernetes.columnPod": "Pod",
|
||||||
"xpack.securitySolution.kubernetes.columnSessionStart": "开始日期",
|
"xpack.securitySolution.kubernetes.columnSessionStart": "开始日期",
|
||||||
"xpack.securitySolution.landing.threatHunting.hostsDescription": "所有主机和主机相关安全事件的全面概览。",
|
"xpack.securitySolution.landing.threatHunting.hostsDescription": "所有主机和主机相关安全事件的全面概览。",
|
||||||
"xpack.securitySolution.lastEventTime.errorSearchDescription": "搜索上次事件时间时发生错误",
|
|
||||||
"xpack.securitySolution.lastEventTime.failSearchDescription": "无法对上次事件时间执行搜索",
|
"xpack.securitySolution.lastEventTime.failSearchDescription": "无法对上次事件时间执行搜索",
|
||||||
"xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "没有可显示的数据",
|
"xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "没有可显示的数据",
|
||||||
"xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "您的许可证不支持 Machine Learning。请升级您的许可证。",
|
"xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "您的许可证不支持 Machine Learning。请升级您的许可证。",
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { of } from 'rxjs';
|
import { of, throwError } from 'rxjs';
|
||||||
import { act, renderHook } from '@testing-library/react-hooks';
|
import { act, renderHook } from '@testing-library/react-hooks';
|
||||||
import { useFetchAlerts, FetchAlertsArgs, FetchAlertResp } from './use_fetch_alerts';
|
import { useFetchAlerts, FetchAlertsArgs, FetchAlertResp } from './use_fetch_alerts';
|
||||||
import { useKibana } from '../../../../common/lib/kibana';
|
import { useKibana } from '../../../../common/lib/kibana';
|
||||||
|
@ -286,9 +286,10 @@ describe('useFetchAlerts', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the correct response if the request is undefined', () => {
|
it('handles search error', () => {
|
||||||
// @ts-expect-error
|
const obs$ = throwError(
|
||||||
const obs$ = of<IKibanaSearchResponse>(undefined);
|
'simulated search response error, which could be 1) undefined response, 2) response without rawResponse, or 3) partial response'
|
||||||
|
);
|
||||||
dataSearchMock.mockReturnValue(obs$);
|
dataSearchMock.mockReturnValue(obs$);
|
||||||
const { result } = renderHook(() => useFetchAlerts(args));
|
const { result } = renderHook(() => useFetchAlerts(args));
|
||||||
|
|
||||||
|
@ -308,7 +309,7 @@ describe('useFetchAlerts', () => {
|
||||||
expect(showErrorMock).toHaveBeenCalled();
|
expect(showErrorMock).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the correct response if the request is running', () => {
|
it('returns the correct response if the search response is running', () => {
|
||||||
const obs$ = of<IKibanaSearchResponse>({ ...searchResponse, isRunning: true });
|
const obs$ = of<IKibanaSearchResponse>({ ...searchResponse, isRunning: true });
|
||||||
dataSearchMock.mockReturnValue(obs$);
|
dataSearchMock.mockReturnValue(obs$);
|
||||||
const { result } = renderHook(() => useFetchAlerts(args));
|
const { result } = renderHook(() => useFetchAlerts(args));
|
||||||
|
@ -327,47 +328,6 @@ describe('useFetchAlerts', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the correct response if the request is partial', () => {
|
|
||||||
const obs$ = of<IKibanaSearchResponse>({ ...searchResponse, isPartial: true });
|
|
||||||
dataSearchMock.mockReturnValue(obs$);
|
|
||||||
const { result } = renderHook(() => useFetchAlerts(args));
|
|
||||||
|
|
||||||
expect(result.current).toEqual([
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
...expectedResponse,
|
|
||||||
alerts: [],
|
|
||||||
getInspectQuery: expect.anything(),
|
|
||||||
refetch: expect.anything(),
|
|
||||||
isInitializing: true,
|
|
||||||
totalAlerts: -1,
|
|
||||||
updatedAt: 0,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
expect(showErrorMock).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns the correct response if there is no rawResponse', () => {
|
|
||||||
// @ts-expect-error
|
|
||||||
const obs$ = of<IKibanaSearchResponse>({ id: '1', isRunning: true, isPartial: false });
|
|
||||||
dataSearchMock.mockReturnValue(obs$);
|
|
||||||
const { result } = renderHook(() => useFetchAlerts(args));
|
|
||||||
|
|
||||||
expect(result.current).toEqual([
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
...expectedResponse,
|
|
||||||
alerts: [],
|
|
||||||
getInspectQuery: expect.anything(),
|
|
||||||
refetch: expect.anything(),
|
|
||||||
isInitializing: true,
|
|
||||||
totalAlerts: -1,
|
|
||||||
updatedAt: 0,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
expect(showErrorMock).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns the correct total alerts if the total alerts in the response is an object', () => {
|
it('returns the correct total alerts if the total alerts in the response is an object', () => {
|
||||||
const obs$ = of<IKibanaSearchResponse>({
|
const obs$ = of<IKibanaSearchResponse>({
|
||||||
...searchResponse,
|
...searchResponse,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { noop } from 'lodash';
|
||||||
import { useCallback, useEffect, useReducer, useRef, useMemo } from 'react';
|
import { useCallback, useEffect, useReducer, useRef, useMemo } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
|
import { isCompleteResponse } from '@kbn/data-plugin/common';
|
||||||
import type {
|
import type {
|
||||||
RuleRegistrySearchRequest,
|
RuleRegistrySearchRequest,
|
||||||
RuleRegistrySearchRequestPagination,
|
RuleRegistrySearchRequestPagination,
|
||||||
|
@ -27,7 +27,6 @@ import type {
|
||||||
import type { Alert, Alerts, GetInspectQuery, InspectQuery } from '../../../../types';
|
import type { Alert, Alerts, GetInspectQuery, InspectQuery } from '../../../../types';
|
||||||
import { useKibana } from '../../../../common/lib/kibana';
|
import { useKibana } from '../../../../common/lib/kibana';
|
||||||
import { DefaultSort } from './constants';
|
import { DefaultSort } from './constants';
|
||||||
import * as i18n from './translations';
|
|
||||||
|
|
||||||
export interface FetchAlertsArgs {
|
export interface FetchAlertsArgs {
|
||||||
featureIds: ValidFeatureId[];
|
featureIds: ValidFeatureId[];
|
||||||
|
@ -260,10 +259,6 @@ const useFetchAlerts = ({
|
||||||
totalAlerts,
|
totalAlerts,
|
||||||
});
|
});
|
||||||
searchSubscription$.current.unsubscribe();
|
searchSubscription$.current.unsubscribe();
|
||||||
} else if (isErrorResponse(response)) {
|
|
||||||
dispatch({ type: 'loading', loading: false });
|
|
||||||
data.search.showError(new Error(i18n.ERROR_FETCH_ALERTS));
|
|
||||||
searchSubscription$.current.unsubscribe();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue