Skip to content

Commit

Permalink
Implement generic approach to execution context propagation
Browse files Browse the repository at this point in the history
  • Loading branch information
xcrzx committed May 23, 2022
1 parent ae8b6c8 commit cc84a20
Show file tree
Hide file tree
Showing 30 changed files with 176 additions and 29 deletions.
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,13 @@ module.exports = {
// to help deprecation and prevent accidental re-use/continued use of code we plan on removing. If you are
// finding yourself turning this off a lot for "new code" consider renaming the file and functions if it is has valid uses.
patterns: ['*legacy*'],
paths: [
{
name: 'react-router-dom',
importNames: ['Route'],
message: "import { Route } from '@kbn/kibana-react-plugin/public'",
},
],
},
],
},
Expand Down
23 changes: 21 additions & 2 deletions src/core/public/apm_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class ApmSystem {
private pageLoadTransaction?: Transaction;
private resourceObserver: CachedResourceObserver;
private apm?: ApmBase;
private executionContext?: ExecutionContextStart;

/**
* `apmConfig` would be populated with relevant APM RUM agent
Expand All @@ -56,6 +57,7 @@ export class ApmSystem {
}

this.addHttpRequestNormalization(apm);
this.addRouteChangeNormalization(apm);

init(apmConfig);
// hold page load transaction blocks a transaction implicitly created by init.
Expand All @@ -65,6 +67,7 @@ export class ApmSystem {
async start(start?: StartDeps) {
if (!this.enabled || !start) return;

this.executionContext = start.executionContext;
this.markPageLoadStart();

start.executionContext.context$.subscribe((c) => {
Expand Down Expand Up @@ -126,7 +129,7 @@ export class ApmSystem {

/**
* Adds an observer to the APM configuration for normalizing transactions of the 'http-request' type to remove the
* hostname, protocol, port, and base path. Allows for coorelating data cross different deployments.
* hostname, protocol, port, and base path. Allows for correlating data cross different deployments.
*/
private addHttpRequestNormalization(apm: ApmBase) {
apm.observe('transaction:end', (t) => {
Expand Down Expand Up @@ -154,7 +157,7 @@ export class ApmSystem {
return;
}

// Strip the protocol, hostnname, port, and protocol slashes to normalize
// Strip the protocol, hostname, port, and protocol slashes to normalize
parts.protocol = null;
parts.hostname = null;
parts.port = null;
Expand All @@ -171,4 +174,20 @@ export class ApmSystem {
t.name = `${method} ${normalizedUrl}`;
});
}

/**
* Set route-change transaction name to the destination page name taken from
* the execution context. Otherwise, all route change transactions would have
* default names, like 'Click - span' or 'Click - a' instead of more
* descriptive '/security/rules/:id/edit'.
*/
private addRouteChangeNormalization(apm: ApmBase) {
apm.observe('transaction:end', (t) => {
const executionContext = this.executionContext?.get();
if (executionContext && t.type === 'route-change') {
const { name, page } = executionContext;
t.name = `${name} ${page || 'unknown'}`;
}
});
}
}
2 changes: 2 additions & 0 deletions src/plugins/kibana_react/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export { TableListView } from './table_list_view';
export type { ToolbarButtonProps } from './toolbar_button';
export { POSITIONS, WEIGHTS, TOOLBAR_BUTTON_SIZES, ToolbarButton } from './toolbar_button';

export { Route } from './router';

export { reactRouterNavigate, reactRouterOnClickHandler } from './react_router_navigate';

export type {
Expand Down
9 changes: 9 additions & 0 deletions src/plugins/kibana_react/public/router/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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.
*/

export { Route } from './router';
86 changes: 86 additions & 0 deletions src/plugins/kibana_react/public/router/router.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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 React, { useMemo } from 'react';
import {
Route as ReactRouterRoute,
RouteComponentProps,
RouteProps,
useRouteMatch,
} from 'react-router-dom';
import { useKibana } from '../context';
import { useExecutionContext } from '../use_execution_context';

/**
* It's a wrapper around the react-router-dom Route component that inserts
* MatchPropagator in every application route. It helps track all route changes
* and send them to the execution context, later used to enrich APM
* 'route-change' transactions.
*/
export const Route = ({ children, component: Component, render, ...rest }: RouteProps) => {
const component = useMemo(() => {
if (!Component) {
return undefined;
}
return (props: RouteComponentProps) => (
<>
<MatchPropagator />
<Component {...props} />
</>
);
}, [Component]);

if (component) {
return <ReactRouterRoute {...rest} component={component} />;
}
if (render) {
return (
<ReactRouterRoute
{...rest}
render={(props) => (
<>
<MatchPropagator />
{render(props)}
</>
)}
/>
);
}
if (typeof children === 'function') {
return (
<ReactRouterRoute
{...rest}
render={(props) => (
<>
<MatchPropagator />
{children(props)}
</>
)}
/>
);
}
return (
<ReactRouterRoute {...rest}>
<MatchPropagator />
{children}
</ReactRouterRoute>
);
};

const MatchPropagator = () => {
const { executionContext } = useKibana().services;
const match = useRouteMatch();

useExecutionContext(executionContext, {
type: 'application',
page: match.path,
id: Object.keys(match.params).length > 0 ? JSON.stringify(match.params) : undefined,
});

return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import useDeepCompareEffect from 'react-use/lib/useDeepCompareEffect';
* @param context
*/
export function useExecutionContext(
executionContext: CoreStart['executionContext'],
executionContext: CoreStart['executionContext'] | undefined,
context: KibanaExecutionContext
) {
useDeepCompareEffect(() => {
executionContext.set(context);
executionContext?.set(context);

return () => {
executionContext.clear();
executionContext?.clear();
};
}, [context]);
}
3 changes: 2 additions & 1 deletion x-pack/plugins/cases/public/components/app/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React, { useCallback } from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';
import { Redirect, Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import { AllCases } from '../all_cases';
import { CaseView } from '../case_view';
import { CreateCase } from '../create';
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/security_solution/public/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Route, Switch } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';

import { NotFoundPage } from './404';
import { SecurityApp } from './app';
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/security_solution/public/app/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import { History } from 'history';
import React, { FC, memo, useEffect } from 'react';
import { Route, Router, Switch } from 'react-router-dom';
import { Router, Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import { useDispatch } from 'react-redux';

import { AppLeaveHandler, AppMountParameters } from '@kbn/core/public';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import { parse, stringify } from 'query-string';
import React from 'react';

import { Redirect, Route, Switch, useRouteMatch } from 'react-router-dom';
import { Redirect, Switch, useRouteMatch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';

import { url as urlUtils } from '@kbn/kibana-utils-plugin/public';
import { addEntitiesToKql } from './add_entities_to_kql';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import { parse, stringify } from 'query-string';
import React from 'react';

import { Redirect, Route, Switch, useRouteMatch } from 'react-router-dom';
import { Redirect, Switch, useRouteMatch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import { url as urlUtils } from '@kbn/kibana-utils-plugin/public';
import { addEntitiesToKql } from './add_entities_to_kql';
import { replaceKQLParts } from './replace_kql_parts';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React from 'react';
import { Route, Switch } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';

import { TrackApplicationView } from '@kbn/usage-collection-plugin/public';
import { ALERTS_PATH, SecurityPageName } from '../../../../common/constants';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* 2.0.
*/
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';

import { TrackApplicationView } from '@kbn/usage-collection-plugin/public';
import * as i18n from './translations';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React, { useCallback } from 'react';
import { Route, Switch } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';

import { UpdateDateRange } from '../../../common/components/charts/common';
import { scoreIntervalToDateTime } from '../../../common/components/ml/score/score_interval_to_datetime';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React, { memo, useCallback } from 'react';
import { Route, Switch } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';

import { HostsTabsProps } from './types';
import { scoreIntervalToDateTime } from '../../common/components/ml/score/score_interval_to_datetime';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import { Switch, Redirect } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import { HOSTS_PATH } from '../../../common/constants';
import { HostDetails } from './details';
import { HostsTableType } from '../store/model';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* 2.0.
*/

import { Switch, Route } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import React, { memo } from 'react';
import { MANAGEMENT_ROUTING_BLOCKLIST_PATH } from '../../common/constants';
import { NotFoundPage } from '../../../app/404';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* 2.0.
*/

import { Switch, Route } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import React, { memo } from 'react';
import { EndpointList } from './view';
import { MANAGEMENT_ROUTING_ENDPOINTS_PATH } from '../../common/constants';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* 2.0.
*/

import { Route, Switch } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import React from 'react';
import { NotFoundPage } from '../../../app/404';
import { MANAGEMENT_ROUTING_EVENT_FILTERS_PATH } from '../../common/constants';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* 2.0.
*/

import { Switch, Route } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import React, { memo } from 'react';
import { MANAGEMENT_ROUTING_HOST_ISOLATION_EXCEPTIONS_PATH } from '../../common/constants';
import { NotFoundPage } from '../../../app/404';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React, { memo } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import { Switch, Redirect } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import { EuiLoadingSpinner } from '@elastic/eui';
import { TrackApplicationView } from '@kbn/usage-collection-plugin/public';
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React, { memo } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import { Switch, Redirect } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import { PolicyDetails, PolicyList } from './view';
import {
MANAGEMENT_ROUTING_POLICY_DETAILS_FORM_PATH,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* 2.0.
*/

import { Switch, Route } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import React, { memo } from 'react';
import { TrustedAppsList } from './view/trusted_apps_list';
import { MANAGEMENT_ROUTING_TRUSTED_APPS_PATH } from '../../common/constants';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React, { useMemo } from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';
import { Redirect, Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';

import { useMlCapabilities } from '../../common/components/ml/hooks/use_ml_capabilities';
import { hasMlUserPermissions } from '../../../common/machine_learning/has_ml_user_permissions';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import React, { useCallback } from 'react';
import { Route, Switch } from 'react-router-dom';
import { Switch } from 'react-router-dom';
import { Route } from '@kbn/kibana-react-plugin/public';
import { EuiFlexItem, EuiSpacer } from '@elastic/eui';

import { FlowTargetSourceDest } from '../../../../common/search_strategy/security_solution/network';
Expand Down
Loading

0 comments on commit cc84a20

Please sign in to comment.