From 5c8d888e383c8343fba87808b776d15c3df182ce Mon Sep 17 00:00:00 2001 From: Carlos Crespo Date: Wed, 27 Nov 2024 11:55:51 +0100 Subject: [PATCH] [APM] Make `trace.id` an optional field (#201821) fixes [#201803](https://github.com/elastic/kibana/issues/201803) ## Summary This PR fixes the error sample details function, making the `trace.id` an optional field, to prevent the function from crashing in case this field is not in the docs. --------- Co-authored-by: Elastic Machine (cherry picked from commit caea2066e4ca70e913b83a1ae13d3f2cd0d46804) # Conflicts: # x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/errors/group_id_samples.spec.ts # x-pack/test/apm_api_integration/tests/errors/generate_data.ts --- .../get_error_sample_details.ts | 4 +-- .../tests/errors/generate_data.ts | 6 ++++- .../tests/errors/group_id_samples.spec.ts | 27 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/observability_solution/apm/server/routes/errors/get_error_groups/get_error_sample_details.ts b/x-pack/plugins/observability_solution/apm/server/routes/errors/get_error_groups/get_error_sample_details.ts index 91da19224d83c..954086ee53084 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/errors/get_error_groups/get_error_sample_details.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/errors/get_error_groups/get_error_sample_details.ts @@ -69,7 +69,6 @@ export async function getErrorSampleDetails({ const requiredFields = asMutableArray([ AGENT_NAME, PROCESSOR_EVENT, - TRACE_ID, TIMESTAMP_US, AT_TIMESTAMP, SERVICE_NAME, @@ -78,6 +77,7 @@ export async function getErrorSampleDetails({ ] as const); const optionalFields = asMutableArray([ + TRACE_ID, TRANSACTION_ID, SPAN_ID, AGENT_VERSION, @@ -131,7 +131,7 @@ export async function getErrorSampleDetails({ const errorFromFields = unflattenKnownApmEventFields(hit.fields, requiredFields); const transactionId = errorFromFields.transaction?.id ?? errorFromFields.span?.id; - const traceId = errorFromFields.trace.id; + const traceId = errorFromFields.trace?.id; let transaction: Transaction | undefined; if (transactionId && traceId) { diff --git a/x-pack/test/apm_api_integration/tests/errors/generate_data.ts b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts index a7e627a048e05..7844168f3c11b 100644 --- a/x-pack/test/apm_api_integration/tests/errors/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { apm, timerange } from '@kbn/apm-synthtrace-client'; +import { ApmFields, apm, timerange } from '@kbn/apm-synthtrace-client'; import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; export const config = { @@ -25,11 +25,13 @@ export async function generateData({ serviceName, start, end, + overrides, }: { apmSynthtraceEsClient: ApmSynthtraceEsClient; serviceName: string; start: number; end: number; + overrides?: Partial; }) { const serviceGoProdInstance = apm .service({ name: serviceName, environment: 'production', agentName: 'go' }) @@ -47,6 +49,7 @@ export async function generateData({ .generator((timestamp) => serviceGoProdInstance .transaction({ transactionName: transaction.name }) + .overrides(overrides ? overrides : {}) .timestamp(timestamp) .duration(1000) .success() @@ -57,6 +60,7 @@ export async function generateData({ .generator((timestamp) => serviceGoProdInstance .transaction({ transactionName: transaction.name }) + .overrides(overrides ? overrides : {}) .errors( serviceGoProdInstance .error({ message: `Error ${index}`, type: transaction.name }) diff --git a/x-pack/test/apm_api_integration/tests/errors/group_id_samples.spec.ts b/x-pack/test/apm_api_integration/tests/errors/group_id_samples.spec.ts index ea74f1fa622d8..4b4f767daccbb 100644 --- a/x-pack/test/apm_api_integration/tests/errors/group_id_samples.spec.ts +++ b/x-pack/test/apm_api_integration/tests/errors/group_id_samples.spec.ts @@ -138,6 +138,33 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); + describe('error sample without trace.id', () => { + before(async () => { + await generateData({ + serviceName, + start, + end, + apmSynthtraceEsClient, + overrides: { + 'trace.id': undefined, + }, + }); + }); + + after(() => apmSynthtraceEsClient.clean()); + + it('returns 200', async () => { + const errorsSamplesResponse = await callErrorGroupSamplesApi({ + groupId: '0000000000000000000000000Error 1', + }); + + const errorId = errorsSamplesResponse.body.errorSampleIds[0]; + + const response = await callErrorSampleDetailsApi(errorId); + expect(response.status).to.be(200); + }); + }); + describe('with sampled and unsampled transactions', () => { let errorGroupSamplesResponse: ErrorGroupSamples;