From 8d3fa287a25b3385188d8f404259c5b704c66290 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 18 Oct 2022 00:43:01 +0200 Subject: [PATCH 1/5] feat: moved EnvService to commons + exposed getXrayTraceId in tracer --- packages/commons/src/config/ConfigService.ts | 37 ++++++++ .../src/config/EnvironmentVariablesService.ts | 60 +++++++++++++ packages/commons/src/config/index.ts | 2 + packages/commons/src/index.ts | 1 + .../EnvironmentVariablesService.test.ts | 88 +++++++++++++++++++ packages/logger/src/Logger.ts | 22 +---- packages/logger/src/config/ConfigService.ts | 85 ------------------ .../src/config/EnvironmentVariablesService.ts | 29 +++--- packages/logger/src/config/index.ts | 1 - .../EnvironmentVariablesService.test.ts | 66 -------------- packages/metrics/src/config/ConfigService.ts | 13 --- .../src/config/EnvironmentVariablesService.ts | 5 +- packages/metrics/src/config/index.ts | 1 - packages/tracer/src/Tracer.ts | 38 ++++++++ packages/tracer/src/TracerInterface.ts | 1 + packages/tracer/src/config/ConfigService.ts | 28 ------ .../src/config/EnvironmentVariablesService.ts | 12 ++- packages/tracer/src/config/index.ts | 1 - packages/tracer/tests/unit/Tracer.test.ts | 17 ++++ .../EnvironmentVariablesService.test.ts | 66 -------------- 20 files changed, 271 insertions(+), 302 deletions(-) create mode 100644 packages/commons/src/config/ConfigService.ts create mode 100644 packages/commons/src/config/EnvironmentVariablesService.ts create mode 100644 packages/commons/src/config/index.ts create mode 100644 packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts delete mode 100644 packages/logger/src/config/ConfigService.ts delete mode 100644 packages/metrics/src/config/ConfigService.ts delete mode 100644 packages/tracer/src/config/ConfigService.ts diff --git a/packages/commons/src/config/ConfigService.ts b/packages/commons/src/config/ConfigService.ts new file mode 100644 index 0000000000..ba629475f4 --- /dev/null +++ b/packages/commons/src/config/ConfigService.ts @@ -0,0 +1,37 @@ +/** + * Abstract class ConfigService + * + * This class defines common methods and variables that can be set by the developer + * in the runtime. + * + * @class + * @abstract + */ +abstract class ConfigService { + + /** + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + * @protected + */ + protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; + + /** + * It returns the value of an environment variable that has given name. + * + * @param {string} name + * @returns {string} + */ + public abstract get(name: string): string; + + /** + * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. + * + * @returns {string} + */ + public abstract getServiceName(): string; + +} + +export { + ConfigService, +}; \ No newline at end of file diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts new file mode 100644 index 0000000000..11b25bd548 --- /dev/null +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -0,0 +1,60 @@ +import { ConfigService } from '.'; + +/** + * Class EnvironmentVariablesService + * + * This class is used to return environment variables that are available in the runtime of + * the current Lambda invocation. + * These variables can be a mix of runtime environment variables set by AWS and + * variables that can be set by the developer additionally. + * + * @class + * @extends {ConfigService} + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + */ +class EnvironmentVariablesService extends ConfigService { + + // Reserved environment variables + private xRayTraceIdVariable = '_X_AMZN_TRACE_ID'; + + /** + * It returns the value of an environment variable that has given name. + * + * @param {string} name + * @returns {string} + */ + public get(name: string): string { + return process.env[name]?.trim() || ''; + } + + /** + * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. + * + * @returns {string} + */ + public getServiceName(): string { + return this.get(this.serviceNameVariable); + } + + /** + * It returns the value of 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`, + * + * The actual Trace ID is: `1-5759e988-bd862e3fe1be46a994272793`. + * + * @returns {string} + */ + public getXrayTraceId(): string { + const xRayTraceId = this.get(this.xRayTraceIdVariable); + + return xRayTraceId.split(';')[0].replace('Root=', ''); + } + +} + +export { + EnvironmentVariablesService, +}; \ No newline at end of file diff --git a/packages/commons/src/config/index.ts b/packages/commons/src/config/index.ts new file mode 100644 index 0000000000..86697bdab3 --- /dev/null +++ b/packages/commons/src/config/index.ts @@ -0,0 +1,2 @@ +export * from './ConfigService'; +export * from './EnvironmentVariablesService'; \ No newline at end of file diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts index 4b333f1d09..f921ac63a6 100644 --- a/packages/commons/src/index.ts +++ b/packages/commons/src/index.ts @@ -1,4 +1,5 @@ export * from './utils/lambda'; export * from './Utility'; +export * from './config'; export * as ContextExamples from './samples/resources/contexts'; export * as Events from './samples/resources/events'; \ No newline at end of file diff --git a/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts new file mode 100644 index 0000000000..33177252fa --- /dev/null +++ b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts @@ -0,0 +1,88 @@ +/** + * Test EnvironmentVariablesService class + * + * @group unit/commons/all + */ + +import { EnvironmentVariablesService } from '../../../src/config'; + +describe('Class: EnvironmentVariablesService', () => { + + const ENVIRONMENT_VARIABLES = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...ENVIRONMENT_VARIABLES }; + }); + + afterAll(() => { + process.env = ENVIRONMENT_VARIABLES; + }); + + describe('Method: get', () => { + + test('When the variable IS present, it returns the value of a runtime variable', () => { + + // Prepare + process.env.CUSTOM_VARIABLE = 'my custom value'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.get('CUSTOM_VARIABLE'); + + // Assess + expect(value).toEqual('my custom value'); + + }); + + test('When the variable IS NOT present, it returns an empty string', () => { + + // Prepare + delete process.env.CUSTOM_VARIABLE; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.get('CUSTOM_VARIABLE'); + + // Assess + expect(value).toEqual(''); + + }); + + }); + + describe('Method: getServiceName', () => { + + test('It returns the value of the environment variable POWERTOOLS_SERVICE_NAME', () => { + + // Prepare + process.env.POWERTOOLS_SERVICE_NAME = 'shopping-cart-api'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getServiceName(); + + // Assess + expect(value).toEqual('shopping-cart-api'); + }); + + }); + + describe('Method: getXrayTraceId', () => { + + test('It returns the value of the environment variable _X_AMZN_TRACE_ID', () => { + + // Prepare + process.env._X_AMZN_TRACE_ID = 'abcd123456789'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getXrayTraceId(); + + // Assess + expect(value).toEqual('abcd123456789'); + }); + + }); + +}); \ No newline at end of file diff --git a/packages/logger/src/Logger.ts b/packages/logger/src/Logger.ts index 805e7a5d1a..be9ee86253 100644 --- a/packages/logger/src/Logger.ts +++ b/packages/logger/src/Logger.ts @@ -117,7 +117,8 @@ class Logger extends Utility implements ClassThatLogs { private static readonly defaultServiceName: string = 'service_undefined'; - private envVarsService?: EnvironmentVariablesService; + // envVarsService is always initialized in the constructor in setOptions() + private envVarsService!: EnvironmentVariablesService; private logEvent: boolean = false; @@ -455,7 +456,7 @@ class Logger extends Utility implements ClassThatLogs { logLevel, timestamp: new Date(), message: typeof input === 'string' ? input : input.message, - xRayTraceId: this.getXrayTraceId(), + xRayTraceId: this.envVarsService.getXrayTraceId(), }, this.getPowertoolLogData()); const logItem = new LogItem({ @@ -545,23 +546,6 @@ class Logger extends Utility implements ClassThatLogs { return this.powertoolLogData.sampleRateValue; } - /** - * It returns the current X-Ray Trace ID parsing the content of the `_X_AMZN_TRACE_ID` env variable. - * - * The X-Ray Trace data available in the environment variable has this format: - * `Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1`, - * - * The actual Trace ID is: `1-5759e988-bd862e3fe1be46a994272793`. - * - * @private - * @returns {string} - */ - private getXrayTraceId(): string { - const xRayTraceId = this.getEnvVarsService().getXrayTraceId(); - - return xRayTraceId.length > 0 ? xRayTraceId.split(';')[0].replace('Root=', '') : xRayTraceId; - } - /** * It returns true if the provided log level is valid. * diff --git a/packages/logger/src/config/ConfigService.ts b/packages/logger/src/config/ConfigService.ts deleted file mode 100644 index 6479ab32ee..0000000000 --- a/packages/logger/src/config/ConfigService.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { ConfigServiceInterface } from '.'; - -/** - * Abstract class ConfigService - * - * This class defines common methods and variables that can be set by the developer - * in the runtime. - * - * @class - * @abstract - * @implements {ConfigServiceInterface} - * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime - * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables - */ -abstract class ConfigService implements ConfigServiceInterface { - - /** - * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables - * @protected - */ - protected currentEnvironmentVariable = 'ENVIRONMENT'; - protected logEventVariable = 'POWERTOOLS_LOGGER_LOG_EVENT'; - protected logLevelVariable = 'LOG_LEVEL'; - protected sampleRateValueVariable = 'POWERTOOLS_LOGGER_SAMPLE_RATE'; - protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; - - /** - * It returns the value of an environment variable that has given name. - * - * @param {string} name - * @returns {string} - */ - public abstract get(name: string): string; - - /** - * It returns the value of the ENVIRONMENT environment variable. - * - * @returns {string} - */ - public abstract getCurrentEnvironment(): string; - - /** - * It returns the value of the POWERTOOLS_LOGGER_LOG_EVENT environment variable. - * - * @returns {boolean} - */ - public abstract getLogEvent(): boolean; - - /** - * It returns the value of the LOG_LEVEL environment variable. - * - * @returns {string} - */ - public abstract getLogLevel(): string; - - /** - * It returns the value of the POWERTOOLS_LOGGER_SAMPLE_RATE environment variable. - * - * @returns {string|undefined} - */ - public abstract getSampleRateValue(): number | undefined; - - /** - * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. - * - * @returns {string} - */ - public abstract getServiceName(): string; - - /** - * It returns true if the string value represents a boolean true value. - * - * @param {string} value - * @returns boolean - * @protected - */ - protected isValueTrue(value: string): boolean { - return value.toLowerCase() === 'true' || value === '1'; - } - -} - -export { - ConfigService, -}; \ No newline at end of file diff --git a/packages/logger/src/config/EnvironmentVariablesService.ts b/packages/logger/src/config/EnvironmentVariablesService.ts index 2484252a65..8778d75ce9 100644 --- a/packages/logger/src/config/EnvironmentVariablesService.ts +++ b/packages/logger/src/config/EnvironmentVariablesService.ts @@ -1,4 +1,5 @@ -import { ConfigService } from '.'; +import { ConfigServiceInterface } from './ConfigServiceInterface'; +import { EnvironmentVariablesService as CommonEnvironmentVariablesService } from '@aws-lambda-powertools/commons'; /** * Class EnvironmentVariablesService @@ -9,28 +10,22 @@ import { ConfigService } from '.'; * variables that can be set by the developer additionally. * * @class - * @extends {ConfigService} + * @extends {CommonEnvironmentVariablesService} + * @implements {ConfigServiceInterface} * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables */ -class EnvironmentVariablesService extends ConfigService { +class EnvironmentVariablesService extends CommonEnvironmentVariablesService implements ConfigServiceInterface { // Reserved environment variables private awsRegionVariable = 'AWS_REGION'; + private currentEnvironmentVariable = 'ENVIRONMENT'; private functionNameVariable = 'AWS_LAMBDA_FUNCTION_NAME'; private functionVersionVariable = 'AWS_LAMBDA_FUNCTION_VERSION'; + private logEventVariable = 'POWERTOOLS_LOGGER_LOG_EVENT'; + private logLevelVariable = 'LOG_LEVEL'; private memoryLimitInMBVariable = 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE'; - private xRayTraceIdVariable = '_X_AMZN_TRACE_ID'; - - /** - * It returns the value of an environment variable that has given name. - * - * @param {string} name - * @returns {string} - */ - public get(name: string): string { - return process.env[name]?.trim() || ''; - } + private sampleRateValueVariable = 'POWERTOOLS_LOGGER_SAMPLE_RATE'; /** * It returns the value of the AWS_REGION environment variable. @@ -85,7 +80,9 @@ class EnvironmentVariablesService extends ConfigService { * @returns {boolean} */ public getLogEvent(): boolean { - return this.isValueTrue(this.get(this.logEventVariable)); + const value = this.get(this.logEventVariable); + + return value.toLowerCase() === 'true' || value === '1'; } /** @@ -123,7 +120,7 @@ class EnvironmentVariablesService extends ConfigService { * @returns {string} */ public getXrayTraceId(): string { - return this.get(this.xRayTraceIdVariable); + return super.getXrayTraceId(); } } diff --git a/packages/logger/src/config/index.ts b/packages/logger/src/config/index.ts index b8a77f2ab4..0f036d810e 100644 --- a/packages/logger/src/config/index.ts +++ b/packages/logger/src/config/index.ts @@ -1,3 +1,2 @@ -export * from './ConfigService'; export * from './ConfigServiceInterface'; export * from './EnvironmentVariablesService'; \ No newline at end of file diff --git a/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts index 18d1e29221..b64c4c228f 100644 --- a/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts +++ b/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts @@ -19,38 +19,6 @@ describe('Class: EnvironmentVariablesService', () => { process.env = ENVIRONMENT_VARIABLES; }); - describe('Method: get', () => { - - test('When the variable IS present, it returns the value of a runtime variable', () => { - - // Prepare - process.env.CUSTOM_VARIABLE = 'my custom value'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.get('CUSTOM_VARIABLE'); - - // Assess - expect(value).toEqual('my custom value'); - - }); - - test('When the variable IS NOT present, it returns an empty string', () => { - - // Prepare - delete process.env.CUSTOM_VARIABLE; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.get('CUSTOM_VARIABLE'); - - // Assess - expect(value).toEqual(''); - - }); - - }); - describe('Method: getAwsRegion', () => { test('It returns the value of the environment variable AWS_REGION', () => { @@ -252,38 +220,4 @@ describe('Class: EnvironmentVariablesService', () => { }); - describe('Method: getServiceName', () => { - - test('It returns the value of the environment variable POWERTOOLS_SERVICE_NAME', () => { - - // Prepare - process.env.POWERTOOLS_SERVICE_NAME = 'shopping-cart-api'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getServiceName(); - - // Assess - expect(value).toEqual('shopping-cart-api'); - }); - - }); - - describe('Method: getXrayTraceId', () => { - - test('It returns the value of the environment variable _X_AMZN_TRACE_ID', () => { - - // Prepare - process.env._X_AMZN_TRACE_ID = 'abcd123456789'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getXrayTraceId(); - - // Assess - expect(value).toEqual('abcd123456789'); - }); - - }); - }); \ No newline at end of file diff --git a/packages/metrics/src/config/ConfigService.ts b/packages/metrics/src/config/ConfigService.ts deleted file mode 100644 index a1fef20267..0000000000 --- a/packages/metrics/src/config/ConfigService.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ConfigServiceInterface } from '.'; - -abstract class ConfigService implements ConfigServiceInterface { - - public abstract get(name: string): string; - public abstract getNamespace(): string; - public abstract getService(): string; - -} - -export { - ConfigService, -}; \ No newline at end of file diff --git a/packages/metrics/src/config/EnvironmentVariablesService.ts b/packages/metrics/src/config/EnvironmentVariablesService.ts index b45c51ecc1..7928ed89a6 100644 --- a/packages/metrics/src/config/EnvironmentVariablesService.ts +++ b/packages/metrics/src/config/EnvironmentVariablesService.ts @@ -1,6 +1,7 @@ -import { ConfigService } from '.'; +import { ConfigServiceInterface } from './ConfigServiceInterface'; +import { EnvironmentVariablesService as CommonEnvironmentVariablesService } from '@aws-lambda-powertools/commons'; -class EnvironmentVariablesService extends ConfigService { +class EnvironmentVariablesService extends CommonEnvironmentVariablesService implements ConfigServiceInterface { private namespaceVariable = 'POWERTOOLS_METRICS_NAMESPACE'; private serviceVariable = 'POWERTOOLS_SERVICE_NAME'; diff --git a/packages/metrics/src/config/index.ts b/packages/metrics/src/config/index.ts index b8a77f2ab4..0f036d810e 100644 --- a/packages/metrics/src/config/index.ts +++ b/packages/metrics/src/config/index.ts @@ -1,3 +1,2 @@ -export * from './ConfigService'; export * from './ConfigServiceInterface'; export * from './EnvironmentVariablesService'; \ No newline at end of file diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index e4fe06553b..a583452025 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -462,6 +462,44 @@ class Tracer extends Utility implements TracerInterface { return descriptor; }; } + + /** + * Get the current root AWS X-Ray trace id. + * + * Utility method that returns the current AWS X-Ray Root trace id. Useful as correlation id for downstream processes. + * + * @see https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-traces + * + * @example + * ```typescript + * import { Tracer } from '@aws-lambda-powertools/tracer'; + * + * const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + * + * export const handler = async () => { + * + * try { + * ... + * } catch (err) { + * const rootTraceId = tracer.getRootXrayTraceId(); + * + * // Example of returning an error response + * return { + * statusCode: 500, + * // Include the rootTraceId in the response so we can show a "contact support" button that + * // takes the customer to a customer service form with the trace as additional context. + * body: `Internal Error - Please contact support and quote the following id: ${rootTraceId}`, + * headers: { "_X_AMZN_TRACE_ID": rootTraceId }, + * }; + * } + * } + * ``` + * + * @returns string - The root X-Ray trace id. + */ + public getRootXrayTraceId(): string { + return this.envVarsService.getXrayTraceId(); + } /** * Get the active segment or subsegment in the current scope. diff --git a/packages/tracer/src/TracerInterface.ts b/packages/tracer/src/TracerInterface.ts index 20ae8f60c9..fd94db45cd 100644 --- a/packages/tracer/src/TracerInterface.ts +++ b/packages/tracer/src/TracerInterface.ts @@ -12,6 +12,7 @@ interface TracerInterface { captureLambdaHandler(options?: CaptureLambdaHandlerOptions): HandlerMethodDecorator captureMethod(options?: CaptureMethodOptions): MethodDecorator getSegment(): Segment | Subsegment + getRootXrayTraceId(): string isTracingEnabled(): boolean putAnnotation: (key: string, value: string | number | boolean) => void putMetadata: (key: string, value: unknown, namespace?: string | undefined) => void diff --git a/packages/tracer/src/config/ConfigService.ts b/packages/tracer/src/config/ConfigService.ts deleted file mode 100644 index bbaffdb7ed..0000000000 --- a/packages/tracer/src/config/ConfigService.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ConfigServiceInterface } from '.'; - -abstract class ConfigService implements ConfigServiceInterface { - - // Custom environment variables - protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; - protected tracerCaptureErrorVariable = 'POWERTOOLS_TRACER_CAPTURE_ERROR'; - protected tracerCaptureHTTPsRequestsVariable = 'POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS'; - protected tracerCaptureResponseVariable = 'POWERTOOLS_TRACER_CAPTURE_RESPONSE'; - protected tracingEnabledVariable = 'POWERTOOLS_TRACE_ENABLED'; - - public abstract get(name: string): string; - - public abstract getCaptureHTTPsRequests(): string; - - public abstract getServiceName(): string; - - public abstract getTracingCaptureError(): string; - - public abstract getTracingCaptureResponse(): string; - - public abstract getTracingEnabled(): string; - -} - -export { - ConfigService -}; \ No newline at end of file diff --git a/packages/tracer/src/config/EnvironmentVariablesService.ts b/packages/tracer/src/config/EnvironmentVariablesService.ts index 7fb780e2f8..19b3ef2c20 100644 --- a/packages/tracer/src/config/EnvironmentVariablesService.ts +++ b/packages/tracer/src/config/EnvironmentVariablesService.ts @@ -1,11 +1,15 @@ -import { ConfigService } from '.'; +import { ConfigServiceInterface } from './ConfigServiceInterface'; +import { EnvironmentVariablesService as CommonEnvironmentVariablesService } from '@aws-lambda-powertools/commons'; -class EnvironmentVariablesService extends ConfigService { +class EnvironmentVariablesService extends CommonEnvironmentVariablesService implements ConfigServiceInterface { // Environment variables private awsExecutionEnv = 'AWS_EXECUTION_ENV'; private samLocalVariable = 'AWS_SAM_LOCAL'; - private xRayTraceIdVariable = '_X_AMZN_TRACE_ID'; + private tracerCaptureErrorVariable = 'POWERTOOLS_TRACER_CAPTURE_ERROR'; + private tracerCaptureHTTPsRequestsVariable = 'POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS'; + private tracerCaptureResponseVariable = 'POWERTOOLS_TRACER_CAPTURE_RESPONSE'; + private tracingEnabledVariable = 'POWERTOOLS_TRACE_ENABLED'; public get(name: string): string { return process.env[name]?.trim() || ''; @@ -40,7 +44,7 @@ class EnvironmentVariablesService extends ConfigService { } public getXrayTraceId(): string { - return this.get(this.xRayTraceIdVariable); + return super.getXrayTraceId(); } } diff --git a/packages/tracer/src/config/index.ts b/packages/tracer/src/config/index.ts index b8a77f2ab4..0f036d810e 100644 --- a/packages/tracer/src/config/index.ts +++ b/packages/tracer/src/config/index.ts @@ -1,3 +1,2 @@ -export * from './ConfigService'; export * from './ConfigServiceInterface'; export * from './EnvironmentVariablesService'; \ No newline at end of file diff --git a/packages/tracer/tests/unit/Tracer.test.ts b/packages/tracer/tests/unit/Tracer.test.ts index ce1acc976e..f541f2e4db 100644 --- a/packages/tracer/tests/unit/Tracer.test.ts +++ b/packages/tracer/tests/unit/Tracer.test.ts @@ -271,6 +271,23 @@ describe('Class: Tracer', () => { }); + describe('Method: getRootXrayTraceId', () => { + + test('when called, it returns the X-Ray trace ID', () => { + + // Prepare + const tracer: Tracer = new Tracer(); + + // Act + const xRayTraceId = tracer.getRootXrayTraceId(); + + // Assess + expect(xRayTraceId).toBe('1-abcdef12-3456abcdef123456abcdef12'); + + }); + + }); + describe('Method: getSegment', () => { test('when called outside of a namespace or without parent segment, and tracing is enabled, it throws an error', () => { diff --git a/packages/tracer/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/tracer/tests/unit/config/EnvironmentVariablesService.test.ts index 30e0db93f2..478944ce31 100644 --- a/packages/tracer/tests/unit/config/EnvironmentVariablesService.test.ts +++ b/packages/tracer/tests/unit/config/EnvironmentVariablesService.test.ts @@ -19,38 +19,6 @@ describe('Class: EnvironmentVariablesService', () => { process.env = ENVIRONMENT_VARIABLES; }); - describe('Method: get', () => { - - test('When the variable IS present, it returns the value of a runtime variable', () => { - - // Prepare - process.env.CUSTOM_VARIABLE = 'my custom value'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.get('CUSTOM_VARIABLE'); - - // Assess - expect(value).toEqual('my custom value'); - - }); - - test('When the variable IS NOT present, it returns an empty string', () => { - - // Prepare - delete process.env.CUSTOM_VARIABLE; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.get('CUSTOM_VARIABLE'); - - // Assess - expect(value).toEqual(''); - - }); - - }); - describe('Method: getTracingEnabled', () => { test('It returns the value of the environment variable POWERTOOLS_TRACE_ENABLED', () => { @@ -119,40 +87,6 @@ describe('Class: EnvironmentVariablesService', () => { }); - describe('Method: getServiceName', () => { - - test('It returns the value of the environment variable POWERTOOLS_SERVICE_NAME', () => { - - // Prepare - process.env.POWERTOOLS_SERVICE_NAME = 'shopping-cart-api'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getServiceName(); - - // Assess - expect(value).toEqual('shopping-cart-api'); - }); - - }); - - describe('Method: getXrayTraceId', () => { - - test('It returns the value of the environment variable _X_AMZN_TRACE_ID', () => { - - // Prepare - process.env._X_AMZN_TRACE_ID = 'abcd123456789'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getXrayTraceId(); - - // Assess - expect(value).toEqual('abcd123456789'); - }); - - }); - describe('Method: getSamLocal', () => { test('It returns the value of the environment variable AWS_SAM_LOCAL', () => { From a355f7baf04a51c8ec309f244ddcc0bad2501808 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 18 Oct 2022 13:55:17 +0200 Subject: [PATCH 2/5] docs: added docs section for getRootXrayTraceId --- docs/core/tracer.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index bba9442920..16ea4b95de 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -484,6 +484,38 @@ Use **`POWERTOOLS_TRACER_CAPTURE_ERROR=false`** environment variable to instruct 1. You might **return sensitive** information from exceptions, stack traces you might not control +### Access AWS X-Ray Root Trace ID + +Tracer exposes a `getRootXrayTraceId()` method that allows you to retrieve the [AWS X-Ray Root Trace ID](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-traces) corresponds to the current function execution. + +!!! info "This is commonly useful in two scenarios" + + 1. By including the root trace id in your response consumers can use it to correlate requests + 2. You might want to surface the root trace id to your end users so that they can reference it while contacting customer service + +=== "index.ts" + + ```typescript hl_lines="9" + import { Tracer } from '@aws-lambda-powertools/tracer'; + + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + + export const handler = async (event: unknown, context: Context): Promise => { + try { + ... + } catch (err) { + const rootTraceId = tracer.getRootXrayTraceId(); + + // Example of returning an error response + return { + statusCode: 500, + body: `Internal Error - Please contact support and quote the following id: ${rootTraceId}`, + headers: { "_X_AMZN_TRACE_ID": rootTraceId }, + }; + } + }; + ``` + ### Escape hatch mechanism You can use `tracer.provider` attribute to access all methods provided by the [AWS X-Ray SDK](https://docs.aws.amazon.com/xray-sdk-for-nodejs/latest/reference/AWSXRay.html). From c2febb1c589e91709e17ab4a7a908bddf65d89d7 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 19 Oct 2022 09:48:36 +0200 Subject: [PATCH 3/5] Update docs/core/tracer.md Co-authored-by: Josh Kellendonk --- docs/core/tracer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 16ea4b95de..14a84cb376 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -490,7 +490,7 @@ Tracer exposes a `getRootXrayTraceId()` method that allows you to retrieve the [ !!! info "This is commonly useful in two scenarios" - 1. By including the root trace id in your response consumers can use it to correlate requests + 1. By including the root trace id in your response, consumers can use it to correlate requests 2. You might want to surface the root trace id to your end users so that they can reference it while contacting customer service === "index.ts" From b553fea84a20cea2d755cc0c1cb3c70d20911b87 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 19 Oct 2022 12:06:59 +0200 Subject: [PATCH 4/5] fix: remove reduntant methods --- packages/commons/src/config/ConfigService.ts | 6 ------ .../src/config/EnvironmentVariablesService.ts | 5 +++++ .../src/config/EnvironmentVariablesService.ts | 18 ------------------ packages/metrics/src/Metrics.ts | 4 ++-- .../src/config/ConfigServiceInterface.ts | 2 +- .../src/config/EnvironmentVariablesService.ts | 8 -------- packages/metrics/tests/unit/Metrics.test.ts | 2 +- .../src/config/EnvironmentVariablesService.ts | 11 ----------- 8 files changed, 9 insertions(+), 47 deletions(-) diff --git a/packages/commons/src/config/ConfigService.ts b/packages/commons/src/config/ConfigService.ts index ba629475f4..6e8f4adf6b 100644 --- a/packages/commons/src/config/ConfigService.ts +++ b/packages/commons/src/config/ConfigService.ts @@ -9,12 +9,6 @@ */ abstract class ConfigService { - /** - * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables - * @protected - */ - protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; - /** * It returns the value of an environment variable that has given name. * diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index 11b25bd548..d2716d6c72 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -15,6 +15,11 @@ import { ConfigService } from '.'; */ class EnvironmentVariablesService extends ConfigService { + /** + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + * @protected + */ + protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; // Reserved environment variables private xRayTraceIdVariable = '_X_AMZN_TRACE_ID'; diff --git a/packages/logger/src/config/EnvironmentVariablesService.ts b/packages/logger/src/config/EnvironmentVariablesService.ts index 8778d75ce9..28b5ee7b4b 100644 --- a/packages/logger/src/config/EnvironmentVariablesService.ts +++ b/packages/logger/src/config/EnvironmentVariablesService.ts @@ -105,24 +105,6 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl return (value && value.length > 0) ? Number(value) : undefined; } - /** - * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. - * - * @returns {string} - */ - public getServiceName(): string { - return this.get(this.serviceNameVariable); - } - - /** - * It returns the value of the _X_AMZN_TRACE_ID environment variable. - * - * @returns {string} - */ - public getXrayTraceId(): string { - return super.getXrayTraceId(); - } - } export { diff --git a/packages/metrics/src/Metrics.ts b/packages/metrics/src/Metrics.ts index 429e8a7d54..69d6f5e2ca 100644 --- a/packages/metrics/src/Metrics.ts +++ b/packages/metrics/src/Metrics.ts @@ -450,8 +450,8 @@ class Metrics extends Utility implements MetricsInterface { private setService(service: string | undefined): void { const targetService = (service || - this.getCustomConfigService()?.getService() || - this.getEnvVarsService().getService()) as string; + this.getCustomConfigService()?.getServiceName() || + this.getEnvVarsService().getServiceName()) as string; if (targetService.length > 0) { this.addDimension('service', targetService); } diff --git a/packages/metrics/src/config/ConfigServiceInterface.ts b/packages/metrics/src/config/ConfigServiceInterface.ts index 65406c5037..0c009b3e79 100644 --- a/packages/metrics/src/config/ConfigServiceInterface.ts +++ b/packages/metrics/src/config/ConfigServiceInterface.ts @@ -2,7 +2,7 @@ interface ConfigServiceInterface { get?(name: string): string getNamespace(): string - getService(): string + getServiceName(): string } diff --git a/packages/metrics/src/config/EnvironmentVariablesService.ts b/packages/metrics/src/config/EnvironmentVariablesService.ts index 7928ed89a6..5bb4eb712b 100644 --- a/packages/metrics/src/config/EnvironmentVariablesService.ts +++ b/packages/metrics/src/config/EnvironmentVariablesService.ts @@ -4,18 +4,10 @@ import { EnvironmentVariablesService as CommonEnvironmentVariablesService } from class EnvironmentVariablesService extends CommonEnvironmentVariablesService implements ConfigServiceInterface { private namespaceVariable = 'POWERTOOLS_METRICS_NAMESPACE'; - private serviceVariable = 'POWERTOOLS_SERVICE_NAME'; - - public get(name: string): string { - return process.env[name]?.trim() || ''; - } public getNamespace(): string { return this.get(this.namespaceVariable); } - public getService(): string { - return this.get(this.serviceVariable); - } } diff --git a/packages/metrics/tests/unit/Metrics.test.ts b/packages/metrics/tests/unit/Metrics.test.ts index 8ce2956969..2b3049c1af 100644 --- a/packages/metrics/tests/unit/Metrics.test.ts +++ b/packages/metrics/tests/unit/Metrics.test.ts @@ -684,7 +684,7 @@ describe('Class: Metrics', () => { const serviceName = 'Custom Provider Service Name'; const namespace = 'Custom Provider namespace'; const customConfigService = { - getService: () => serviceName, + getServiceName: () => serviceName, getNamespace: () => namespace, }; diff --git a/packages/tracer/src/config/EnvironmentVariablesService.ts b/packages/tracer/src/config/EnvironmentVariablesService.ts index 19b3ef2c20..d8503864c1 100644 --- a/packages/tracer/src/config/EnvironmentVariablesService.ts +++ b/packages/tracer/src/config/EnvironmentVariablesService.ts @@ -11,10 +11,6 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl private tracerCaptureResponseVariable = 'POWERTOOLS_TRACER_CAPTURE_RESPONSE'; private tracingEnabledVariable = 'POWERTOOLS_TRACE_ENABLED'; - public get(name: string): string { - return process.env[name]?.trim() || ''; - } - public getAwsExecutionEnv(): string { return this.get(this.awsExecutionEnv); } @@ -27,10 +23,6 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl return this.get(this.samLocalVariable); } - public getServiceName(): string { - return this.get(this.serviceNameVariable); - } - public getTracingCaptureError(): string { return this.get(this.tracerCaptureErrorVariable); } @@ -43,9 +35,6 @@ class EnvironmentVariablesService extends CommonEnvironmentVariablesService impl return this.get(this.tracingEnabledVariable); } - public getXrayTraceId(): string { - return super.getXrayTraceId(); - } } export { From 88ae5f1f6bde622214b99f4241d0826a747d6b43 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Thu, 27 Oct 2022 10:51:37 +0200 Subject: [PATCH 5/5] chore: updated unit test case --- .../layer-publisher.test.ts.snap | 2 +- .../src/config/EnvironmentVariablesService.ts | 4 ++- .../EnvironmentVariablesService.test.ts | 25 +++++++++++++++++++ packages/tracer/src/Tracer.ts | 2 +- packages/tracer/src/TracerInterface.ts | 2 +- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/layer-publisher/tests/unit/__snapshots__/layer-publisher.test.ts.snap b/layer-publisher/tests/unit/__snapshots__/layer-publisher.test.ts.snap index 161eb78d35..9e6b8f7ad7 100644 --- a/layer-publisher/tests/unit/__snapshots__/layer-publisher.test.ts.snap +++ b/layer-publisher/tests/unit/__snapshots__/layer-publisher.test.ts.snap @@ -32,7 +32,7 @@ Object { "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "c2f621503b147cecccf2e6cc6df420a8f11ee29ae042d2c1f523cf5db3f47ca2.zip", + "S3Key": "dbdb3f66eaeed03649521bf73dbcdd95a713086afccbac3f57fa407ffb76bdaa.zip", }, "Description": "Lambda Powertools for TypeScript version 1.0.1", "LayerName": "AWSLambdaPowertoolsTypeScript", diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index d2716d6c72..380bbc0458 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -52,9 +52,11 @@ class EnvironmentVariablesService extends ConfigService { * * @returns {string} */ - public getXrayTraceId(): string { + public getXrayTraceId(): string | undefined { const xRayTraceId = this.get(this.xRayTraceIdVariable); + if (xRayTraceId === '') return undefined; + return xRayTraceId.split(';')[0].replace('Root=', ''); } diff --git a/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts index 33177252fa..692a5b1ff0 100644 --- a/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts +++ b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts @@ -82,6 +82,31 @@ describe('Class: EnvironmentVariablesService', () => { // Assess expect(value).toEqual('abcd123456789'); }); + test('It returns the value of the Root X-Ray segment ID properly formatted', () => { + + // Prepare + process.env._X_AMZN_TRACE_ID = 'Root=1-5759e988-bd862e3fe1be46a994272793;Parent=557abcec3ee5a047;Sampled=1'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getXrayTraceId(); + + // Assess + expect(value).toEqual('1-5759e988-bd862e3fe1be46a994272793'); + }); + + test('It returns the value of the Root X-Ray segment ID properly formatted', () => { + + // Prepare + delete process.env._X_AMZN_TRACE_ID; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getXrayTraceId(); + + // Assess + expect(value).toEqual(undefined); + }); }); diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index a583452025..09ac5e3314 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -497,7 +497,7 @@ class Tracer extends Utility implements TracerInterface { * * @returns string - The root X-Ray trace id. */ - public getRootXrayTraceId(): string { + public getRootXrayTraceId(): string | undefined { return this.envVarsService.getXrayTraceId(); } diff --git a/packages/tracer/src/TracerInterface.ts b/packages/tracer/src/TracerInterface.ts index fd94db45cd..128a2c5553 100644 --- a/packages/tracer/src/TracerInterface.ts +++ b/packages/tracer/src/TracerInterface.ts @@ -12,7 +12,7 @@ interface TracerInterface { captureLambdaHandler(options?: CaptureLambdaHandlerOptions): HandlerMethodDecorator captureMethod(options?: CaptureMethodOptions): MethodDecorator getSegment(): Segment | Subsegment - getRootXrayTraceId(): string + getRootXrayTraceId(): string | undefined isTracingEnabled(): boolean putAnnotation: (key: string, value: string | number | boolean) => void putMetadata: (key: string, value: unknown, namespace?: string | undefined) => void