Skip to content

Commit

Permalink
Merge branch 'main' into renovate/main-@elasticcharts
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Jun 26, 2023
2 parents 29d0c97 + 2c24494 commit 41f6915
Show file tree
Hide file tree
Showing 120 changed files with 2,468 additions and 559 deletions.
2 changes: 2 additions & 0 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ enabled:
- x-pack/test/observability_api_integration/trial/config.ts
- x-pack/test/observability_api_integration/apis/config.ts
- x-pack/test/observability_functional/with_rac_write.config.ts
- x-pack/test/observability_onboarding_api_integration/basic/config.ts
- x-pack/test/observability_onboarding_api_integration/cloud/config.ts
- x-pack/test/plugin_api_integration/config.ts
- x-pack/test/plugin_functional/config.ts
- x-pack/test/reporting_api_integration/reporting_and_security.config.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
* Side Public License, v 1.
*/

export { RootRoute } from './root';
export { StatusHandler } from './status';
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

import { Server } from '@hapi/hapi';
import { duration } from 'moment';
import { URL } from 'url';
import fetch, { Response } from 'node-fetch';
import { loggerMock, MockedLogger } from '@kbn/logging-mocks';
import type { KibanaConfig } from '../kibana_config';
import { RootRoute } from './root';
import { StatusHandler } from './status';

describe('RootRoute', () => {
describe('StatusHandler', () => {
let kibanaConfig: KibanaConfig;
let logger: MockedLogger;
let server: Server;
Expand All @@ -30,7 +31,11 @@ describe('RootRoute', () => {
logger = loggerMock.create();

server = new Server();
server.route(new RootRoute(kibanaConfig, logger));
server.route({
method: 'GET',
path: '/',
handler: new StatusHandler(kibanaConfig, logger).handler,
});
await server.initialize();
});

Expand Down Expand Up @@ -248,5 +253,49 @@ describe('RootRoute', () => {
})
);
});

it('should call the host with the correct path', async () => {
kibanaConfig.hosts.splice(0, kibanaConfig.hosts.length);
kibanaConfig.hosts.push('http://localhost:5601', 'http://localhost:5602');

(fetch as jest.MockedFunction<typeof fetch>).mockResolvedValue(new Response('', ok));

await server.inject({
method: 'get',
url: '/',
});

expect(fetch).toHaveBeenCalledTimes(2);
expect(fetch).toHaveBeenCalledWith(
new URL('http://localhost:5601/api/status'),
expect.any(Object)
);
expect(fetch).toHaveBeenCalledWith(
new URL('http://localhost:5602/api/status'),
expect.any(Object)
);
});

it('should append the status path when path already present on the host', async () => {
kibanaConfig.hosts.splice(0, kibanaConfig.hosts.length);
kibanaConfig.hosts.push('http://localhost:5601/prefix', 'http://localhost:5602/other/path');

(fetch as jest.MockedFunction<typeof fetch>).mockResolvedValue(new Response('', ok));

await server.inject({
method: 'get',
url: '/',
});

expect(fetch).toHaveBeenCalledTimes(2);
expect(fetch).toHaveBeenCalledWith(
new URL('http://localhost:5601/prefix/api/status'),
expect.any(Object)
);
expect(fetch).toHaveBeenCalledWith(
new URL('http://localhost:5602/other/path/api/status'),
expect.any(Object)
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
* Side Public License, v 1.
*/

import { capitalize, chain, memoize, pick } from 'lodash';
import { capitalize, chain, memoize } from 'lodash';
import { Agent, AgentOptions } from 'https';
import { URL } from 'url';
import type { Request, ResponseObject, ResponseToolkit, ServerRoute } from '@hapi/hapi';
import type { Request, ResponseObject, ResponseToolkit } from '@hapi/hapi';
import nodeFetch, { Response } from 'node-fetch';
import type { Logger } from '@kbn/logging';
import type { KibanaConfig } from '../kibana_config';

type Status = 'healthy' | 'unhealthy' | 'failure' | 'timeout';

interface RootRouteResponse {
const statusApiPath = '/api/status';

interface StatusRouteResponse {
status: Status;
hosts?: HostStatus[];
}
Expand All @@ -27,9 +29,9 @@ interface HostStatus {
code?: number;
}

export class RootRoute implements ServerRoute {
export class StatusHandler {
private static isHealthy(response: Response) {
return RootRoute.isSuccess(response) || RootRoute.isUnauthorized(response);
return StatusHandler.isSuccess(response) || StatusHandler.isUnauthorized(response);
}

private static isUnauthorized({ status, headers }: Response): boolean {
Expand All @@ -47,25 +49,20 @@ export class RootRoute implements ServerRoute {
timeout: 504,
};

readonly method = 'GET';
readonly path = '/';

constructor(private kibanaConfig: KibanaConfig, private logger: Logger) {
this.handler = this.handler.bind(this);

return pick(this, ['method', 'path', 'handler']) as RootRoute;
}

async handler(request: Request, toolkit: ResponseToolkit): Promise<ResponseObject> {
const body = await this.poll();
const code = RootRoute.STATUS_CODE[body.status];
const code = StatusHandler.STATUS_CODE[body.status];

this.logger.debug(`Returning ${code} response with body: ${JSON.stringify(body)}`);

return toolkit.response(body).type('application/json').code(code);
}

private async poll(): Promise<RootRouteResponse> {
private async poll(): Promise<StatusRouteResponse> {
const hosts = await Promise.all(this.kibanaConfig.hosts.map(this.pollHost.bind(this)));
const statuses = chain(hosts).map('status').uniq().value();
const status = statuses.length <= 1 ? statuses[0] ?? 'healthy' : 'unhealthy';
Expand All @@ -81,7 +78,7 @@ export class RootRoute implements ServerRoute {

try {
const response = await this.fetch(host);
const status = RootRoute.isHealthy(response) ? 'healthy' : 'unhealthy';
const status = StatusHandler.isHealthy(response) ? 'healthy' : 'unhealthy';
this.logger.debug(
`${capitalize(status)} response from '${host}' with code ${response.status}`
);
Expand Down Expand Up @@ -112,8 +109,9 @@ export class RootRoute implements ServerRoute {
}
}

private async fetch(url: string) {
const { protocol } = new URL(url);
private async fetch(host: string) {
const url = new URL(host);
appendStatusApiPath(url);

const controller = new AbortController();
const timeoutId = setTimeout(
Expand All @@ -123,7 +121,7 @@ export class RootRoute implements ServerRoute {

try {
return await nodeFetch(url, {
agent: protocol === 'https:' ? this.getAgent() : undefined,
agent: url.protocol === 'https:' ? this.getAgent() : undefined,
signal: controller.signal,
redirect: 'manual',
});
Expand Down Expand Up @@ -161,3 +159,7 @@ export class RootRoute implements ServerRoute {
return options;
}
}

const appendStatusApiPath = (url: URL) => {
url.pathname = `${url.pathname}/${statusApiPath}`.replace(/\/{2,}/g, '/');
};
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ describe('KibanaService', () => {
expect.objectContaining({
method: 'GET',
path: '/',
handler: expect.any(Function),
})
);
});

test('registers /api/status route with the server', async () => {
const kibanaService = new KibanaService({ config, logger });
await kibanaService.start({ server });
expect(server.addRoute).toHaveBeenCalledWith(
expect.objectContaining({
method: 'GET',
path: '/api/status',
handler: expect.any(Function),
})
);
});
Expand Down
14 changes: 12 additions & 2 deletions packages/kbn-health-gateway-server/src/kibana/kibana_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { IConfigService } from '@kbn/config';
import type { Logger, LoggerFactory } from '@kbn/logging';
import { ServerStart } from '../server';
import { KibanaConfig } from './kibana_config';
import { RootRoute } from './routes';
import { StatusHandler } from './handlers';

interface KibanaServiceStartDependencies {
server: ServerStart;
Expand All @@ -34,7 +34,17 @@ export class KibanaService {
}

async start({ server }: KibanaServiceStartDependencies) {
server.addRoute(new RootRoute(this.kibanaConfig, this.logger));
const statusHandler = new StatusHandler(this.kibanaConfig, this.logger);
server.addRoute({
method: 'GET',
path: '/',
handler: statusHandler.handler,
});
server.addRoute({
method: 'GET',
path: '/api/status',
handler: statusHandler.handler,
});
this.logger.info('Server is ready');
}

Expand Down
57 changes: 43 additions & 14 deletions src/plugins/discover/public/application/context/context_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { DataView, DataViewField } from '@kbn/data-views-plugin/public';
import { useExecutionContext } from '@kbn/kibana-react-plugin/public';
import { generateFilters } from '@kbn/data-plugin/public';
import { i18n } from '@kbn/i18n';
import { reportPerformanceMetricEvent } from '@kbn/ebt-tools';
import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '../../../common';
import { ContextErrorMessage } from './components/context_error_message';
import { LoadingStatus } from './services/context_query_state';
Expand All @@ -40,8 +41,16 @@ export interface ContextAppProps {

export const ContextApp = ({ dataView, anchorId, referrer }: ContextAppProps) => {
const services = useDiscoverServices();
const { locator, uiSettings, capabilities, dataViews, navigation, filterManager, core } =
services;
const {
analytics,
locator,
uiSettings,
capabilities,
dataViews,
navigation,
filterManager,
core,
} = services;

const isLegacy = useMemo(() => uiSettings.get(DOC_TABLE_LEGACY), [uiSettings]);
const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]);
Expand Down Expand Up @@ -109,22 +118,42 @@ export const ContextApp = ({ dataView, anchorId, referrer }: ContextAppProps) =>
* Fetch docs on ui changes
*/
useEffect(() => {
if (!prevAppState.current) {
fetchAllRows();
} else if (prevAppState.current.predecessorCount !== appState.predecessorCount) {
fetchSurroundingRows(SurrDocType.PREDECESSORS);
} else if (prevAppState.current.successorCount !== appState.successorCount) {
fetchSurroundingRows(SurrDocType.SUCCESSORS);
} else if (
!isEqualFilters(prevAppState.current.filters, appState.filters) ||
!isEqualFilters(prevGlobalState.current.filters, globalState.filters)
) {
fetchContextRows();
}
const doFetch = async () => {
const startTime = window.performance.now();
let fetchType = '';
if (!prevAppState.current) {
fetchType = 'all';
await fetchAllRows();
} else if (prevAppState.current.predecessorCount !== appState.predecessorCount) {
fetchType = 'predecessors';
await fetchSurroundingRows(SurrDocType.PREDECESSORS);
} else if (prevAppState.current.successorCount !== appState.successorCount) {
fetchType = 'successors';
await fetchSurroundingRows(SurrDocType.SUCCESSORS);
} else if (
!isEqualFilters(prevAppState.current.filters, appState.filters) ||
!isEqualFilters(prevGlobalState.current.filters, globalState.filters)
) {
fetchType = 'context';
await fetchContextRows();
}

if (analytics) {
const fetchDuration = window.performance.now() - startTime;
reportPerformanceMetricEvent(analytics, {
eventName: 'discoverSurroundingDocsFetch',
duration: fetchDuration,
meta: { fetchType },
});
}
};

doFetch();

prevAppState.current = cloneDeep(appState);
prevGlobalState.current = cloneDeep(globalState);
}, [
analytics,
appState,
globalState,
anchorId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from '@kbn/shared-ux-page-analytics-no-data';
import { getSavedSearchFullPathUrl } from '@kbn/saved-search-plugin/public';
import useObservable from 'react-use/lib/useObservable';
import { reportPerformanceMetricEvent } from '@kbn/ebt-tools';
import { useUrl } from './hooks/use_url';
import { useSingleton } from './hooks/use_singleton';
import { MainHistoryLocationState } from '../../../common/locator';
Expand Down Expand Up @@ -127,6 +128,7 @@ export function DiscoverMainRoute({ customizationCallbacks, isDev }: MainRoutePr

const loadSavedSearch = useCallback(
async (nextDataView?: DataView) => {
const loadSavedSearchStartTime = window.performance.now();
setLoading(true);
if (!nextDataView && !(await checkData())) {
setLoading(false);
Expand Down Expand Up @@ -159,6 +161,13 @@ export function DiscoverMainRoute({ customizationCallbacks, isDev }: MainRoutePr
);

setLoading(false);
if (services.analytics) {
const loadSavedSearchDuration = window.performance.now() - loadSavedSearchStartTime;
reportPerformanceMetricEvent(services.analytics, {
eventName: 'discoverLoadSavedSearch',
duration: loadSavedSearchDuration,
});
}
} catch (e) {
if (e instanceof SavedObjectNotFound) {
redirectWhenMissing({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { SavedSearch } from '@kbn/saved-search-plugin/public';
import { AggregateQuery, Query } from '@kbn/es-query';
import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types';
import { DataView } from '@kbn/data-views-plugin/common';
import { reportPerformanceMetricEvent } from '@kbn/ebt-tools';
import { getDataViewByTextBasedQueryLang } from '../utils/get_data_view_by_text_based_query_lang';
import { isTextBasedQuery } from '../utils/is_text_based_query';
import { getRawRecordType } from '../utils/get_raw_record_type';
Expand Down Expand Up @@ -204,6 +205,7 @@ export function getDataStateContainer({
abortController = new AbortController();
const prevAutoRefreshDone = autoRefreshDone;

const fetchAllStartTime = window.performance.now();
await fetchAll(dataSubjects, reset, {
abortController,
initialFetchStatus: getInitialFetchStatus(),
Expand All @@ -214,6 +216,11 @@ export function getDataStateContainer({
savedSearch: getSavedSearch(),
useNewFieldsApi: !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE),
});
const fetchAllDuration = window.performance.now() - fetchAllStartTime;
reportPerformanceMetricEvent(services.analytics, {
eventName: 'discoverFetchAll',
duration: fetchAllDuration,
});

// If the autoRefreshCallback is still the same as when we started i.e. there was no newer call
// replacing this current one, call it to make sure we tell that the auto refresh is done
Expand Down
Loading

0 comments on commit 41f6915

Please sign in to comment.