[ML] Adding ML execution context to es requests (#148746)

Adds the page path as the ID to our existing execution context and adds
an additional context entry to every ml kibana endpoint.
In the search slow log, the id for each slow search from ML will look
like this:


`"a90d5297-fd77-4ea0-ac0d-c302963d7e75;kibana:application:ml:%2Fjobs%2Fnew_job%2Fsingle_metric;application:ml:%2Fapi%2Fml%2Fjobs%2Fnew_job_line_chart`

Separating by semicolon:
`a90d5297-fd77-4ea0-ac0d-c302963d7e75` -> kibana ID

`kibana:application:ml:%2Fjobs%2Fnew_job%2Fsingle_metric` -> default
context items added on the client side to show the source page.

`application:ml:%2Fapi%2Fml%2Fjobs%2Fnew_job_line_chart` -> new items
added by the server to show the source endpoint path.

Note, the paths have been encoded to replace the forward slashes.

Part of https://github.com/elastic/kibana/issues/147378
This commit is contained in:
James Gowdy 2023-01-24 07:58:42 +00:00 committed by GitHub
parent badf9a808e
commit afb84dcbcd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 17 deletions

View file

@ -96,6 +96,7 @@ export const useActiveRoute = (routesList: MlRoute[]): MlRoute => {
name: PLUGIN_ID,
type: 'application',
page: activeRoute?.path ?? '/overview',
id: activeRoute?.path,
});
return activeRoute ?? routesMap['/overview'];

View file

@ -12,6 +12,8 @@ import type {
IScopedClusterClient,
RequestHandler,
SavedObjectsClientContract,
CoreSetup,
CoreStart,
} from '@kbn/core/server';
import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server';
import type { SecurityPluginSetup } from '@kbn/security-plugin/server';
@ -19,6 +21,7 @@ import type { SecurityPluginSetup } from '@kbn/security-plugin/server';
import type { AlertingApiRequestHandlerContext } from '@kbn/alerting-plugin/server';
import type { PluginStart as DataViewsPluginStart } from '@kbn/data-views-plugin/server';
import type { DataViewsService } from '@kbn/data-views-plugin/common';
import { PLUGIN_ID } from '../../common/constants/app';
import { mlSavedObjectServiceFactory, MLSavedObjectService } from '../saved_objects';
import type { MlLicense } from '../../common/license';
@ -51,6 +54,7 @@ export class RouteGuard {
private _authorization: SecurityPluginSetup['authz'] | undefined;
private _isMlReady: () => Promise<void>;
private _getDataViews: GetDataViews;
private _getStartServices: CoreSetup['getStartServices'];
constructor(
mlLicense: MlLicense,
@ -59,7 +63,8 @@ export class RouteGuard {
spacesPlugin: SpacesPluginSetup | undefined,
authorization: SecurityPluginSetup['authz'] | undefined,
isMlReady: () => Promise<void>,
getDataViews: GetDataViews
getDataViews: GetDataViews,
getStartServices: CoreSetup['getStartServices']
) {
this._mlLicense = mlLicense;
this._getMlSavedObjectClient = getSavedObject;
@ -68,6 +73,7 @@ export class RouteGuard {
this._authorization = authorization;
this._isMlReady = isMlReady;
this._getDataViews = getDataViews;
this._getStartServices = getStartServices;
}
public fullLicenseAPIGuard<P, Q, B>(handler: Handler<P, Q, B>) {
@ -88,8 +94,11 @@ export class RouteGuard {
return response.forbidden();
}
const { elasticsearch, savedObjects } = await context.core;
const client = elasticsearch.client;
const {
elasticsearch: { client },
savedObjects: { client: savedObjectClient },
} = await context.core;
const mlSavedObjectClient = this._getMlSavedObjectClient(request);
const internalSavedObjectsClient = this._getInternalSavedObjectClient();
if (mlSavedObjectClient === null || internalSavedObjectsClient === null) {
@ -107,20 +116,36 @@ export class RouteGuard {
this._isMlReady
);
return handler({
client,
request,
response,
context,
mlSavedObjectService,
mlClient: getMlClient(client, mlSavedObjectService),
getDataViewsService: getDataViewsServiceFactory(
this._getDataViews,
savedObjects.client,
const [coreStart] = await this._getStartServices();
const executionContext = await createExecutionContext(coreStart, request.route.path);
return await coreStart.executionContext.withContext(executionContext, () =>
handler({
client,
request
),
});
request,
response,
context,
mlSavedObjectService,
mlClient: getMlClient(client, mlSavedObjectService),
getDataViewsService: getDataViewsServiceFactory(
this._getDataViews,
savedObjectClient,
client,
request
),
})
);
};
}
}
async function createExecutionContext(coreStart: CoreStart, id?: string) {
const labels = coreStart.executionContext.getAsLabels();
const page = labels.page as string;
return {
type: 'application',
name: PLUGIN_ID,
id: id ?? page,
page,
};
}

View file

@ -198,7 +198,8 @@ export class MlServerPlugin
plugins.spaces,
plugins.security?.authz,
() => this.isMlReady,
() => this.dataViews
() => this.dataViews,
coreSetup.getStartServices
),
mlLicense: this.mlLicense,
};