From 61a31884fbd370364c4faaa04d222cdfa376d91f Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 30 Jun 2020 10:27:22 -0700 Subject: [PATCH] [APM] Fix service maps load failure when user doesn't have ML permissions (#70138) * checks for statusCode 403 when fetching ML jobs, and returns empty list of jobs instead of throwing * Catches any error thrown when retrieving service anomalies and logs them to the console before responding service maps data without anomalies. Co-authored-by: Elastic Machine --- .../lib/service_map/get_service_anomalies.ts | 9 +++++++-- .../apm/server/lib/service_map/get_service_map.ts | 15 ++++++++++++--- x-pack/plugins/apm/server/routes/service_map.ts | 7 ++++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts index 2d988110e593ad..eb94dff365f62b 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts @@ -26,7 +26,7 @@ async function getApmAnomalyDetectionJobs( const { jobs } = await ml.anomalyDetectors.jobs(APM_ML_JOB_GROUP_NAME); return jobs; } catch (error) { - if (error.statusCode === 404) { + if (error.statusCode === 404 || error.statusCode === 403) { return []; } throw error; @@ -131,7 +131,7 @@ export async function getServiceAnomalies( }; const response = (await ml.mlSystem.mlSearch(params)) as { - aggregations: { + aggregations?: { jobs: { buckets: Array<{ key: string; @@ -151,6 +151,11 @@ export async function getServiceAnomalies( }; }; }; + + if (!response.aggregations) { + return []; + } + const anomalyScores = response.aggregations.jobs.buckets.map((jobBucket) => { const jobId = jobBucket.key; const bucketSource = jobBucket.top_score_hits.hits.hits?.[0]?._source; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts index 9f3ded82d7cbd8..a3f5e87a8f3853 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { chunk } from 'lodash'; +import { Logger } from 'kibana/server'; import { AGENT_NAME, SERVICE_ENVIRONMENT, @@ -26,6 +27,7 @@ export interface IEnvOptions { setup: Setup & SetupTimeRange; serviceName?: string; environment?: string; + logger: Logger; } async function getConnectionData({ @@ -138,6 +140,7 @@ export type ServicesResponse = PromiseReturnType; export type ServiceMapAPIResponse = PromiseReturnType; export async function getServiceMap(options: IEnvOptions) { + const { logger } = options; const [connectionData, servicesData] = await Promise.all([ getConnectionData(options), getServicesData(options), @@ -150,12 +153,18 @@ export async function getServiceMap(options: IEnvOptions) { (serviceData) => serviceData[SERVICE_NAME] ); - // Get related service anomalies - const serviceAnomalies = await getServiceAnomalies(options, serviceNames); + let anomalies: ServiceAnomalies = []; + try { + // Get related service anomalies + anomalies = await getServiceAnomalies(options, serviceNames); + } catch (error) { + logger.warn('Unabled to retrieve anomaly detection data for service maps.'); + logger.error(error); + } return transformServiceMapResponses({ ...connectionData, - anomalies: serviceAnomalies, + anomalies, services: servicesData, }); } diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index df0403be7b9759..d9390dc79bb04d 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -39,7 +39,12 @@ export const serviceMapRoute = createRoute(() => ({ const { query: { serviceName, environment }, } = context.params; - return getServiceMap({ setup, serviceName, environment }); + return getServiceMap({ + setup, + serviceName, + environment, + logger: context.logger, + }); }, }));