From d15172542249827ab73b52327ca0125807836a0c Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 12:26:56 -0400 Subject: [PATCH 01/12] extract common logic into getXrayTraceData method --- .../src/config/EnvironmentVariablesService.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index 2f2d0c7165..4522808a5b 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -53,11 +53,11 @@ class EnvironmentVariablesService extends ConfigService { * @returns {string} */ public getXrayTraceId(): string | undefined { - const xRayTraceId = this.get(this.xRayTraceIdVariable); + const xRayTraceData = this.getXrayTraceData(); - if (xRayTraceId === '') return undefined; + if (xRayTraceData.length === 0) return undefined; - return xRayTraceId.split(';')[0].replace('Root=', ''); + return xRayTraceData[0].replace('Root=', ''); } /** @@ -72,6 +72,13 @@ class EnvironmentVariablesService extends ConfigService { return truthyValues.includes(value.toLowerCase()); } + private getXrayTraceData(): string[] { + const xRayTraceEnv = this.get(this.xRayTraceIdVariable); + + if (xRayTraceEnv === '') return []; + + return xRayTraceEnv.split(';'); + } } export { From 1bd60b523d0b0dc12bf072fd9d606e7a570230d2 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 12:56:30 -0400 Subject: [PATCH 02/12] implement getXrayTraceSampled method & tests --- .../src/config/EnvironmentVariablesService.ts | 14 +++++++ .../EnvironmentVariablesService.test.ts | 42 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index 4522808a5b..bdd58a7933 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -60,6 +60,20 @@ class EnvironmentVariablesService extends ConfigService { return xRayTraceData[0].replace('Root=', ''); } + /** + * It returns true if the Sampled flag is set in the _X_AMZN_TRACE_ID environment variable. + * + * The AWS X-Ray Trace data available in the environment variable has this format: + * `Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1`, + * + * @returns {string} + */ + public getXrayTraceSampled(): boolean { + const xRayTraceData = this.getXrayTraceData(); + + return xRayTraceData[2] === 'Sampled=1'; + } + /** * It returns true if the string value represents a boolean true value. * diff --git a/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts index c9b56b22ef..06e458282b 100644 --- a/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts +++ b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts @@ -110,6 +110,48 @@ describe('Class: EnvironmentVariablesService', () => { }); + describe('Method: getXrayTraceSampled', () => { + + test('It returns true if the Sampled flag is set in the _X_AMZN_TRACE_ID environment variable', () => { + + // Prepare + process.env._X_AMZN_TRACE_ID = 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getXrayTraceSampled(); + + // Assess + expect(value).toEqual(true); + }); + + test('It returns false if the Sampled flag is not set in the _X_AMZN_TRACE_ID environment variable', () => { + + // Prepare + process.env._X_AMZN_TRACE_ID = 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getXrayTraceSampled(); + + // Assess + expect(value).toEqual(false); + }); + + it('It returns false when no _X_AMZN_TRACE_ID environment variable is present', () => { + + // Prepare + delete process.env._X_AMZN_TRACE_ID; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getXrayTraceSampled(); + + // Assess + expect(value).toEqual(false); + }); + }); + describe('Method: isValueTrue', () => { const valuesToTest: Array> = [ From 95172948bf8e2672fb6464f5e8473e3bc0dc29b6 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 13:06:00 -0400 Subject: [PATCH 03/12] implement Tracer method --- packages/tracer/src/Tracer.ts | 4 ++++ packages/tracer/src/TracerInterface.ts | 1 + packages/tracer/tests/unit/Tracer.test.ts | 17 +++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index b4fe242395..c4ac69bc49 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -510,6 +510,10 @@ class Tracer extends Utility implements TracerInterface { public getRootXrayTraceId(): string | undefined { return this.envVarsService.getXrayTraceId(); } + + public isTraceSampled(): boolean { + return this.envVarsService.getXrayTraceSampled(); + } /** * Get the active segment or subsegment (if any) in the current scope. diff --git a/packages/tracer/src/TracerInterface.ts b/packages/tracer/src/TracerInterface.ts index 344e44177e..30a78d86cc 100644 --- a/packages/tracer/src/TracerInterface.ts +++ b/packages/tracer/src/TracerInterface.ts @@ -13,6 +13,7 @@ interface TracerInterface { captureMethod(options?: CaptureMethodOptions): MethodDecorator getSegment(): Segment | Subsegment | undefined getRootXrayTraceId(): string | undefined + isTraceSampled(): boolean isTracingEnabled(): boolean putAnnotation: (key: string, value: string | number | boolean) => void putMetadata: (key: string, value: unknown, namespace?: string | undefined) => void diff --git a/packages/tracer/tests/unit/Tracer.test.ts b/packages/tracer/tests/unit/Tracer.test.ts index 997258bd5a..02ee542087 100644 --- a/packages/tracer/tests/unit/Tracer.test.ts +++ b/packages/tracer/tests/unit/Tracer.test.ts @@ -279,6 +279,23 @@ describe('Class: Tracer', () => { }); + describe('Method: isTraceSampled', () => { + + test('when called, it returns true if the Sampled flag is set', () => { + + // Prepare + const tracer: Tracer = new Tracer(); + + // Act + const xRayTraceSampled = tracer.getRootXrayTraceId(); + + // Assess + expect(xRayTraceSampled).toBe(true); + + }); + + }); + describe('Method: getSegment', () => { test('when called and no segment is returned, it logs a warning', () => { From 7ebefaa47305cbe6c3859c9d3ede4549363861d3 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 13:07:23 -0400 Subject: [PATCH 04/12] fix test --- packages/tracer/tests/unit/Tracer.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tracer/tests/unit/Tracer.test.ts b/packages/tracer/tests/unit/Tracer.test.ts index 02ee542087..f014f58c64 100644 --- a/packages/tracer/tests/unit/Tracer.test.ts +++ b/packages/tracer/tests/unit/Tracer.test.ts @@ -287,7 +287,7 @@ describe('Class: Tracer', () => { const tracer: Tracer = new Tracer(); // Act - const xRayTraceSampled = tracer.getRootXrayTraceId(); + const xRayTraceSampled = tracer.isTraceSampled(); // Assess expect(xRayTraceSampled).toBe(true); From d739297766f543d789f36fe455061353c4b6523b Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 13:09:22 -0400 Subject: [PATCH 05/12] fix unit test --- packages/tracer/tests/unit/Tracer.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tracer/tests/unit/Tracer.test.ts b/packages/tracer/tests/unit/Tracer.test.ts index f014f58c64..49fa38bfa8 100644 --- a/packages/tracer/tests/unit/Tracer.test.ts +++ b/packages/tracer/tests/unit/Tracer.test.ts @@ -290,7 +290,7 @@ describe('Class: Tracer', () => { const xRayTraceSampled = tracer.isTraceSampled(); // Assess - expect(xRayTraceSampled).toBe(true); + expect(xRayTraceSampled).toBe(false); }); From a24c4f90e339f8951b82092f38e1b8ae9bdfadda Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 13:13:27 -0400 Subject: [PATCH 06/12] add doc comment --- packages/tracer/src/Tracer.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index c4ac69bc49..49315b06a9 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -510,10 +510,6 @@ class Tracer extends Utility implements TracerInterface { public getRootXrayTraceId(): string | undefined { return this.envVarsService.getXrayTraceId(); } - - public isTraceSampled(): boolean { - return this.envVarsService.getXrayTraceSampled(); - } /** * Get the active segment or subsegment (if any) in the current scope. @@ -551,6 +547,19 @@ class Tracer extends Utility implements TracerInterface { return segment; } + /** + * Get the current value of the AWS X-Ray Sampled flag. + * + * Utility method that returns the current AWS X-Ray Sampled flag. + * + * @see https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-traces + * + * @returns boolean - `true` if the trace is sampled, `false` otherwise. + */ + public isTraceSampled(): boolean { + return this.envVarsService.getXrayTraceSampled(); + } + /** * Get the current value of the `tracingEnabled` property. * From 57f0a9596a02196513df7afce632ac0965011c58 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 13:28:15 -0400 Subject: [PATCH 07/12] fix return type --- packages/commons/src/config/EnvironmentVariablesService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index bdd58a7933..9694223c56 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -66,7 +66,7 @@ class EnvironmentVariablesService extends ConfigService { * The AWS X-Ray Trace data available in the environment variable has this format: * `Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1`, * - * @returns {string} + * @returns {boolean} */ public getXrayTraceSampled(): boolean { const xRayTraceData = this.getXrayTraceData(); From 5d5beb38e31d61b1f9433fa6f5467cfccd95aa08 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 15:31:51 -0400 Subject: [PATCH 08/12] Update packages/tracer/src/Tracer.ts Co-authored-by: Andrea Amorosi --- packages/tracer/src/Tracer.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index 49315b06a9..d02d6e2658 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -557,6 +557,8 @@ class Tracer extends Utility implements TracerInterface { * @returns boolean - `true` if the trace is sampled, `false` otherwise. */ public isTraceSampled(): boolean { + if (!this.isTracingEnabled()) return false; + return this.envVarsService.getXrayTraceSampled(); } From d693fe09eecfb81144fa522feb3c03649916fe22 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 15:31:56 -0400 Subject: [PATCH 09/12] Update packages/tracer/src/Tracer.ts Co-authored-by: Andrea Amorosi --- packages/tracer/src/Tracer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index d02d6e2658..0b0bdc09a1 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -554,7 +554,7 @@ class Tracer extends Utility implements TracerInterface { * * @see https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-traces * - * @returns boolean - `true` if the trace is sampled, `false` otherwise. + * @returns boolean - `true` if the trace is sampled, `false` if tracing is disabled or the trace is not sampled. */ public isTraceSampled(): boolean { if (!this.isTracingEnabled()) return false; From 8191e6ac551ac445411416553616934a978a32b6 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 16:42:15 -0400 Subject: [PATCH 10/12] update getXrayTraceData to return object --- .../src/config/EnvironmentVariablesService.ts | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index 9694223c56..63bc9f6561 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -55,9 +55,7 @@ class EnvironmentVariablesService extends ConfigService { public getXrayTraceId(): string | undefined { const xRayTraceData = this.getXrayTraceData(); - if (xRayTraceData.length === 0) return undefined; - - return xRayTraceData[0].replace('Root=', ''); + return xRayTraceData?.Root; } /** @@ -71,7 +69,7 @@ class EnvironmentVariablesService extends ConfigService { public getXrayTraceSampled(): boolean { const xRayTraceData = this.getXrayTraceData(); - return xRayTraceData[2] === 'Sampled=1'; + return xRayTraceData?.Sampled === '1'; } /** @@ -86,12 +84,27 @@ class EnvironmentVariablesService extends ConfigService { return truthyValues.includes(value.toLowerCase()); } - private getXrayTraceData(): string[] { + /** + * It parses the key/value data present in the _X_AMZN_TRACE_ID environment variable + * and returns it as an object when available. + */ + private getXrayTraceData(): Record | undefined { const xRayTraceEnv = this.get(this.xRayTraceIdVariable); - if (xRayTraceEnv === '') return []; + if (xRayTraceEnv === '') return undefined; + + if (!xRayTraceEnv.includes('=')) return { Root: xRayTraceEnv }; + + const xRayTraceData: Record = {}; + + xRayTraceEnv.split(';').forEach((field) => { + + const [ key, value ] = field.split('='); + + xRayTraceData[key] = value; + }); - return xRayTraceEnv.split(';'); + return xRayTraceData; } } From 56c53e94237b074db73c3afed284d6eda454cd35 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 17:16:13 -0400 Subject: [PATCH 11/12] add tests for disabled tracer --- packages/tracer/src/Tracer.ts | 4 ++++ packages/tracer/tests/unit/Tracer.test.ts | 25 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index 0b0bdc09a1..ec482ce0be 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -508,6 +508,10 @@ class Tracer extends Utility implements TracerInterface { * @returns string - The root X-Ray trace id. */ public getRootXrayTraceId(): string | undefined { + if (!this.isTracingEnabled()) { + return undefined; + } + return this.envVarsService.getXrayTraceId(); } diff --git a/packages/tracer/tests/unit/Tracer.test.ts b/packages/tracer/tests/unit/Tracer.test.ts index 49fa38bfa8..28ae7ffa4d 100644 --- a/packages/tracer/tests/unit/Tracer.test.ts +++ b/packages/tracer/tests/unit/Tracer.test.ts @@ -277,6 +277,18 @@ describe('Class: Tracer', () => { }); + test('when called and Tracer is disabled, it returns undefined', () => { + + // Prepare + const tracer: Tracer = new Tracer({ enabled: false }); + + // Act + const xRayTraceId = tracer.getRootXrayTraceId(); + + // Assess + expect(xRayTraceId).toBe(undefined); + }); + }); describe('Method: isTraceSampled', () => { @@ -294,6 +306,19 @@ describe('Class: Tracer', () => { }); + test('when called and Trace is disabled, it returns false', () => { + + // Prepare + const tracer: Tracer = new Tracer({ enabled: false }); + + // Act + const xRayTraceSampled = tracer.isTraceSampled(); + + // Assess + expect(xRayTraceSampled).toBe(false); + + }); + }); describe('Method: getSegment', () => { From aa6b825741034a3d05fabc6d49915620838db508 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Thu, 4 May 2023 17:18:06 -0400 Subject: [PATCH 12/12] remove extra braces --- packages/tracer/src/Tracer.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index ec482ce0be..6b8cff3009 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -508,9 +508,7 @@ class Tracer extends Utility implements TracerInterface { * @returns string - The root X-Ray trace id. */ public getRootXrayTraceId(): string | undefined { - if (!this.isTracingEnabled()) { - return undefined; - } + if (!this.isTracingEnabled()) return undefined; return this.envVarsService.getXrayTraceId(); }