Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ export declare class SearchInterceptor
| --- | --- | --- |
| [getTimeoutMode()](./kibana-plugin-plugins-data-public.searchinterceptor.gettimeoutmode.md) | | |
| [handleSearchError(e, timeoutSignal, options)](./kibana-plugin-plugins-data-public.searchinterceptor.handlesearcherror.md) | | |
| [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given <code>search</code> method. Overrides the <code>AbortSignal</code> with one that will abort either when <code>cancelPending</code> is called, when the request times out, or when the original <code>AbortSignal</code> is aborted. Updates <code>pendingCount$</code> when the request is started/finalized. |
| [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given <code>search</code> method. Overrides the <code>AbortSignal</code> with one that will abort either when the request times out, or when the original <code>AbortSignal</code> is aborted. Updates <code>pendingCount$</code> when the request is started/finalized. |
| [showError(e)](./kibana-plugin-plugins-data-public.searchinterceptor.showerror.md) | | |

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## SearchInterceptor.search() method

Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort either when `cancelPending` is called, when the request times out, or when the original `AbortSignal` is aborted. Updates `pendingCount$` when the request is started/finalized.
Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort either when the request times out, or when the original `AbortSignal` is aborted. Updates `pendingCount$` when the request is started/finalized.

<b>Signature:</b>

Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ export type {
ISessionService,
SearchSessionInfoProvider,
ISessionsClient,
SearchUsageCollector,
} from './search';

export { ISearchOptions, isErrorResponse, isCompleteResponse, isPartialResponse } from '../common';
Expand Down
66 changes: 50 additions & 16 deletions src/plugins/data/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1669,7 +1669,7 @@ export interface ISearchSetup {
aggs: AggsSetup;
session: ISessionService;
sessionsClient: ISessionsClient;
// Warning: (ae-forgotten-export) The symbol "SearchUsageCollector" needs to be exported by the entry point index.d.ts
// Warning: (ae-incompatible-release-tags) The symbol "usageCollector" is marked as @public, but its signature references "SearchUsageCollector" which is marked as @internal
//
// (undocumented)
usageCollector?: SearchUsageCollector;
Expand Down Expand Up @@ -2337,6 +2337,8 @@ export interface SearchInterceptorDeps {
toasts: ToastsSetup;
// (undocumented)
uiSettings: CoreSetup_2['uiSettings'];
// Warning: (ae-incompatible-release-tags) The symbol "usageCollector" is marked as @public, but its signature references "SearchUsageCollector" which is marked as @internal
//
// (undocumented)
usageCollector?: SearchUsageCollector;
}
Expand Down Expand Up @@ -2461,6 +2463,38 @@ export class SearchTimeoutError extends KbnError {
mode: TimeoutErrorMode;
}

// @internal (undocumented)
export interface SearchUsageCollector {
// (undocumented)
trackQueryTimedOut: () => Promise<void>;
// (undocumented)
trackSessionCancelled: () => Promise<void>;
// (undocumented)
trackSessionDeleted: () => Promise<void>;
// (undocumented)
trackSessionExtended: () => Promise<void>;
// (undocumented)
trackSessionIndicatorSaveDisabled: () => Promise<void>;
// (undocumented)
trackSessionIndicatorTourLoading: () => Promise<void>;
// (undocumented)
trackSessionIndicatorTourRestored: () => Promise<void>;
// (undocumented)
trackSessionIsRestored: () => Promise<void>;
// (undocumented)
trackSessionReloaded: () => Promise<void>;
// (undocumented)
trackSessionSavedResults: () => Promise<void>;
// (undocumented)
trackSessionSentToBackground: () => Promise<void>;
// (undocumented)
trackSessionsListLoaded: () => Promise<void>;
// (undocumented)
trackSessionViewRestored: () => Promise<void>;
// (undocumented)
trackViewSessionsList: () => Promise<void>;
}

// Warning: (ae-missing-release-tag) "SortDirection" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
Expand Down Expand Up @@ -2615,21 +2649,21 @@ export const UI_SETTINGS: {
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:425:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/search/session/session_service.ts:42:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,66 @@ describe('Search Usage Collector', () => {
);
});

test('tracks query cancellation', async () => {
await usageCollector.trackQueriesCancelled();
test('tracks session sent to background', async () => {
await usageCollector.trackSessionSentToBackground();
expect(mockUsageCollectionSetup.reportUiCounter).toHaveBeenCalled();
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.LOADED);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][2]).toBe(
SEARCH_EVENT_TYPE.SESSION_SENT_TO_BACKGROUND
);
});

test('tracks session saved results', async () => {
await usageCollector.trackSessionSavedResults();
expect(mockUsageCollectionSetup.reportUiCounter).toHaveBeenCalled();
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][2]).toBe(
SEARCH_EVENT_TYPE.SESSION_SAVED_RESULTS
);
});

test('tracks session view restored', async () => {
await usageCollector.trackSessionViewRestored();
expect(mockUsageCollectionSetup.reportUiCounter).toHaveBeenCalled();
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][2]).toBe(
SEARCH_EVENT_TYPE.SESSION_VIEW_RESTORED
);
});

test('tracks session is restored', async () => {
await usageCollector.trackSessionIsRestored();
expect(mockUsageCollectionSetup.reportUiCounter).toHaveBeenCalled();
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][2]).toBe(
SEARCH_EVENT_TYPE.SESSION_IS_RESTORED
);
});

test('tracks session reloaded', async () => {
await usageCollector.trackSessionReloaded();
expect(mockUsageCollectionSetup.reportUiCounter).toHaveBeenCalled();
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][2]).toBe(
SEARCH_EVENT_TYPE.SESSION_RELOADED
);
});

test('tracks session extended', async () => {
await usageCollector.trackSessionExtended();
expect(mockUsageCollectionSetup.reportUiCounter).toHaveBeenCalled();
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][2]).toBe(
SEARCH_EVENT_TYPE.SESSION_EXTENDED
);
});

test('tracks session cancelled', async () => {
await usageCollector.trackSessionCancelled();
expect(mockUsageCollectionSetup.reportUiCounter).toHaveBeenCalled();
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK);
expect(mockUsageCollectionSetup.reportUiCounter.mock.calls[0][2]).toBe(
SEARCH_EVENT_TYPE.QUERIES_CANCELLED
SEARCH_EVENT_TYPE.SESSION_CANCELLED
);
});
});
59 changes: 43 additions & 16 deletions src/plugins/data/public/search/collectors/create_usage_collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { first } from 'rxjs/operators';
import { UiCounterMetricType } from '@kbn/analytics';
import { StartServicesAccessor } from '../../../../../core/public';
import { METRIC_TYPE, UsageCollectionSetup } from '../../../../usage_collection/public';
import { SEARCH_EVENT_TYPE, SearchUsageCollector } from './types';
Expand All @@ -20,22 +21,48 @@ export const createUsageCollector = (
return application.currentAppId$.pipe(first()).toPromise();
};

return {
trackQueryTimedOut: async () => {
const currentApp = await getCurrentApp();
return usageCollection?.reportUiCounter(
currentApp!,
METRIC_TYPE.LOADED,
SEARCH_EVENT_TYPE.QUERY_TIMED_OUT
);
},
trackQueriesCancelled: async () => {
const getCollector = (metricType: UiCounterMetricType, eventType: SEARCH_EVENT_TYPE) => {
return async () => {
const currentApp = await getCurrentApp();
return usageCollection?.reportUiCounter(
currentApp!,
METRIC_TYPE.LOADED,
SEARCH_EVENT_TYPE.QUERIES_CANCELLED
);
},
return usageCollection?.reportUiCounter(currentApp!, metricType, eventType);
};
};

return {
trackQueryTimedOut: getCollector(METRIC_TYPE.LOADED, SEARCH_EVENT_TYPE.QUERY_TIMED_OUT),
trackSessionIndicatorTourLoading: getCollector(
METRIC_TYPE.LOADED,
SEARCH_EVENT_TYPE.SESSION_INDICATOR_TOUR_LOADING
),
trackSessionIndicatorTourRestored: getCollector(
METRIC_TYPE.LOADED,
SEARCH_EVENT_TYPE.SESSION_INDICATOR_TOUR_RESTORED
),
trackSessionIndicatorSaveDisabled: getCollector(
METRIC_TYPE.LOADED,
SEARCH_EVENT_TYPE.SESSION_INDICATOR_SAVE_DISABLED
),
trackSessionSentToBackground: getCollector(
METRIC_TYPE.CLICK,
SEARCH_EVENT_TYPE.SESSION_SENT_TO_BACKGROUND
),
trackSessionSavedResults: getCollector(
METRIC_TYPE.CLICK,
SEARCH_EVENT_TYPE.SESSION_SAVED_RESULTS
),
trackSessionViewRestored: getCollector(
METRIC_TYPE.CLICK,
SEARCH_EVENT_TYPE.SESSION_VIEW_RESTORED
),
trackSessionIsRestored: getCollector(METRIC_TYPE.CLICK, SEARCH_EVENT_TYPE.SESSION_IS_RESTORED),
trackSessionReloaded: getCollector(METRIC_TYPE.CLICK, SEARCH_EVENT_TYPE.SESSION_RELOADED),
trackSessionExtended: getCollector(METRIC_TYPE.CLICK, SEARCH_EVENT_TYPE.SESSION_EXTENDED),
trackSessionCancelled: getCollector(METRIC_TYPE.CLICK, SEARCH_EVENT_TYPE.SESSION_CANCELLED),
trackSessionDeleted: getCollector(METRIC_TYPE.CLICK, SEARCH_EVENT_TYPE.SESSION_DELETED),
trackViewSessionsList: getCollector(METRIC_TYPE.CLICK, SEARCH_EVENT_TYPE.SESSION_VIEW_LIST),
trackSessionsListLoaded: getCollector(
METRIC_TYPE.LOADED,
SEARCH_EVENT_TYPE.SESSIONS_LIST_LOADED
),
};
};
28 changes: 28 additions & 0 deletions src/plugins/data/public/search/collectors/mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { SearchUsageCollector } from './types';

export function createSearchUsageCollectorMock(): jest.Mocked<SearchUsageCollector> {
return {
trackQueryTimedOut: jest.fn(),
trackSessionIndicatorTourLoading: jest.fn(),
trackSessionIndicatorTourRestored: jest.fn(),
trackSessionIndicatorSaveDisabled: jest.fn(),
trackSessionSentToBackground: jest.fn(),
trackSessionSavedResults: jest.fn(),
trackSessionViewRestored: jest.fn(),
trackSessionIsRestored: jest.fn(),
trackSessionReloaded: jest.fn(),
trackSessionExtended: jest.fn(),
trackSessionCancelled: jest.fn(),
trackSessionDeleted: jest.fn(),
trackViewSessionsList: jest.fn(),
trackSessionsListLoaded: jest.fn(),
};
}
76 changes: 74 additions & 2 deletions src/plugins/data/public/search/collectors/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,84 @@
* Side Public License, v 1.
*/

/**
* @internal
*/
export enum SEARCH_EVENT_TYPE {
/**
* A search reached the timeout configured in UI setting search:timeout
*/
QUERY_TIMED_OUT = 'queryTimedOut',
QUERIES_CANCELLED = 'queriesCancelled',
/**
* The session indicator was automatically brought up because of a long running query
*/
SESSION_INDICATOR_TOUR_LOADING = 'sessionIndicatorTourLoading',
/**
* The session indicator was automatically brought up because of a restored session
*/
SESSION_INDICATOR_TOUR_RESTORED = 'sessionIndicatorTourRestored',
/**
* The session indicator was disabled because of a completion timeout
*/
SESSION_INDICATOR_SAVE_DISABLED = 'sessionIndicatorSaveDisabled',
/**
* The user clicked to continue a session in the background (prior to results completing)
*/
SESSION_SENT_TO_BACKGROUND = 'sessionSentToBackground',
/**
* The user clicked to save the session (after results completing)
*/
SESSION_SAVED_RESULTS = 'sessionSavedResults',
/**
* The user clicked to view a completed session
*/
SESSION_VIEW_RESTORED = 'sessionViewRestored',
/**
* The session was successfully restored upon a user navigating
*/
SESSION_IS_RESTORED = 'sessionIsRestored',
/**
* The user clicked to reload an expired/cancelled session
*/
SESSION_RELOADED = 'sessionReloaded',
/**
* The user clicked to extend the expiration of a session
*/
SESSION_EXTENDED = 'sessionExtended',
/**
* The user clicked to cancel a session
*/
SESSION_CANCELLED = 'sessionCancelled',
/**
* The user clicked to delete a session
*/
SESSION_DELETED = 'sessionDeleted',
/**
* The user clicked a link to view the list of sessions
*/
SESSION_VIEW_LIST = 'sessionViewList',
/**
* The user landed on the sessions management page
*/
SESSIONS_LIST_LOADED = 'sessionsListLoaded',
}

/**
* @internal
*/
export interface SearchUsageCollector {
trackQueryTimedOut: () => Promise<void>;
trackQueriesCancelled: () => Promise<void>;
trackSessionIndicatorTourLoading: () => Promise<void>;
trackSessionIndicatorTourRestored: () => Promise<void>;
trackSessionIndicatorSaveDisabled: () => Promise<void>;
trackSessionSentToBackground: () => Promise<void>;
trackSessionSavedResults: () => Promise<void>;
trackSessionViewRestored: () => Promise<void>;
trackSessionIsRestored: () => Promise<void>;
trackSessionReloaded: () => Promise<void>;
trackSessionExtended: () => Promise<void>;
trackSessionCancelled: () => Promise<void>;
trackSessionDeleted: () => Promise<void>;
trackViewSessionsList: () => Promise<void>;
trackSessionsListLoaded: () => Promise<void>;
}
8 changes: 7 additions & 1 deletion src/plugins/data/public/search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@

export * from './expressions';

export { ISearchSetup, ISearchStart, ISearchStartSearchSource, SearchEnhancements } from './types';
export {
ISearchSetup,
ISearchStart,
ISearchStartSearchSource,
SearchEnhancements,
SearchUsageCollector,
} from './types';

export {
ES_SEARCH_STRATEGY,
Expand Down
Loading