From f081e223f9a0b71df69958acababfe09dad3c83c Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 20 Oct 2023 23:35:12 +0200 Subject: [PATCH 1/5] chore(logger): refactor types and interfaces --- packages/logger/src/Logger.ts | 169 +++-- .../src/config/EnvironmentVariablesService.ts | 2 +- packages/logger/src/constants.ts | 17 + packages/logger/src/formatter/LogFormatter.ts | 32 +- .../logger/src/{log => formatter}/LogItem.ts | 2 +- .../src/formatter/PowertoolsLogFormatter.ts | 12 +- packages/logger/src/index.ts | 2 +- .../ConfigServiceInterface.ts | 0 .../LogFormatterInterface.ts | 22 +- .../src/{log => types}/LogItemInterface.ts | 2 +- packages/logger/src/types/Logger.ts | 59 +- packages/logger/src/types/PowertoolsLog.ts | 85 +++ .../logger/src/types/formats/PowertoolsLog.ts | 93 --- packages/logger/src/types/formats/index.ts | 1 - packages/logger/src/types/index.ts | 3 +- .../tests/e2e/sampleRate.decorator.test.ts | 11 +- .../EnvironmentVariablesService.test.ts | 4 +- packages/logger/tests/unit/Logger.test.ts | 596 ++++++++---------- .../formatter/PowertoolsLogFormatter.test.ts | 14 +- .../tests/unit/middleware/middy.test.ts | 52 +- 20 files changed, 535 insertions(+), 643 deletions(-) create mode 100644 packages/logger/src/constants.ts rename packages/logger/src/{log => formatter}/LogItem.ts (95%) rename packages/logger/src/{config => types}/ConfigServiceInterface.ts (100%) rename packages/logger/src/{formatter => types}/LogFormatterInterface.ts (51%) rename packages/logger/src/{log => types}/LogItemInterface.ts (75%) create mode 100644 packages/logger/src/types/PowertoolsLog.ts delete mode 100644 packages/logger/src/types/formats/PowertoolsLog.ts delete mode 100644 packages/logger/src/types/formats/index.ts rename packages/logger/tests/unit/{config => }/EnvironmentVariablesService.test.ts (97%) diff --git a/packages/logger/src/Logger.ts b/packages/logger/src/Logger.ts index 5810a7b2d5..6fe323ef3e 100644 --- a/packages/logger/src/Logger.ts +++ b/packages/logger/src/Logger.ts @@ -1,30 +1,31 @@ -import { randomInt } from 'node:crypto'; -import { Console } from 'node:console'; -import type { Context, Handler } from 'aws-lambda'; import { Utility } from '@aws-lambda-powertools/commons'; -import { PowertoolsLogFormatter } from './formatter/PowertoolsLogFormatter.js'; -import { LogFormatterInterface } from './formatter/LogFormatterInterface.js'; -import { LogItem } from './log/LogItem.js'; +import type { HandlerMethodDecorator } from '@aws-lambda-powertools/commons/types'; +import type { Context, Handler } from 'aws-lambda'; import merge from 'lodash.merge'; -import { ConfigServiceInterface } from './config/ConfigServiceInterface.js'; +import { Console } from 'node:console'; +import { randomInt } from 'node:crypto'; import { EnvironmentVariablesService } from './config/EnvironmentVariablesService.js'; -import { LogJsonIndent } from './types/Logger.js'; +import { LogJsonIndent } from './constants.js'; +import { LogItem } from './formatter/LogItem.js'; +import { PowertoolsLogFormatter } from './formatter/PowertoolsLogFormatter.js'; +import type { ConfigServiceInterface } from './types/ConfigServiceInterface.js'; import type { Environment, LogAttributes, LogLevel, LogLevelThresholds, } from './types/Log.js'; +import type { LogFormatterInterface } from './types/LogFormatterInterface.js'; import type { ClassThatLogs, - HandlerMethodDecorator, - LambdaFunctionContext, ConstructorOptions, + HandlerOptions, LogItemExtraInput, LogItemMessage, - PowertoolLogData, - HandlerOptions, + LoggerInterface, + PowertoolsLogData, } from './types/Logger.js'; + /** * ## Intro * The Logger utility provides an opinionated logger with output structured as JSON. @@ -111,7 +112,7 @@ import type { * @implements {ClassThatLogs} * @see https://docs.powertools.aws.dev/lambda-typescript/latest/core/logger/ */ -class Logger extends Utility implements ClassThatLogs { +class Logger extends Utility implements LoggerInterface { /** * Console instance used to print logs. * @@ -155,9 +156,9 @@ class Logger extends Utility implements ClassThatLogs { SILENT: 28, }; - private persistentLogAttributes?: LogAttributes = {}; + private persistentLogAttributes: LogAttributes = {}; - private powertoolLogData: PowertoolLogData = {}; + private powertoolsLogData: PowertoolsLogData = {}; /** * Log level used by the current instance of Logger. @@ -187,17 +188,15 @@ class Logger extends Utility implements ClassThatLogs { * @returns {void} */ public addContext(context: Context): void { - const lambdaContext: Partial = { - invokedFunctionArn: context.invokedFunctionArn, - coldStart: this.getColdStart(), - awsRequestId: context.awsRequestId, - memoryLimitInMB: Number(context.memoryLimitInMB), - functionName: context.functionName, - functionVersion: context.functionVersion, - }; - - this.addToPowertoolLogData({ - lambdaContext, + this.addToPowertoolsLogData({ + lambdaContext: { + invokedFunctionArn: context.invokedFunctionArn, + coldStart: this.getColdStart(), + awsRequestId: context.awsRequestId, + memoryLimitInMB: context.memoryLimitInMB, + functionName: context.functionName, + functionVersion: context.functionVersion, + }, }); } @@ -229,23 +228,27 @@ class Logger extends Utility implements ClassThatLogs { * @returns {Logger} */ public createChild(options: ConstructorOptions = {}): Logger { - const parentsOptions = { - logLevel: this.getLevelName(), - customConfigService: this.getCustomConfigService(), - logFormatter: this.getLogFormatter(), - sampleRateValue: this.powertoolLogData.sampleRateValue, - }; - const parentsPowertoolsLogData = this.getPowertoolLogData(); const childLogger = this.createLogger( - merge(parentsOptions, parentsPowertoolsLogData, options) + // Merge parent logger options with options passed to createChild, + // the latter having precedence. + merge( + {}, + { + logLevel: this.getLevelName(), + serviceName: this.powertoolsLogData.serviceName, + sampleRateValue: this.powertoolsLogData.sampleRateValue, + logFormatter: this.getLogFormatter(), + customConfigService: this.getCustomConfigService(), + environment: this.powertoolsLogData.environment, + persistentLogAttributes: this.persistentLogAttributes, + }, + options + ) ); - - const parentsPersistentLogAttributes = this.getPersistentLogAttributes(); - childLogger.addPersistentLogAttributes(parentsPersistentLogAttributes); - - if (parentsPowertoolsLogData.lambdaContext) { - childLogger.addContext(parentsPowertoolsLogData.lambdaContext as Context); - } + if (this.powertoolsLogData.lambdaContext) + childLogger.addContext( + this.powertoolsLogData.lambdaContext as unknown as Context + ); return childLogger; } @@ -315,7 +318,7 @@ class Logger extends Utility implements ClassThatLogs { * @returns {LogAttributes} */ public getPersistentLogAttributes(): LogAttributes { - return this.persistentLogAttributes as LogAttributes; + return this.persistentLogAttributes; } /** @@ -425,8 +428,8 @@ class Logger extends Utility implements ClassThatLogs { logger.addContext(context); let shouldLogEvent = undefined; - if (options && options.hasOwnProperty('logEvent')) { - shouldLogEvent = options.logEvent; + if (Object.hasOwn(options || {}, 'logEvent')) { + shouldLogEvent = options!.logEvent; } logger.logEventIfEnabled(event, shouldLogEvent); } @@ -439,9 +442,7 @@ class Logger extends Utility implements ClassThatLogs { * @returns {void} */ public logEventIfEnabled(event: unknown, overwriteValue?: boolean): void { - if (!this.shouldLogEvent(overwriteValue)) { - return; - } + if (!this.shouldLogEvent(overwriteValue)) return; this.info('Lambda invocation event', { event }); } @@ -453,7 +454,7 @@ class Logger extends Utility implements ClassThatLogs { * @returns {void} */ public refreshSampleRateCalculation(): void { - this.setInitialSampleRate(this.powertoolLogData.sampleRateValue); + this.setInitialSampleRate(this.powertoolsLogData.sampleRateValue); } /** @@ -473,11 +474,11 @@ class Logger extends Utility implements ClassThatLogs { * @returns {void} */ public removePersistentLogAttributes(keys: string[]): void { - keys.forEach((key) => { - if (this.persistentLogAttributes && key in this.persistentLogAttributes) { + for (const key of keys) { + if (Object.hasOwn(this.persistentLogAttributes, key)) { delete this.persistentLogAttributes[key]; } - }); + } } /** @@ -559,16 +560,12 @@ class Logger extends Utility implements ClassThatLogs { /** * It stores information that is printed in all log items. * - * @param {Partial} attributesArray + * @param {Partial} attributes * @private * @returns {void} */ - private addToPowertoolLogData( - ...attributesArray: Array> - ): void { - attributesArray.forEach((attributes: Partial) => { - merge(this.powertoolLogData, attributes); - }); + private addToPowertoolsLogData(attributes: Partial): void { + merge(this.powertoolsLogData, attributes); } /** @@ -595,7 +592,7 @@ class Logger extends Utility implements ClassThatLogs { message: typeof input === 'string' ? input : input.message, xRayTraceId: this.envVarsService.getXrayTraceId(), }, - this.getPowertoolLogData() + this.getPowertoolsLogData() ); let additionalLogAttributes: LogAttributes = {}; @@ -665,15 +662,15 @@ class Logger extends Utility implements ClassThatLogs { * @returns - The name of the log level */ private getLogLevelNameFromNumber(logLevel: number): Uppercase { - const found = Object.entries(this.logLevelThresholds).find( - ([key, value]) => { - if (value === logLevel) { - return key; - } + let found; + for (const [key, value] of Object.entries(this.logLevelThresholds)) { + if (value === logLevel) { + found = key; + break; } - )!; + } - return found[0] as Uppercase; + return found as Uppercase; } /** @@ -683,8 +680,8 @@ class Logger extends Utility implements ClassThatLogs { * @private * @returns {LogAttributes} */ - private getPowertoolLogData(): PowertoolLogData { - return this.powertoolLogData; + private getPowertoolsLogData(): PowertoolsLogData { + return this.powertoolsLogData; } /** @@ -890,14 +887,14 @@ class Logger extends Utility implements ClassThatLogs { * @returns {void} */ private setInitialSampleRate(sampleRateValue?: number): void { - this.powertoolLogData.sampleRateValue = 0; + this.powertoolsLogData.sampleRateValue = 0; const constructorValue = sampleRateValue; const customConfigValue = this.getCustomConfigService()?.getSampleRateValue(); const envVarsValue = this.getEnvVarsService().getSampleRateValue(); for (const value of [constructorValue, customConfigValue, envVarsValue]) { if (this.isValidSampleRate(value)) { - this.powertoolLogData.sampleRateValue = value; + this.powertoolsLogData.sampleRateValue = value; if (value && randomInt(0, 100) / 100 <= value) { this.setLogLevel('DEBUG'); @@ -972,7 +969,7 @@ class Logger extends Utility implements ClassThatLogs { this.setCustomConfigService(customConfigService); this.setInitialLogLevel(logLevel); this.setLogFormatter(logFormatter); - this.setPowertoolLogData(serviceName, environment); + this.setPowertoolsLogData(serviceName, environment); this.setInitialSampleRate(sampleRateValue); this.setLogEvent(); this.setLogIndentation(); @@ -991,26 +988,24 @@ class Logger extends Utility implements ClassThatLogs { * @private * @returns {void} */ - private setPowertoolLogData( + private setPowertoolsLogData( serviceName?: string, environment?: Environment, persistentLogAttributes: LogAttributes = {} ): void { - this.addToPowertoolLogData( - { - awsRegion: this.getEnvVarsService().getAwsRegion(), - environment: - environment || - this.getCustomConfigService()?.getCurrentEnvironment() || - this.getEnvVarsService().getCurrentEnvironment(), - serviceName: - serviceName || - this.getCustomConfigService()?.getServiceName() || - this.getEnvVarsService().getServiceName() || - this.getDefaultServiceName(), - }, - persistentLogAttributes - ); + this.addToPowertoolsLogData({ + awsRegion: this.getEnvVarsService().getAwsRegion(), + environment: + environment || + this.getCustomConfigService()?.getCurrentEnvironment() || + this.getEnvVarsService().getCurrentEnvironment(), + serviceName: + serviceName || + this.getCustomConfigService()?.getServiceName() || + this.getEnvVarsService().getServiceName() || + this.getDefaultServiceName(), + }); + this.addPersistentLogAttributes(persistentLogAttributes); } } diff --git a/packages/logger/src/config/EnvironmentVariablesService.ts b/packages/logger/src/config/EnvironmentVariablesService.ts index a9c0786eb6..9627b2c018 100644 --- a/packages/logger/src/config/EnvironmentVariablesService.ts +++ b/packages/logger/src/config/EnvironmentVariablesService.ts @@ -1,4 +1,4 @@ -import { ConfigServiceInterface } from './ConfigServiceInterface.js'; +import { ConfigServiceInterface } from '../types/ConfigServiceInterface.js'; import { EnvironmentVariablesService as CommonEnvironmentVariablesService } from '@aws-lambda-powertools/commons'; /** diff --git a/packages/logger/src/constants.ts b/packages/logger/src/constants.ts new file mode 100644 index 0000000000..90a26baa24 --- /dev/null +++ b/packages/logger/src/constants.ts @@ -0,0 +1,17 @@ +/** + * The indent level for JSON logs. + * + * By default Logger will use the `LogJsonIndent.COMPACT` indent level, which + * produces logs on a single line. This is the most efficient option for + * CloudWatch Logs. + * + * When enabling the `POWERTOOLS_DEV` environment variable, Logger will use the + * `LogJsonIndent.PRETTY` indent level, which indents the JSON logs for easier + * reading. + */ +const LogJsonIndent = { + PRETTY: 4, + COMPACT: 0, +} as const; + +export { LogJsonIndent }; diff --git a/packages/logger/src/formatter/LogFormatter.ts b/packages/logger/src/formatter/LogFormatter.ts index ccdf8b67b3..42a29b7636 100644 --- a/packages/logger/src/formatter/LogFormatter.ts +++ b/packages/logger/src/formatter/LogFormatter.ts @@ -1,24 +1,7 @@ -import { LogFormatterInterface } from './LogFormatterInterface.js'; -import { LogAttributes } from '../types/Log.js'; -import { UnformattedAttributes } from '../types/Logger.js'; -import { LogItem } from '../log/LogItem.js'; - -/** - * Typeguard to monkey patch Error to add a cause property. - * - * This is needed because the `cause` property was added in Node 16.x. - * Since we want to be able to format errors in Node 14.x, we need to - * add this property ourselves. We can remove this once we drop support - * for Node 14.x. - * - * @see 1361 - * @see https://nodejs.org/api/errors.html#errors_error_cause - */ -const isErrorWithCause = ( - error: Error -): error is Error & { cause: unknown } => { - return 'cause' in error; -}; +import type { LogFormatterInterface } from '../types/LogFormatterInterface.js'; +import type { LogAttributes } from '../types/Log.js'; +import type { UnformattedAttributes } from '../types/Logger.js'; +import { LogItem } from './LogItem.js'; /** * This class defines and implements common methods for the formatting of log attributes. @@ -52,11 +35,10 @@ abstract class LogFormatter implements LogFormatterInterface { location: this.getCodeLocation(error.stack), message: error.message, stack: error.stack, - cause: isErrorWithCause(error) - ? error.cause instanceof Error + cause: + error.cause instanceof Error ? this.formatError(error.cause) - : error.cause - : undefined, + : error.cause, }; } diff --git a/packages/logger/src/log/LogItem.ts b/packages/logger/src/formatter/LogItem.ts similarity index 95% rename from packages/logger/src/log/LogItem.ts rename to packages/logger/src/formatter/LogItem.ts index 4183017b4f..011fa5625d 100644 --- a/packages/logger/src/log/LogItem.ts +++ b/packages/logger/src/formatter/LogItem.ts @@ -1,5 +1,5 @@ import merge from 'lodash.merge'; -import { LogItemInterface } from './LogItemInterface.js'; +import { LogItemInterface } from '../types/LogItemInterface.js'; import { LogAttributes } from '../types/Log.js'; class LogItem implements LogItemInterface { diff --git a/packages/logger/src/formatter/PowertoolsLogFormatter.ts b/packages/logger/src/formatter/PowertoolsLogFormatter.ts index f88630bf2a..afa78a53f5 100644 --- a/packages/logger/src/formatter/PowertoolsLogFormatter.ts +++ b/packages/logger/src/formatter/PowertoolsLogFormatter.ts @@ -1,12 +1,12 @@ +import type { LogAttributes } from '../types/Log.js'; +import type { UnformattedAttributes } from '../types/Logger.js'; +import type { PowertoolsLog } from '../types/PowertoolsLog.js'; import { LogFormatter } from './LogFormatter.js'; -import { LogAttributes } from '../types/Log.js'; -import { UnformattedAttributes } from '../types/Logger.js'; -import { PowertoolsLog } from '../types/formats/PowertoolsLog.js'; -import { LogItem } from '../log/LogItem.js'; +import { LogItem } from './LogItem.js'; /** * This class is used to transform a set of log key-value pairs - * in the AWS Lambda Powertools' default structure log format. + * in the Powertools for AWS Lambda default structure log format. * * @class * @extends {LogFormatter} @@ -36,9 +36,7 @@ class PowertoolsLogFormatter extends LogFormatter { timestamp: this.formatTimestamp(attributes.timestamp), xray_trace_id: attributes.xRayTraceId, }; - const powertoolsLogItem = new LogItem({ attributes: baseAttributes }); - powertoolsLogItem.addAttributes(additionalLogAttributes); return powertoolsLogItem; diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 096d26bb30..1fe46bcf9b 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,3 +1,3 @@ export { Logger } from './Logger.js'; export { LogFormatter } from './formatter/LogFormatter.js'; -export { LogItem } from './log/LogItem.js'; +export { LogItem } from './formatter/LogItem.js'; diff --git a/packages/logger/src/config/ConfigServiceInterface.ts b/packages/logger/src/types/ConfigServiceInterface.ts similarity index 100% rename from packages/logger/src/config/ConfigServiceInterface.ts rename to packages/logger/src/types/ConfigServiceInterface.ts diff --git a/packages/logger/src/formatter/LogFormatterInterface.ts b/packages/logger/src/types/LogFormatterInterface.ts similarity index 51% rename from packages/logger/src/formatter/LogFormatterInterface.ts rename to packages/logger/src/types/LogFormatterInterface.ts index 49d35154c3..fc783b8464 100644 --- a/packages/logger/src/formatter/LogFormatterInterface.ts +++ b/packages/logger/src/types/LogFormatterInterface.ts @@ -1,6 +1,6 @@ -import { LogAttributes } from '../types/Log.js'; -import { UnformattedAttributes } from '../types/Logger.js'; -import { LogItem } from '../log/LogItem.js'; +import { LogAttributes } from './Log.js'; +import { UnformattedAttributes } from './Logger.js'; +import { LogItem } from '../formatter/LogItem.js'; /** * @interface @@ -25,6 +25,22 @@ interface LogFormatterInterface { * @returns {LogAttributes} */ formatError(error: Error): LogAttributes; + + /** + * It formats a date into a string in simplified extended ISO format (ISO 8601). + * + * @param {Date} now + * @returns {string} + */ + formatTimestamp(now: Date): string; + + /** + * It returns a string containing the location of an error, given a particular stack trace. + * + * @param stack + * @returns {string} + */ + getCodeLocation(stack?: string): string; } export { LogFormatterInterface }; diff --git a/packages/logger/src/log/LogItemInterface.ts b/packages/logger/src/types/LogItemInterface.ts similarity index 75% rename from packages/logger/src/log/LogItemInterface.ts rename to packages/logger/src/types/LogItemInterface.ts index ed0c89bb0b..f5c2c73971 100644 --- a/packages/logger/src/log/LogItemInterface.ts +++ b/packages/logger/src/types/LogItemInterface.ts @@ -1,4 +1,4 @@ -import { LogAttributes } from '../types/Log.js'; +import { LogAttributes } from './Log.js'; interface LogItemInterface { addAttributes(attributes: LogAttributes): void; diff --git a/packages/logger/src/types/Logger.ts b/packages/logger/src/types/Logger.ts index c937d66542..4ae7b6b1ae 100644 --- a/packages/logger/src/types/Logger.ts +++ b/packages/logger/src/types/Logger.ts @@ -1,17 +1,12 @@ +import { ConfigServiceInterface } from './ConfigServiceInterface.js'; +import { LogFormatterInterface } from './LogFormatterInterface.js'; import type { - AsyncHandler, - LambdaInterface, - SyncHandler, -} from '@aws-lambda-powertools/commons/types'; -import { Handler } from 'aws-lambda'; -import { ConfigServiceInterface } from '../config/ConfigServiceInterface.js'; -import { LogFormatterInterface } from '../formatter/LogFormatterInterface.js'; -import { Environment, LogAttributes, LogAttributesWithMessage, LogLevel, } from './Log.js'; +import type { Context } from 'aws-lambda'; type ClassThatLogs = { [key in Exclude, 'silent'>]: ( @@ -20,6 +15,7 @@ type ClassThatLogs = { ) => void; }; +// TODO: see if we can rename this type HandlerOptions = { logEvent?: boolean; clearState?: boolean; @@ -35,32 +31,28 @@ type ConstructorOptions = { environment?: Environment; }; -type LambdaFunctionContext = { - functionName: string; - memoryLimitInMB: number; - functionVersion: string; +type LambdaFunctionContext = Pick< + Context, + | 'functionName' + | 'memoryLimitInMB' + | 'functionVersion' + | 'invokedFunctionArn' + | 'awsRequestId' +> & { coldStart: boolean; - invokedFunctionArn: string; - awsRequestId: string; }; -type PowertoolLogData = LogAttributes & { +type PowertoolsLogData = LogAttributes & { environment?: Environment; serviceName: string; sampleRateValue: number; - lambdaFunctionContext: LambdaFunctionContext; + lambdaContext?: LambdaFunctionContext; xRayTraceId?: string; awsRegion: string; }; -type UnformattedAttributes = { - environment?: Environment; +type UnformattedAttributes = PowertoolsLogData & { error?: Error; - serviceName: string; - sampleRateValue?: number; - lambdaContext?: LambdaFunctionContext; - xRayTraceId?: string; - awsRegion: string; logLevel: LogLevel; timestamp: Date; message: string; @@ -69,27 +61,20 @@ type UnformattedAttributes = { type LogItemMessage = string | LogAttributesWithMessage; type LogItemExtraInput = [Error | string] | LogAttributes[]; -type HandlerMethodDecorator = ( - target: LambdaInterface, - propertyKey: string | symbol, - descriptor: - | TypedPropertyDescriptor> - | TypedPropertyDescriptor> -) => void; +type LoggerInterface = ClassThatLogs & { + addContext(context: Context): void; + addPersistentLogAttributes(attributes?: LogAttributes): void; + appendKeys(attributes?: LogAttributes): void; +}; export { + LoggerInterface, ClassThatLogs, LogItemMessage, LogItemExtraInput, - HandlerMethodDecorator, LambdaFunctionContext, UnformattedAttributes, - PowertoolLogData, + PowertoolsLogData, ConstructorOptions, HandlerOptions, }; - -export const enum LogJsonIndent { - PRETTY = 4, - COMPACT = 0, -} diff --git a/packages/logger/src/types/PowertoolsLog.ts b/packages/logger/src/types/PowertoolsLog.ts new file mode 100644 index 0000000000..afa3d820f0 --- /dev/null +++ b/packages/logger/src/types/PowertoolsLog.ts @@ -0,0 +1,85 @@ +import type { LogAttributes, LogLevel } from './Log.js'; + +type PowertoolsLog = LogAttributes & { + /** + * Timestamp of actual log statement. + * + * @example "2020-05-24 18:17:33,774" + */ + timestamp?: string; + + /** + * Log level + * + * @example "INFO" + */ + level?: LogLevel; + + /** + * Service name defined. + * + * @example "payment" + */ + service: string; + + /** + * The value of the logging sampling rate in percentage. + * + * @example 0.1 + */ + sampling_rate?: number; + + /** + * Log statement value. Unserializable JSON values will be cast to string. + * + * @example "Collecting payment" + */ + message?: string; + + /** + * X-Ray Trace ID set by the Lambda runtime. + * + * @example "1-5759e988-bd862e3fe1be46a994272793" + */ + xray_trace_id?: string; + + /** + * Indicates whether the current execution experienced a cold start. + * + * @example false + */ + cold_start?: boolean; + + /** + * The name of the Lambda function. + * + * @example "example-powertools-HelloWorldFunction-1P1Z6B39FLU73" + */ + lambda_function_name?: string; + + /** + * The memory size of the Lambda function. + * + * Description: + * Example: 128 + */ + lambda_function_memory_size?: number; + + /** + * lambda_function_arn + * + * Description: The ARN of the Lambda function. + * Example: "arn:aws:lambda:eu-west-1:012345678910:function:example-powertools-HelloWorldFunction-1P1Z6B39FLU73" + */ + lambda_function_arn?: string; + + /** + * lambda_request_id + * + * Description: The request ID of the current invocation. + * Example: "899856cb-83d1-40d7-8611-9e78f15f32f4" + */ + lambda_request_id?: string; +}; + +export type { PowertoolsLog }; diff --git a/packages/logger/src/types/formats/PowertoolsLog.ts b/packages/logger/src/types/formats/PowertoolsLog.ts deleted file mode 100644 index 9406a2a5fe..0000000000 --- a/packages/logger/src/types/formats/PowertoolsLog.ts +++ /dev/null @@ -1,93 +0,0 @@ -import type { LogAttributes, LogLevel } from '../Log.js'; - -type PowertoolsLog = LogAttributes & { - /** - * timestamp - * - * Description: Timestamp of actual log statement. - * Example: "2020-05-24 18:17:33,774" - */ - timestamp?: string; - - /** - * level - * - * Description: Logging level - * Example: "INFO" - */ - level?: LogLevel; - - /** - * service - * - * Description: Service name defined. - * Example: "payment" - */ - service: string; - - /** - * sampling_rate - * - * Description: The value of the logging sampling rate in percentage. - * Example: 0.1 - */ - sampling_rate?: number; - - /** - * message - * - * Description: Log statement value. Unserializable JSON values will be cast to string. - * Example: "Collecting payment" - */ - message?: string; - - /** - * xray_trace_id - * - * Description: X-Ray Trace ID when Lambda function has enabled Tracing. - * Example: "1-5759e988-bd862e3fe1be46a994272793" - */ - xray_trace_id?: string; - - /** - * cold_start - * - * Description: Indicates whether the current execution experienced a cold start. - * Example: false - */ - cold_start?: boolean; - - /** - * lambda_function_name - * - * Description: The name of the Lambda function. - * Example: "example-powertools-HelloWorldFunction-1P1Z6B39FLU73" - */ - lambda_function_name?: string; - - /** - * lambda_function_memory_size - * - * Description: The memory size of the Lambda function. - * Example: 128 - */ - lambda_function_memory_size?: number; - - /** - * lambda_function_arn - * - * Description: The ARN of the Lambda function. - * Example: "arn:aws:lambda:eu-west-1:012345678910:function:example-powertools-HelloWorldFunction-1P1Z6B39FLU73" - */ - lambda_function_arn?: string; - - /** - * lambda_request_id - * - * Description: The request ID of the current invocation. - * Example: "899856cb-83d1-40d7-8611-9e78f15f32f4" - */ - lambda_request_id?: string; -}; - -export type { PowertoolsLog }; diff --git a/packages/logger/src/types/formats/index.ts b/packages/logger/src/types/formats/index.ts deleted file mode 100644 index 03dabd2013..0000000000 --- a/packages/logger/src/types/formats/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { PowertoolsLog } from './PowertoolsLog.js'; diff --git a/packages/logger/src/types/index.ts b/packages/logger/src/types/index.ts index 9c01595ede..3b5e19d7a9 100644 --- a/packages/logger/src/types/index.ts +++ b/packages/logger/src/types/index.ts @@ -11,10 +11,9 @@ export type { ClassThatLogs, LogItemMessage, LogItemExtraInput, - HandlerMethodDecorator, LambdaFunctionContext, UnformattedAttributes, - PowertoolLogData, + PowertoolsLogData, ConstructorOptions, HandlerOptions, } from './Logger.js'; diff --git a/packages/logger/tests/e2e/sampleRate.decorator.test.ts b/packages/logger/tests/e2e/sampleRate.decorator.test.ts index dfb60141ab..cf22722e7f 100644 --- a/packages/logger/tests/e2e/sampleRate.decorator.test.ts +++ b/packages/logger/tests/e2e/sampleRate.decorator.test.ts @@ -82,16 +82,17 @@ describe(`Logger E2E tests, sample rate and injectLambdaContext()`, () => { if (logMessages.length === 1 && logMessages[0].includes('ERROR')) { countNotSampled++; } else if ( - logMessages.length === 5 && - logMessages[0].includes( - 'Setting log level to DEBUG due to sampling rate' - ) + (logMessages.length === 5 && + logMessages[0].includes( + 'Setting log level to DEBUG due to sampling rate' + )) || + logMessages.length === 4 ) { countSampled++; } else { console.error(`Log group ${logGroupName} contains missing log`); throw new Error( - 'Sampled log should have either 1 error log or 4 logs of all levels' + 'Sampled log should have either 1 error log or 5 logs of all levels' ); } } diff --git a/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/logger/tests/unit/EnvironmentVariablesService.test.ts similarity index 97% rename from packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts rename to packages/logger/tests/unit/EnvironmentVariablesService.test.ts index 760f50cac9..8ac6924f00 100644 --- a/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts +++ b/packages/logger/tests/unit/EnvironmentVariablesService.test.ts @@ -1,9 +1,9 @@ /** * Test Logger EnvironmentVariablesService class * - * @group unit/logger/all + * @group unit/logger/config */ -import { EnvironmentVariablesService } from '../../../src/config/EnvironmentVariablesService.js'; +import { EnvironmentVariablesService } from '../../src/config/EnvironmentVariablesService.js'; describe('Class: EnvironmentVariablesService', () => { const ENVIRONMENT_VARIABLES = process.env; diff --git a/packages/logger/tests/unit/Logger.test.ts b/packages/logger/tests/unit/Logger.test.ts index c3ecc4729f..a983081093 100644 --- a/packages/logger/tests/unit/Logger.test.ts +++ b/packages/logger/tests/unit/Logger.test.ts @@ -1,22 +1,21 @@ /** * Test Logger class * - * @group unit/logger/all + * @group unit/logger/logger */ import context from '@aws-lambda-powertools/testing-utils/context'; import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { Logger, LogFormatter } from '../../src/index.js'; -import { ConfigServiceInterface } from '../../src/config/ConfigServiceInterface.js'; +import { ConfigServiceInterface } from '../../src/types/ConfigServiceInterface.js'; import { EnvironmentVariablesService } from '../../src/config/EnvironmentVariablesService.js'; import { PowertoolsLogFormatter } from '../../src/formatter/PowertoolsLogFormatter.js'; import { LogLevelThresholds, LogLevel } from '../../src/types/Log.js'; -import { +import type { ClassThatLogs, - LogJsonIndent, ConstructorOptions, } from '../../src/types/Logger.js'; +import { LogJsonIndent } from '../../src/constants.js'; import type { Context } from 'aws-lambda'; -import { Console } from 'node:console'; const mockDate = new Date(1466424490000); const dateSpy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate); @@ -26,6 +25,15 @@ const getConsoleMethod = ( method === 'critical' ? 'error' : (method.toLowerCase() as keyof Omit); +jest.mock('node:console', () => ({ + ...jest.requireActual('node:console'), + Console: jest.fn().mockImplementation(() => ({ + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + })), +})); describe('Class: Logger', () => { const ENVIRONMENT_VARIABLES = process.env; @@ -60,7 +68,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: '', @@ -103,14 +111,19 @@ describe('Class: Logger', () => { logIndentation: 0, logFormatter: expect.any(PowertoolsLogFormatter), logLevel: 8, // 100% sample rate value changes log level to DEBUG - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), logLevelThresholds: { ...logLevelThresholds, }, persistentLogAttributes: { awsAccountId: '123456789', }, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: 'prod', sampleRateValue: 1, @@ -139,12 +152,17 @@ describe('Class: Logger', () => { logIndentation: 0, logFormatter: expect.any(PowertoolsLogFormatter), logLevel: 12, - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), logLevelThresholds: { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 0, @@ -167,7 +185,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: '', @@ -195,7 +213,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: '', @@ -223,7 +241,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: '', @@ -251,7 +269,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: '', @@ -284,12 +302,17 @@ describe('Class: Logger', () => { logIndentation: 0, logFormatter: expect.any(PowertoolsLogFormatter), logLevel: 12, - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), logLevelThresholds: { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 0, @@ -312,7 +335,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 1, awsRegion: 'eu-west-1', environment: '', @@ -366,7 +389,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: 'dev', @@ -408,7 +431,7 @@ describe('Class: Logger', () => { version: '0.2.4', }, }, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: '', @@ -436,7 +459,7 @@ describe('Class: Logger', () => { expect(logger).toEqual( expect.objectContaining({ persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { sampleRateValue: 0, awsRegion: 'eu-west-1', environment: 'dev', @@ -468,7 +491,7 @@ describe('Class: Logger', () => { ['error', 'DOES', true, 'DOES', true, 'DOES', true, 'DOES', true], ['critical', 'DOES', true, 'DOES', true, 'DOES', true, 'DOES', true], ])( - 'Method: %p', + 'Method:', ( method: string, debugAction, @@ -488,10 +511,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(method)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(method) + ); // Act logger[methodOfLogger]('foo'); @@ -517,10 +540,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'INFO', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act logger[methodOfLogger]('foo'); @@ -546,10 +569,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'WARN', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act logger[methodOfLogger]('foo'); @@ -575,10 +598,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'ERROR', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act logger[methodOfLogger]('foo'); @@ -604,10 +627,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'SILENT', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act logger[methodOfLogger]('foo'); @@ -619,10 +642,10 @@ describe('Class: Logger', () => { // Prepare process.env.LOG_LEVEL = methodOfLogger.toUpperCase(); const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act logger[methodOfLogger]('foo'); @@ -649,10 +672,10 @@ describe('Class: Logger', () => { logLevel: 'SILENT', sampleRateValue: 0, }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act if (logger[methodOfLogger]) { logger[methodOfLogger]('foo'); @@ -670,10 +693,10 @@ describe('Class: Logger', () => { logLevel: 'SILENT', sampleRateValue: 1, }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act if (logger[methodOfLogger]) { logger[methodOfLogger]('foo'); @@ -682,9 +705,9 @@ describe('Class: Logger', () => { // Assess expect(logger.level).toBe(8); expect(logger.getLevelName()).toBe('DEBUG'); - expect(consoleSpy).toBeCalledTimes(1); + expect(consoleSpy).toBeCalledTimes(method === 'debug' ? 2 : 1); expect(consoleSpy).toHaveBeenNthCalledWith( - 1, + method === 'debug' ? 2 : 1, JSON.stringify({ level: method.toUpperCase(), message: 'foo', @@ -705,10 +728,10 @@ describe('Class: Logger', () => { () => { // Prepare const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act if (logger[methodOfLogger]) { logger[methodOfLogger]('foo'); @@ -740,10 +763,10 @@ describe('Class: Logger', () => { logLevel: 'DEBUG', }); logger.addContext(context); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act if (logger[methodOfLogger]) { logger[methodOfLogger]('foo'); @@ -757,7 +780,7 @@ describe('Class: Logger', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: method.toUpperCase(), @@ -778,10 +801,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); interface NestedObject { bool: boolean; str: string; @@ -997,10 +1020,10 @@ describe('Class: Logger', () => { aws_region: 'eu-west-1', }, }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act if (logger[methodOfLogger]) { logger[methodOfLogger]('foo'); @@ -1030,10 +1053,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act if (logger[methodOfLogger]) { logger[methodOfLogger]('foo'); @@ -1060,10 +1083,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); - + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); // Act if (logger[methodOfLogger]) { logger[methodOfLogger]('foo'); @@ -1090,9 +1113,10 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); const circularObject = { foo: 'bar', self: {}, @@ -1132,9 +1156,7 @@ describe('Class: Logger', () => { test('when a logged item has BigInt value, it does not throw TypeError', () => { // Prepare const logger = new Logger(); - jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); + jest.spyOn(logger['console'], getConsoleMethod(methodOfLogger)); const message = `This is an ${methodOfLogger} log with BigInt value`; const logItem = { value: BigInt(42) }; const errorMessage = 'Do not know how to serialize a BigInt'; @@ -1148,9 +1170,10 @@ describe('Class: Logger', () => { test('when a logged item has a BigInt value, it prints the log with value as a string', () => { // Prepare const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); const message = `This is an ${methodOfLogger} log with BigInt value`; const logItem = { value: BigInt(42) }; @@ -1176,9 +1199,10 @@ describe('Class: Logger', () => { test('when a logged item has empty string, null, or undefined values, it removes it', () => { // Prepare const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], getConsoleMethod(methodOfLogger)) - .mockImplementation(); + const consoleSpy = jest.spyOn( + logger['console'], + getConsoleMethod(methodOfLogger) + ); const message = `This is an ${methodOfLogger} log with empty, null, and undefined values`; const logItem = { value: 42, @@ -1210,7 +1234,7 @@ describe('Class: Logger', () => { ); describe('Method: addContext', () => { - test('when called during a cold start invocation, it populates the logger PowertoolLogData object with coldStart set to TRUE', () => { + test('when called during a cold start invocation, it populates the logger powertoolsLogData object with coldStart set to TRUE', () => { // Prepare const logger = new Logger(); @@ -1218,36 +1242,18 @@ describe('Class: Logger', () => { logger.addContext(context); // Assess - expect(logger).toEqual({ - console: expect.any(Console), - coldStart: false, // This is now false because the `coldStart` attribute has been already accessed once by the `addContext` method - customConfigService: undefined, - defaultServiceName: 'service_undefined', - envVarsService: expect.any(EnvironmentVariablesService), - logEvent: false, - logIndentation: 0, - logFormatter: expect.any(PowertoolsLogFormatter), - logLevel: 8, - logLevelThresholds: { - ...logLevelThresholds, - }, - persistentLogAttributes: {}, - powertoolLogData: { - awsRegion: 'eu-west-1', - environment: '', - lambdaContext: { - awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678', - coldStart: true, - functionName: 'foo-bar-function', - functionVersion: '$LATEST', - invokedFunctionArn: - 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - memoryLimitInMB: 128, - }, - sampleRateValue: 0, - serviceName: 'hello-world', - }, - }); + expect(logger).toEqual( + expect.objectContaining({ + coldStart: false, // This is now false because the `coldStart` attribute has been already accessed once by the `addContext` method + powertoolsLogData: expect.objectContaining({ + lambdaContext: expect.objectContaining({ + coldStart: true, + }), + sampleRateValue: 0, + serviceName: 'hello-world', + }), + }) + ); }); test('when called with a context object, the object is not mutated', () => { @@ -1294,7 +1300,7 @@ describe('Class: Logger', () => { // Assess expect(logger).toEqual( expect.objectContaining({ - powertoolLogData: expect.objectContaining({ + powertoolsLogData: expect.objectContaining({ lambdaContext: expect.objectContaining({ awsRequestId: context2.awsRequestId, }), @@ -1472,9 +1478,7 @@ describe('Class: Logger', () => { // Prepare const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext() public async handler( @@ -1502,7 +1506,7 @@ describe('Class: Logger', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -1518,9 +1522,7 @@ describe('Class: Logger', () => { test('it captures Lambda context information and adds it in the printed logs', async () => { // Prepare const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext() public async handler( @@ -1557,7 +1559,7 @@ describe('Class: Logger', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -1574,9 +1576,7 @@ describe('Class: Logger', () => { // Prepare const expectedReturnValue = 'Lambda invoked!'; const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext() public async handler( @@ -1616,7 +1616,7 @@ describe('Class: Logger', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -1638,7 +1638,6 @@ describe('Class: Logger', () => { biz: 'baz', }, }); - jest.spyOn(logger['console'], 'debug').mockImplementation(); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext({ clearState: true }) public async handler( @@ -1684,7 +1683,6 @@ describe('Class: Logger', () => { biz: 'baz', }, }); - jest.spyOn(logger['console'], 'debug').mockImplementation(); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext({ clearState: true }) public async handler( @@ -1726,9 +1724,7 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext({ logEvent: true }) public async handler( @@ -1752,7 +1748,7 @@ describe('Class: Logger', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -1775,10 +1771,7 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext() public async handler( @@ -1802,7 +1795,7 @@ describe('Class: Logger', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -1824,10 +1817,7 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { private readonly memberVariable: string; @@ -1863,7 +1853,7 @@ describe('Class: Logger', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -1885,9 +1875,7 @@ describe('Class: Logger', () => { const logger = new Logger({ logLevel: 'DEBUG', }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext() public async handler( @@ -1927,9 +1915,7 @@ describe('Class: Logger', () => { version: '1.0.0', }, }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); + const consoleSpy = jest.spyOn(logger['console'], 'info'); class LambdaFunction implements LambdaInterface { @logger.injectLambdaContext({ clearState: true, logEvent: true }) public async handler( @@ -2004,7 +1990,12 @@ describe('Class: Logger', () => { expect(parentLogger === grandchildLogger).toBe(false); expect(parentLogger).toEqual({ - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), coldStart: true, customConfigService: undefined, defaultServiceName: 'service_undefined', @@ -2017,7 +2008,7 @@ describe('Class: Logger', () => { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 0, @@ -2026,7 +2017,12 @@ describe('Class: Logger', () => { }); expect(childLogger).toEqual({ - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), coldStart: true, customConfigService: undefined, defaultServiceName: 'service_undefined', @@ -2039,7 +2035,7 @@ describe('Class: Logger', () => { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 1, @@ -2048,7 +2044,12 @@ describe('Class: Logger', () => { }); expect(grandchildLogger).toEqual({ - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), coldStart: true, customConfigService: undefined, defaultServiceName: 'service_undefined', @@ -2061,7 +2062,7 @@ describe('Class: Logger', () => { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 1, @@ -2089,7 +2090,7 @@ describe('Class: Logger', () => { ); const optionsWithSampleRateEnabled = { - sampleRateValue: 1, // 100% probability to make sure that the logs are sampled + sampleRateValue: 1, }; const childLoggerWithSampleRateEnabled = parentLogger.createChild( optionsWithSampleRateEnabled @@ -2106,14 +2107,24 @@ describe('Class: Logger', () => { expect(parentLogger === childLogger).toBe(false); expect(childLogger).toEqual({ ...parentLogger, - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), }); expect(parentLogger === childLoggerWithPermanentAttributes).toBe(false); expect(parentLogger === childLoggerWithSampleRateEnabled).toBe(false); expect(parentLogger === childLoggerWithErrorLogLevel).toBe(false); expect(parentLogger).toEqual({ - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), coldStart: true, customConfigService: undefined, defaultServiceName: 'service_undefined', @@ -2126,7 +2137,7 @@ describe('Class: Logger', () => { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 0, @@ -2135,7 +2146,12 @@ describe('Class: Logger', () => { }); expect(childLoggerWithPermanentAttributes).toEqual({ - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), coldStart: true, customConfigService: undefined, defaultServiceName: 'service_undefined', @@ -2151,7 +2167,7 @@ describe('Class: Logger', () => { extra: 'This is an attribute that will be logged only by the child logger', }, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 0, @@ -2160,7 +2176,12 @@ describe('Class: Logger', () => { }); expect(childLoggerWithSampleRateEnabled).toEqual({ - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), coldStart: true, customConfigService: undefined, defaultServiceName: 'service_undefined', @@ -2173,7 +2194,7 @@ describe('Class: Logger', () => { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 1, @@ -2182,7 +2203,12 @@ describe('Class: Logger', () => { }); expect(childLoggerWithErrorLogLevel).toEqual({ - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), coldStart: true, customConfigService: undefined, defaultServiceName: 'service_undefined', @@ -2195,7 +2221,7 @@ describe('Class: Logger', () => { ...logLevelThresholds, }, persistentLogAttributes: {}, - powertoolLogData: { + powertoolsLogData: { awsRegion: 'eu-west-1', environment: '', sampleRateValue: 0, @@ -2206,7 +2232,6 @@ describe('Class: Logger', () => { test('child logger should have same keys in persistentLogAttributes as its parent', () => { // Prepare - const INDENTATION = LogJsonIndent.COMPACT; const parentLogger = new Logger(); const childLogger = parentLogger.createChild(); @@ -2224,85 +2249,25 @@ describe('Class: Logger', () => { childLoggerWithKeys.removeKeys(['test_key']); // Assess - expect(childLogger).toEqual({ - console: expect.any(Console), - coldStart: true, - customConfigService: undefined, - defaultServiceName: 'service_undefined', - envVarsService: expect.any(EnvironmentVariablesService), - logEvent: false, - logIndentation: INDENTATION, - logFormatter: expect.any(PowertoolsLogFormatter), - logLevel: 8, - logLevelThresholds: { - ...logLevelThresholds, - }, - persistentLogAttributes: {}, - powertoolLogData: { - awsRegion: 'eu-west-1', - environment: '', - sampleRateValue: 0, - serviceName: 'hello-world', - }, - }); + expect(childLogger.getPersistentLogAttributes()).toEqual({}); - expect(childLoggerWithKeys).toEqual({ - console: expect.any(Console), - coldStart: true, - customConfigService: undefined, - defaultServiceName: 'service_undefined', - envVarsService: expect.any(EnvironmentVariablesService), - logEvent: false, - logIndentation: INDENTATION, - logFormatter: expect.any(PowertoolsLogFormatter), - logLevel: 8, - logLevelThresholds: { - ...logLevelThresholds, - }, - persistentLogAttributes: { - aws_account_id: '123456789012', - aws_region: 'eu-west-1', - logger: { - name: 'aws-lambda-powertool-typescript', - version: '0.2.4', - }, - }, - powertoolLogData: { - awsRegion: 'eu-west-1', - environment: '', - sampleRateValue: 0, - serviceName: 'hello-world', + expect(childLoggerWithKeys.getPersistentLogAttributes()).toEqual({ + aws_account_id: '123456789012', + aws_region: 'eu-west-1', + logger: { + name: 'aws-lambda-powertool-typescript', + version: '0.2.4', }, }); - expect(parentLogger).toEqual({ - console: expect.any(Console), - coldStart: true, - customConfigService: undefined, - defaultServiceName: 'service_undefined', - envVarsService: expect.any(EnvironmentVariablesService), - logEvent: false, - logIndentation: INDENTATION, - logFormatter: expect.any(PowertoolsLogFormatter), - logLevel: 8, - logLevelThresholds: { - ...logLevelThresholds, - }, - persistentLogAttributes: { - aws_account_id: '123456789012', - aws_region: 'eu-west-1', - logger: { - name: 'aws-lambda-powertool-typescript', - version: '0.2.4', - }, - test_key: 'key-for-test', - }, - powertoolLogData: { - awsRegion: 'eu-west-1', - environment: '', - sampleRateValue: 0, - serviceName: 'hello-world', + expect(parentLogger.getPersistentLogAttributes()).toEqual({ + aws_account_id: '123456789012', + aws_region: 'eu-west-1', + logger: { + name: 'aws-lambda-powertool-typescript', + version: '0.2.4', }, + test_key: 'key-for-test', }); }); @@ -2315,36 +2280,26 @@ describe('Class: Logger', () => { const childLoggerWithContext = parentLogger.createChild(); // Assess - expect(childLoggerWithContext).toEqual({ - console: expect.any(Console), - coldStart: false, // This is now false because the `coldStart` attribute has been already accessed once by the `addContext` method - customConfigService: undefined, - defaultServiceName: 'service_undefined', - envVarsService: expect.any(EnvironmentVariablesService), - logEvent: false, - logIndentation: 0, - logFormatter: expect.any(PowertoolsLogFormatter), - logLevel: 8, - logLevelThresholds: { - ...logLevelThresholds, - }, - persistentLogAttributes: {}, - powertoolLogData: { - awsRegion: 'eu-west-1', - environment: '', - lambdaContext: { - awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678', - coldStart: true, - functionName: 'foo-bar-function', - functionVersion: '$LATEST', - invokedFunctionArn: - 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - memoryLimitInMB: 128, + expect(childLoggerWithContext).toEqual( + expect.objectContaining({ + coldStart: false, // This is now false because the `coldStart` attribute has been already accessed once by the `addContext` method + powertoolsLogData: { + awsRegion: 'eu-west-1', + environment: '', + lambdaContext: { + awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678', + coldStart: true, + functionName: 'foo-bar-function', + functionVersion: '$LATEST', + invokedFunctionArn: + 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', + memoryLimitInMB: '128', + }, + sampleRateValue: 0, + serviceName: 'hello-world', }, - sampleRateValue: 0, - serviceName: 'hello-world', - }, - }); + }) + ); }); test('child logger should have the same logFormatter as its parent', () => { @@ -2414,7 +2369,12 @@ describe('Class: Logger', () => { // Assess expect(childLogger).toEqual({ ...parentLogger, - console: expect.any(Console), + console: expect.objectContaining({ + debug: expect.any(Function), + error: expect.any(Function), + info: expect.any(Function), + warn: expect.any(Function), + }), }); expect(childLogger).toEqual( @@ -2435,10 +2395,7 @@ describe('Class: Logger', () => { test('When the feature is disabled, it DOES NOT log the event', () => { // Prepare const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.logEventIfEnabled(event); @@ -2452,10 +2409,7 @@ describe('Class: Logger', () => { something: 'happened!', }; const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.logEventIfEnabled(event, true); @@ -2484,9 +2438,7 @@ describe('Class: Logger', () => { process.env.POWERTOOLS_DEV = 'true'; const INDENTATION = LogJsonIndent.PRETTY; const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); + const consoleSpy = jest.spyOn(console, 'info').mockImplementation(); // Act logger.info('Message with pretty identation'); @@ -2513,10 +2465,7 @@ describe('Class: Logger', () => { test('when the `POWERTOOLS_DEV` env var is NOT SET it makes log output as one-liner', () => { // Prepare const logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.info('Message without pretty identation'); @@ -2607,7 +2556,6 @@ describe('Class: Logger', () => { logLevel: 'ERROR', customConfigService: new MyCustomEnvironmentVariablesService(), }; - const logger: Logger = new Logger(loggerOptions); // Assess @@ -2655,11 +2603,7 @@ describe('Class: Logger', () => { customConfigService: new MyCustomEnvironmentVariablesService(), }; const logger: Logger = new Logger(loggerOptions); - - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.info('foo'); @@ -2692,11 +2636,7 @@ describe('Class: Logger', () => { customConfigService: new MyCustomEnvironmentVariablesService(), }; const logger: Logger = new Logger(loggerOptions); - - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.info('foo'); @@ -2719,17 +2659,25 @@ describe('Class: Logger', () => { // Prepare process.env.POWERTOOLS_LOGGER_SAMPLE_RATE = '1'; const logger: Logger = new Logger(); - const consoleSpy = jest - .spyOn(logger['console'], 'debug') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'debug'); // Act logger.debug('foo'); // Assess - expect(consoleSpy).toBeCalledTimes(1); + expect(consoleSpy).toBeCalledTimes(2); expect(consoleSpy).toHaveBeenNthCalledWith( 1, + JSON.stringify({ + level: 'DEBUG', + message: 'Setting log level to DEBUG due to sampling rate', + sampling_rate: 1, + service: 'hello-world', + timestamp: '2016-06-20T12:08:10.000Z', + xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793', + }) + ); + expect(consoleSpy).toHaveBeenNthCalledWith( + 2, JSON.stringify({ level: 'DEBUG', message: 'foo', @@ -2754,10 +2702,7 @@ describe('Class: Logger', () => { }; const logger: Logger = new Logger(loggerOptions); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.info('foo'); @@ -2782,10 +2727,7 @@ describe('Class: Logger', () => { logLevel: 'INFO', sampleRateValue: 42, }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.info('foo'); @@ -2818,10 +2760,7 @@ describe('Class: Logger', () => { }; const logger: Logger = new Logger(loggerOptions); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.info('foo'); @@ -2846,10 +2785,7 @@ describe('Class: Logger', () => { const logger: Logger = new Logger({ logLevel: 'INFO', }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.info('foo'); @@ -2875,10 +2811,7 @@ describe('Class: Logger', () => { logLevel: 'INFO', sampleRateValue: 1, }); - const consoleSpy = jest - .spyOn(logger['console'], 'info') - .mockImplementation(); - + const consoleSpy = jest.spyOn(logger['console'], 'info'); // Act logger.refreshSampleRateCalculation(); logger.info('foo'); @@ -2905,9 +2838,6 @@ describe('Class: Logger', () => { sampleRateValue: 0.1, // 10% probability }); - // suppress "Setting log level to DEBUG due to sampling rate" log messages - jest.spyOn(logger['console'], 'debug').mockImplementation(); - let logLevelChangedToDebug = 0; const numOfIterations = 1000; const minExpected = numOfIterations * 0.05; // Min expected based on 5% probability diff --git a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts index b7d5e3334a..3a97c9637b 100644 --- a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts +++ b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts @@ -1,13 +1,13 @@ /** * Test Logger formatter * - * @group unit/logger/all + * @group unit/logger/logFormatter */ import { AssertionError, strictEqual } from 'node:assert'; import { PowertoolsLogFormatter } from '../../../src/formatter/PowertoolsLogFormatter.js'; import { LogItem } from '../../../src/index.js'; -import { UnformattedAttributes } from '../../../src/types/Logger.js'; -import { LogAttributes } from '../../../src/types/Log.js'; +import type { UnformattedAttributes } from '../../../src/types/Logger.js'; +import type { LogAttributes } from '../../../src/types/Log.js'; describe('Class: PowertoolsLogFormatter', () => { const mockDate = new Date(1466424490000); @@ -22,7 +22,7 @@ describe('Class: PowertoolsLogFormatter', () => { // Prepare const formatter = new PowertoolsLogFormatter(); const unformattedAttributes: UnformattedAttributes = { - sampleRateValue: undefined, + sampleRateValue: 0, awsRegion: 'eu-west-1', environment: '', serviceName: 'hello-world', @@ -48,7 +48,7 @@ describe('Class: PowertoolsLogFormatter', () => { function_request_id: undefined, level: 'WARN', message: 'This is a WARN log', - sampling_rate: undefined, + sampling_rate: 0, service: 'hello-world', timestamp: '2016-06-20T12:08:10.000Z', xray_trace_id: '1-5759e988-bd862e3fe1be46a994272793', @@ -71,7 +71,7 @@ describe('Class: PowertoolsLogFormatter', () => { error: new Error('Something happened!'), lambdaContext: { functionName: 'my-lambda-function', - memoryLimitInMB: 123, + memoryLimitInMB: '123', functionVersion: '1.23.3', coldStart: true, invokedFunctionArn: @@ -91,7 +91,7 @@ describe('Class: PowertoolsLogFormatter', () => { expect(value.getAttributes()).toEqual({ cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:Example', - function_memory_size: 123, + function_memory_size: '123', function_name: 'my-lambda-function', function_request_id: 'abcdefg123456789', level: 'WARN', diff --git a/packages/logger/tests/unit/middleware/middy.test.ts b/packages/logger/tests/unit/middleware/middy.test.ts index a37fc5e816..02738d3a33 100644 --- a/packages/logger/tests/unit/middleware/middy.test.ts +++ b/packages/logger/tests/unit/middleware/middy.test.ts @@ -1,18 +1,15 @@ /** * Test Logger middleware * - * @group unit/logger/all + * @group unit/logger/middleware */ -import context from '@aws-lambda-powertools/testing-utils/context'; import { cleanupMiddlewares } from '@aws-lambda-powertools/commons'; -import { ConfigServiceInterface } from '../../../src/config/ConfigServiceInterface.js'; -import { EnvironmentVariablesService } from '../../../src/config/EnvironmentVariablesService.js'; -import { injectLambdaContext } from '../../../src/middleware/middy.js'; -import { Logger } from './../../../src/Logger.js'; +import context from '@aws-lambda-powertools/testing-utils/context'; import middy from '@middy/core'; -import { PowertoolsLogFormatter } from '../../../src/formatter/PowertoolsLogFormatter.js'; -import { Console } from 'node:console'; import type { Context } from 'aws-lambda'; +import { injectLambdaContext } from '../../../src/middleware/middy.js'; +import { ConfigServiceInterface } from '../../../src/types/ConfigServiceInterface.js'; +import { Logger } from './../../../src/Logger.js'; const mockDate = new Date(1466424490000); const dateSpy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate); @@ -52,11 +49,7 @@ describe('Middy middleware', () => { // Assess expect(logger).toEqual( expect.objectContaining({ - persistentLogAttributes: {}, - powertoolLogData: { - sampleRateValue: 0, - awsRegion: 'eu-west-1', - environment: '', + powertoolsLogData: expect.objectContaining({ lambdaContext: { awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678', coldStart: true, @@ -64,14 +57,9 @@ describe('Middy middleware', () => { functionVersion: '$LATEST', invokedFunctionArn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - memoryLimitInMB: 128, + memoryLimitInMB: '128', }, - serviceName: 'hello-world', - }, - envVarsService: expect.any(EnvironmentVariablesService), - customConfigService: undefined, - logLevel: 8, - logFormatter: expect.any(PowertoolsLogFormatter), + }), }) ); }); @@ -90,11 +78,7 @@ describe('Middy middleware', () => { // Assess const expectation = expect.objectContaining({ - persistentLogAttributes: {}, - powertoolLogData: { - sampleRateValue: 0, - awsRegion: 'eu-west-1', - environment: '', + powertoolsLogData: expect.objectContaining({ lambdaContext: { awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678', coldStart: true, @@ -102,15 +86,9 @@ describe('Middy middleware', () => { functionVersion: '$LATEST', invokedFunctionArn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - memoryLimitInMB: 128, + memoryLimitInMB: '128', }, - serviceName: 'hello-world', - }, - envVarsService: expect.any(EnvironmentVariablesService), - customConfigService: undefined, - logLevel: 8, - logFormatter: expect.any(PowertoolsLogFormatter), - console: expect.any(Console), + }), }); expect(logger).toEqual(expectation); expect(anotherLogger).toEqual(expectation); @@ -273,7 +251,7 @@ describe('Middy middleware', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -340,7 +318,7 @@ describe('Middy middleware', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -379,7 +357,7 @@ describe('Middy middleware', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', @@ -418,7 +396,7 @@ describe('Middy middleware', () => { cold_start: true, function_arn: 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', - function_memory_size: 128, + function_memory_size: '128', function_name: 'foo-bar-function', function_request_id: 'c6af9ac6-7b61-11e6-9a41-93e812345678', level: 'INFO', From 6a6abbe7086e3ab7cbd267d7336ecc228163f164 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 20 Oct 2023 23:58:10 +0200 Subject: [PATCH 2/5] chore: grouped type files --- packages/logger/src/Logger.ts | 16 +- packages/logger/src/formatter/LogFormatter.ts | 3 +- packages/logger/src/formatter/LogItem.ts | 3 +- .../src/formatter/PowertoolsLogFormatter.ts | 3 +- packages/logger/src/middleware/middy.ts | 6 +- packages/logger/src/types/Log.ts | 137 ++++++++++++++++++ .../logger/src/types/LogFormatterInterface.ts | 46 ------ packages/logger/src/types/LogItemInterface.ts | 9 -- packages/logger/src/types/Logger.ts | 35 ++++- packages/logger/src/types/PowertoolsLog.ts | 85 ----------- packages/logger/src/types/index.ts | 3 +- packages/logger/tests/unit/Logger.test.ts | 8 +- 12 files changed, 184 insertions(+), 170 deletions(-) delete mode 100644 packages/logger/src/types/LogFormatterInterface.ts delete mode 100644 packages/logger/src/types/LogItemInterface.ts delete mode 100644 packages/logger/src/types/PowertoolsLog.ts diff --git a/packages/logger/src/Logger.ts b/packages/logger/src/Logger.ts index 6fe323ef3e..f0d0e8b59d 100644 --- a/packages/logger/src/Logger.ts +++ b/packages/logger/src/Logger.ts @@ -14,12 +14,12 @@ import type { LogAttributes, LogLevel, LogLevelThresholds, + LogFormatterInterface, } from './types/Log.js'; -import type { LogFormatterInterface } from './types/LogFormatterInterface.js'; import type { - ClassThatLogs, + LogFunction, ConstructorOptions, - HandlerOptions, + InjectLambdaContextOptions, LogItemExtraInput, LogItemMessage, LoggerInterface, @@ -364,7 +364,9 @@ class Logger extends Utility implements LoggerInterface { * @see https://www.typescriptlang.org/docs/handbook/decorators.html#method-decorators * @returns {HandlerMethodDecorator} */ - public injectLambdaContext(options?: HandlerOptions): HandlerMethodDecorator { + public injectLambdaContext( + options?: InjectLambdaContextOptions + ): HandlerMethodDecorator { return (_target, _propertyKey, descriptor) => { /** * The descriptor.value is the method this decorator decorates, it cannot be undefined. @@ -412,7 +414,7 @@ class Logger extends Utility implements LoggerInterface { public static injectLambdaContextAfterOrOnError( logger: Logger, initialPersistentAttributes: LogAttributes, - options?: HandlerOptions + options?: InjectLambdaContextOptions ): void { if (options && options.clearState === true) { logger.setPersistentLogAttributes(initialPersistentAttributes); @@ -423,7 +425,7 @@ class Logger extends Utility implements LoggerInterface { logger: Logger, event: unknown, context: Context, - options?: HandlerOptions + options?: InjectLambdaContextOptions ): void { logger.addContext(context); @@ -762,7 +764,7 @@ class Logger extends Utility implements LoggerInterface { logLevel === 24 ? 'error' : (this.getLogLevelNameFromNumber(logLevel).toLowerCase() as keyof Omit< - ClassThatLogs, + LogFunction, 'critical' >); diff --git a/packages/logger/src/formatter/LogFormatter.ts b/packages/logger/src/formatter/LogFormatter.ts index 42a29b7636..478e04152f 100644 --- a/packages/logger/src/formatter/LogFormatter.ts +++ b/packages/logger/src/formatter/LogFormatter.ts @@ -1,5 +1,4 @@ -import type { LogFormatterInterface } from '../types/LogFormatterInterface.js'; -import type { LogAttributes } from '../types/Log.js'; +import type { LogAttributes, LogFormatterInterface } from '../types/Log.js'; import type { UnformattedAttributes } from '../types/Logger.js'; import { LogItem } from './LogItem.js'; diff --git a/packages/logger/src/formatter/LogItem.ts b/packages/logger/src/formatter/LogItem.ts index 011fa5625d..40435b06e6 100644 --- a/packages/logger/src/formatter/LogItem.ts +++ b/packages/logger/src/formatter/LogItem.ts @@ -1,6 +1,5 @@ import merge from 'lodash.merge'; -import { LogItemInterface } from '../types/LogItemInterface.js'; -import { LogAttributes } from '../types/Log.js'; +import type { LogAttributes, LogItemInterface } from '../types/Log.js'; class LogItem implements LogItemInterface { private attributes: LogAttributes = {}; diff --git a/packages/logger/src/formatter/PowertoolsLogFormatter.ts b/packages/logger/src/formatter/PowertoolsLogFormatter.ts index afa78a53f5..80c0406bbb 100644 --- a/packages/logger/src/formatter/PowertoolsLogFormatter.ts +++ b/packages/logger/src/formatter/PowertoolsLogFormatter.ts @@ -1,6 +1,5 @@ -import type { LogAttributes } from '../types/Log.js'; +import type { LogAttributes, PowertoolsLog } from '../types/Log.js'; import type { UnformattedAttributes } from '../types/Logger.js'; -import type { PowertoolsLog } from '../types/PowertoolsLog.js'; import { LogFormatter } from './LogFormatter.js'; import { LogItem } from './LogItem.js'; diff --git a/packages/logger/src/middleware/middy.ts b/packages/logger/src/middleware/middy.ts index 7d8b3099da..d40be85cd2 100644 --- a/packages/logger/src/middleware/middy.ts +++ b/packages/logger/src/middleware/middy.ts @@ -1,6 +1,6 @@ import { Logger } from '../Logger.js'; -import { LogAttributes } from '../types/Log.js'; -import { HandlerOptions } from '../types/Logger.js'; +import type { LogAttributes } from '../types/Log.js'; +import type { InjectLambdaContextOptions } from '../types/Logger.js'; import { LOGGER_KEY } from '@aws-lambda-powertools/commons'; import type { MiddlewareLikeObj, @@ -33,7 +33,7 @@ import type { */ const injectLambdaContext = ( target: Logger | Logger[], - options?: HandlerOptions + options?: InjectLambdaContextOptions ): MiddlewareLikeObj => { const loggers = target instanceof Array ? target : [target]; const persistentAttributes: LogAttributes[] = []; diff --git a/packages/logger/src/types/Log.ts b/packages/logger/src/types/Log.ts index 931ef10027..dd15a69f72 100644 --- a/packages/logger/src/types/Log.ts +++ b/packages/logger/src/types/Log.ts @@ -1,3 +1,6 @@ +import type { LogItem } from '../formatter/LogItem.js'; +import type { UnformattedAttributes } from './Logger.js'; + type LogLevelDebug = 'DEBUG'; type LogLevelInfo = 'INFO'; type LogLevelWarn = 'WARN'; @@ -32,6 +35,137 @@ type LogAttributesWithMessage = LogAttributes & { type Environment = 'dev' | 'local' | 'staging' | 'prod' | string; +type PowertoolsLog = LogAttributes & { + /** + * Timestamp of actual log statement. + * + * @example "2020-05-24 18:17:33,774" + */ + timestamp?: string; + + /** + * Log level + * + * @example "INFO" + */ + level?: LogLevel; + + /** + * Service name defined. + * + * @example "payment" + */ + service: string; + + /** + * The value of the logging sampling rate in percentage. + * + * @example 0.1 + */ + sampling_rate?: number; + + /** + * Log statement value. Unserializable JSON values will be cast to string. + * + * @example "Collecting payment" + */ + message?: string; + + /** + * X-Ray Trace ID set by the Lambda runtime. + * + * @example "1-5759e988-bd862e3fe1be46a994272793" + */ + xray_trace_id?: string; + + /** + * Indicates whether the current execution experienced a cold start. + * + * @example false + */ + cold_start?: boolean; + + /** + * The name of the Lambda function. + * + * @example "example-powertools-HelloWorldFunction-1P1Z6B39FLU73" + */ + lambda_function_name?: string; + + /** + * The memory size of the Lambda function. + * + * Description: + * Example: 128 + */ + lambda_function_memory_size?: number; + + /** + * lambda_function_arn + * + * Description: The ARN of the Lambda function. + * Example: "arn:aws:lambda:eu-west-1:012345678910:function:example-powertools-HelloWorldFunction-1P1Z6B39FLU73" + */ + lambda_function_arn?: string; + + /** + * lambda_request_id + * + * Description: The request ID of the current invocation. + * Example: "899856cb-83d1-40d7-8611-9e78f15f32f4" + */ + lambda_request_id?: string; +}; + +interface LogItemInterface { + addAttributes(attributes: LogAttributes): void; + getAttributes(): LogAttributes; + prepareForPrint(): void; + removeEmptyKeys(attributes: LogAttributes): LogAttributes; + setAttributes(attributes: LogAttributes): void; +} + +/** + * @interface + */ +interface LogFormatterInterface { + /** + * It formats key-value pairs of log attributes. + * + * @param {UnformattedAttributes} attributes + * @param {LogAttributes} additionalLogAttributes + * @returns {LogItem} + */ + formatAttributes( + attributes: UnformattedAttributes, + additionalLogAttributes: LogAttributes + ): LogItem; + + /** + * It formats a given Error parameter. + * + * @param {Error} error + * @returns {LogAttributes} + */ + formatError(error: Error): LogAttributes; + + /** + * It formats a date into a string in simplified extended ISO format (ISO 8601). + * + * @param {Date} now + * @returns {string} + */ + formatTimestamp(now: Date): string; + + /** + * It returns a string containing the location of an error, given a particular stack trace. + * + * @param stack + * @returns {string} + */ + getCodeLocation(stack?: string): string; +} + export type { LogAttributesWithMessage, LogAttributeValue, @@ -39,4 +173,7 @@ export type { LogLevelThresholds, LogAttributes, LogLevel, + PowertoolsLog, + LogItemInterface, + LogFormatterInterface, }; diff --git a/packages/logger/src/types/LogFormatterInterface.ts b/packages/logger/src/types/LogFormatterInterface.ts deleted file mode 100644 index fc783b8464..0000000000 --- a/packages/logger/src/types/LogFormatterInterface.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { LogAttributes } from './Log.js'; -import { UnformattedAttributes } from './Logger.js'; -import { LogItem } from '../formatter/LogItem.js'; - -/** - * @interface - */ -interface LogFormatterInterface { - /** - * It formats key-value pairs of log attributes. - * - * @param {UnformattedAttributes} attributes - * @param {LogAttributes} additionalLogAttributes - * @returns {LogItem} - */ - formatAttributes( - attributes: UnformattedAttributes, - additionalLogAttributes: LogAttributes - ): LogItem; - - /** - * It formats a given Error parameter. - * - * @param {Error} error - * @returns {LogAttributes} - */ - formatError(error: Error): LogAttributes; - - /** - * It formats a date into a string in simplified extended ISO format (ISO 8601). - * - * @param {Date} now - * @returns {string} - */ - formatTimestamp(now: Date): string; - - /** - * It returns a string containing the location of an error, given a particular stack trace. - * - * @param stack - * @returns {string} - */ - getCodeLocation(stack?: string): string; -} - -export { LogFormatterInterface }; diff --git a/packages/logger/src/types/LogItemInterface.ts b/packages/logger/src/types/LogItemInterface.ts deleted file mode 100644 index f5c2c73971..0000000000 --- a/packages/logger/src/types/LogItemInterface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { LogAttributes } from './Log.js'; - -interface LogItemInterface { - addAttributes(attributes: LogAttributes): void; - - getAttributes(): LogAttributes; -} - -export { LogItemInterface }; diff --git a/packages/logger/src/types/Logger.ts b/packages/logger/src/types/Logger.ts index 4ae7b6b1ae..67d22a2963 100644 --- a/packages/logger/src/types/Logger.ts +++ b/packages/logger/src/types/Logger.ts @@ -1,22 +1,22 @@ -import { ConfigServiceInterface } from './ConfigServiceInterface.js'; -import { LogFormatterInterface } from './LogFormatterInterface.js'; +import type { HandlerMethodDecorator } from '@aws-lambda-powertools/commons/types'; +import type { ConfigServiceInterface } from './ConfigServiceInterface.js'; import type { Environment, LogAttributes, LogAttributesWithMessage, LogLevel, + LogFormatterInterface, } from './Log.js'; import type { Context } from 'aws-lambda'; -type ClassThatLogs = { +type LogFunction = { [key in Exclude, 'silent'>]: ( input: LogItemMessage, ...extraInput: LogItemExtraInput ) => void; }; -// TODO: see if we can rename this -type HandlerOptions = { +type InjectLambdaContextOptions = { logEvent?: boolean; clearState?: boolean; }; @@ -61,20 +61,39 @@ type UnformattedAttributes = PowertoolsLogData & { type LogItemMessage = string | LogAttributesWithMessage; type LogItemExtraInput = [Error | string] | LogAttributes[]; -type LoggerInterface = ClassThatLogs & { +type LoggerInterface = { addContext(context: Context): void; addPersistentLogAttributes(attributes?: LogAttributes): void; appendKeys(attributes?: LogAttributes): void; + createChild(options?: ConstructorOptions): LoggerInterface; + critical(input: LogItemMessage, ...extraInput: LogItemExtraInput): void; + debug(input: LogItemMessage, ...extraInput: LogItemExtraInput): void; + error(input: LogItemMessage, ...extraInput: LogItemExtraInput): void; + getLevelName(): Uppercase; + getLogEvent(): boolean; + getPersistentLogAttributes(): LogAttributes; + info(input: LogItemMessage, ...extraInput: LogItemExtraInput): void; + injectLambdaContext( + options?: InjectLambdaContextOptions + ): HandlerMethodDecorator; + logEventIfEnabled(event: unknown, overwriteValue?: boolean): void; + refreshSampleRateCalculation(): void; + removeKeys(keys?: string[]): void; + removePersistentLogAttributes(keys?: string[]): void; + setLogLevel(logLevel: LogLevel): void; + setPersistentLogAttributes(attributes?: LogAttributes): void; + shouldLogEvent(overwriteValue?: boolean): boolean; + warn(input: LogItemMessage, ...extraInput: LogItemExtraInput): void; }; export { + LogFunction, LoggerInterface, - ClassThatLogs, LogItemMessage, LogItemExtraInput, LambdaFunctionContext, UnformattedAttributes, PowertoolsLogData, ConstructorOptions, - HandlerOptions, + InjectLambdaContextOptions, }; diff --git a/packages/logger/src/types/PowertoolsLog.ts b/packages/logger/src/types/PowertoolsLog.ts deleted file mode 100644 index afa3d820f0..0000000000 --- a/packages/logger/src/types/PowertoolsLog.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { LogAttributes, LogLevel } from './Log.js'; - -type PowertoolsLog = LogAttributes & { - /** - * Timestamp of actual log statement. - * - * @example "2020-05-24 18:17:33,774" - */ - timestamp?: string; - - /** - * Log level - * - * @example "INFO" - */ - level?: LogLevel; - - /** - * Service name defined. - * - * @example "payment" - */ - service: string; - - /** - * The value of the logging sampling rate in percentage. - * - * @example 0.1 - */ - sampling_rate?: number; - - /** - * Log statement value. Unserializable JSON values will be cast to string. - * - * @example "Collecting payment" - */ - message?: string; - - /** - * X-Ray Trace ID set by the Lambda runtime. - * - * @example "1-5759e988-bd862e3fe1be46a994272793" - */ - xray_trace_id?: string; - - /** - * Indicates whether the current execution experienced a cold start. - * - * @example false - */ - cold_start?: boolean; - - /** - * The name of the Lambda function. - * - * @example "example-powertools-HelloWorldFunction-1P1Z6B39FLU73" - */ - lambda_function_name?: string; - - /** - * The memory size of the Lambda function. - * - * Description: - * Example: 128 - */ - lambda_function_memory_size?: number; - - /** - * lambda_function_arn - * - * Description: The ARN of the Lambda function. - * Example: "arn:aws:lambda:eu-west-1:012345678910:function:example-powertools-HelloWorldFunction-1P1Z6B39FLU73" - */ - lambda_function_arn?: string; - - /** - * lambda_request_id - * - * Description: The request ID of the current invocation. - * Example: "899856cb-83d1-40d7-8611-9e78f15f32f4" - */ - lambda_request_id?: string; -}; - -export type { PowertoolsLog }; diff --git a/packages/logger/src/types/index.ts b/packages/logger/src/types/index.ts index 3b5e19d7a9..88f38933d1 100644 --- a/packages/logger/src/types/index.ts +++ b/packages/logger/src/types/index.ts @@ -8,12 +8,11 @@ export type { } from './Log.js'; export type { - ClassThatLogs, LogItemMessage, LogItemExtraInput, LambdaFunctionContext, UnformattedAttributes, PowertoolsLogData, ConstructorOptions, - HandlerOptions, + InjectLambdaContextOptions, } from './Logger.js'; diff --git a/packages/logger/tests/unit/Logger.test.ts b/packages/logger/tests/unit/Logger.test.ts index a983081093..fe91a5ade1 100644 --- a/packages/logger/tests/unit/Logger.test.ts +++ b/packages/logger/tests/unit/Logger.test.ts @@ -11,7 +11,7 @@ import { EnvironmentVariablesService } from '../../src/config/EnvironmentVariabl import { PowertoolsLogFormatter } from '../../src/formatter/PowertoolsLogFormatter.js'; import { LogLevelThresholds, LogLevel } from '../../src/types/Log.js'; import type { - ClassThatLogs, + LogFunction, ConstructorOptions, } from '../../src/types/Logger.js'; import { LogJsonIndent } from '../../src/constants.js'; @@ -21,10 +21,10 @@ const mockDate = new Date(1466424490000); const dateSpy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate); const getConsoleMethod = ( method: string -): keyof Omit => +): keyof Omit => method === 'critical' ? 'error' - : (method.toLowerCase() as keyof Omit); + : (method.toLowerCase() as keyof Omit); jest.mock('node:console', () => ({ ...jest.requireActual('node:console'), Console: jest.fn().mockImplementation(() => ({ @@ -503,7 +503,7 @@ describe('Class: Logger', () => { errorAction, errorPrints ) => { - const methodOfLogger = method as keyof ClassThatLogs; + const methodOfLogger = method as keyof LogFunction; describe('Feature: log level', () => { test(`when the level is DEBUG, it ${debugAction} print to stdout`, () => { From f42e9bd5150d7ba1b888839a61e38e1efd1eb64b Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 20 Oct 2023 23:59:38 +0200 Subject: [PATCH 3/5] chore: fix code smell --- packages/logger/src/formatter/LogItem.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/logger/src/formatter/LogItem.ts b/packages/logger/src/formatter/LogItem.ts index 40435b06e6..7ddacc61f8 100644 --- a/packages/logger/src/formatter/LogItem.ts +++ b/packages/logger/src/formatter/LogItem.ts @@ -12,8 +12,8 @@ class LogItem implements LogItemInterface { this.addAttributes(params.attributes); } - public addAttributes(attributes: LogAttributes): LogItem { - this.attributes = merge(this.attributes, attributes); + public addAttributes(attributes: LogAttributes): this { + merge(this.attributes, attributes); return this; } From 5dc0ad9576c686af47be5083c15246a342e7edb3 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Sat, 21 Oct 2023 00:02:45 +0200 Subject: [PATCH 4/5] chore: fix ci --- package-lock.json | 6 +++--- tsconfig.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index eefa6cdd40..df69291ea2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1801,9 +1801,9 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.13", diff --git a/tsconfig.json b/tsconfig.json index a49b03e30e..c2eb4a63ed 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "incremental": true, "composite": true, - "target": "ES2021", // Node.js 16 + "target": "ES2022", // Node.js 16 "experimentalDecorators": true, "module": "commonjs", "moduleResolution": "node", // TODO: experiment with bundler & esnext From d914346aa2c2625f81b5b5704f31076a44031a9f Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Sat, 21 Oct 2023 00:08:37 +0200 Subject: [PATCH 5/5] chore: fix ci --- 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 812f8ce14f..4b6031e092 100644 --- a/packages/tracer/tests/unit/Tracer.test.ts +++ b/packages/tracer/tests/unit/Tracer.test.ts @@ -20,7 +20,7 @@ type CaptureAsyncFuncMock = jest.SpyInstance< [ name: string, fcn: (subsegment?: Subsegment) => unknown, - parent?: Segment | Subsegment + parent?: Segment | Subsegment, ] >; const createCaptureAsyncFuncMock = function (