diff --git a/examples/cdk/src/example-function.MyFunctionWithMiddy.ts b/examples/cdk/src/example-function.MyFunctionWithMiddy.ts index c2e6f8d444..6b743512aa 100644 --- a/examples/cdk/src/example-function.MyFunctionWithMiddy.ts +++ b/examples/cdk/src/example-function.MyFunctionWithMiddy.ts @@ -62,7 +62,7 @@ const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: C return res; }; -// We instrument the handler with the various Middy middlewares +// We instrument the handler with the various Middy middleware export const handler = middy(lambdaHandler) .use(captureLambdaHandler(tracer)) .use( diff --git a/packages/logger/src/Logger.ts b/packages/logger/src/Logger.ts index 9fa63fb5b4..d9f732262d 100644 --- a/packages/logger/src/Logger.ts +++ b/packages/logger/src/Logger.ts @@ -18,6 +18,92 @@ import type { PowertoolLogData, } from './types'; +/** + * ## Intro + * The Logger utility provides an opinionated logger with output structured as JSON. + * + * ## Key features + * * Capture key fields from Lambda context, cold start and structures logging output as JSON + * * Log Lambda context when instructed (disabled by default) + * * Log sampling prints all logs for a percentage of invocations (disabled by default) + * * Append additional keys to structured log at any point in time + * + * ## Usage + * + * For more usage examples, see [our documentation](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/core/logger/). + * + * ### Basic usage + * + * @example + * ```typescript + * import { Logger } from "@aws-lambda-powertools/logger"; + * + * // Logger parameters fetched from the environment variables: + * const logger = new Logger(); + * ``` + * + * ### Functions usage with manual instrumentation + * + * If you prefer to manually instrument your Lambda handler you can use the methods in the Logger class directly. + * + * @example + * ```typescript + * import { Logger } from "@aws-lambda-powertools/logger"; + * + * const logger = new Logger(); + * + * export const handler = async (_event, context) => { + * logger.addContext(context); + * logger.info("This is an INFO log with some context"); + * }; + * ``` + * + * ### Functions usage with middleware + * + * If you use function-based Lambda handlers you can use the [injectLambdaContext()](#injectLambdaContext) + * middy middleware to automatically add context to your Lambda logs. + * + * @example + * ```typescript + * import { Logger, injectLambdaContext } from "@aws-lambda-powertools/logger"; + * import middy from '@middy/core'; + * + * const logger = new Logger(); + * + * const lambdaHandler = async (_event: any, _context: any) => { + * logger.info("This is an INFO log with some context"); + * }; + * + * export const handler = middy(lambdaHandler).use(injectLambdaContext(logger)); + * ``` + * + * ### Object oriented usage with decorators + * + * If instead you use TypeScript classes to wrap your Lambda handler you can use the [@logger.injectLambdaContext()](./_aws_lambda_powertools_logger.Logger.html#injectLambdaContext) decorator. + * + * @example + * ```typescript + * import { Logger } from "@aws-lambda-powertools/logger"; + * import { LambdaInterface } from '@aws-lambda-powertools/commons'; + * + * const logger = new Logger(); + * + * class Lambda implements LambdaInterface { + * // Decorate your handler class method + * @logger.injectLambdaContext() + * public async handler(_event: any, _context: any): Promise { + * logger.info("This is an INFO log with some context"); + * } + * } + * + * export const myFunction = new Lambda(); + * export const handler = myFunction.handler; + * ``` + * + * @class + * @implements {ClassThatLogs} + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/core/logger/ + */ class Logger implements ClassThatLogs { private static coldStart?: boolean = undefined; @@ -49,10 +135,22 @@ class Logger implements ClassThatLogs { private powertoolLogData: PowertoolLogData = {}; + /** + * It initializes the Logger class with an optional set of options (settings). + * * + * @param {LoggerOptions} options + */ public constructor(options: LoggerOptions = {}) { this.setOptions(options); } + /** + * It adds the current Lambda function's invocation context data to the powertoolLogData property of the instance. + * This context data will be part of all printed log items. + * + * @param {Context} context + * @returns {void} + */ public addContext(context: Context): void { Logger.evaluateColdStartOnce(); const lambdaContext: Partial = { @@ -69,48 +167,120 @@ class Logger implements ClassThatLogs { }); } + /** + * It adds the given attributes (key-value pairs) to all log items generated by this Logger instance. + * + * @param {LogAttributes} attributes + * @returns {void} + */ public addPersistentLogAttributes(attributes?: LogAttributes): void { this.persistentLogAttributes = merge(attributes, this.getPersistentLogAttributes()); } + /** + * Alias for addPersistentLogAttributes. + * + * @param {LogAttributes} attributes + * @returns {void} + */ public appendKeys(attributes?: LogAttributes): void { this.addPersistentLogAttributes(attributes); } + /** + * It creates a separate Logger instance, identical to the current one + * It's possible to overwrite the new instance options by passing them. + * + * @param {LoggerOptions} options + * @returns {Logger} + */ public createChild(options: LoggerOptions = {}): Logger { return cloneDeep(this).setOptions(options); } + /** + * It prints a log item with level DEBUG. + * + * @param {LogItemMessage} input + * @param {Error | LogAttributes | unknown} extraInput + * @returns {void} + */ public debug(input: LogItemMessage, ...extraInput: LogItemExtraInput): void { this.processLogItem('DEBUG', input, extraInput); } + /** + * It prints a log item with level ERROR. + * + * @param {LogItemMessage} input + * @param {Error | LogAttributes | unknown} extraInput + * @returns {void} + */ public error(input: LogItemMessage, ...extraInput: LogItemExtraInput): void { this.processLogItem('ERROR', input, extraInput); } + /** + * It evaluates whether the current Lambda function invocation has a cold start or not. + * + * @static + * @returns {void} + */ public static evaluateColdStartOnce(): void { if (!Logger.getColdStartEvaluatedValue()) { Logger.evaluateColdStart(); } } + /** + * It returns a boolean value which is true if the current Lambda function cold start has been already evaluated, false otherwise. + * + * @static + * @returns {boolean} + */ public static getColdStartEvaluatedValue(): boolean { return Logger.coldStartEvaluated; } + /** + * It returns an optional boolean value, true if the current Lambda function invocation has a cold start, false otherwise. + * + * @static + * @returns {boolean | undefined} + */ public static getColdStartValue(): boolean | undefined { return Logger.coldStart; } + /** + * It returns a boolean value, if true all the logs will be printed. + * + * @returns {boolean} + */ public getLogsSampled(): boolean { return this.logsSampled; } + /** + * It prints a log item with level INFO. + * + * @param {LogItemMessage} input + * @param {Error | LogAttributes | unknown} extraInput + * @returns {void} + */ public info(input: LogItemMessage, ...extraInput: LogItemExtraInput): void { this.processLogItem('INFO', input, extraInput); } + /** + * Method decorator that adds the current Lambda function context as extra + * information in all log items. + * The decorator can be used only when attached to a Lambda function handler which + * is written as method of a class, and should be declared just before the handler declaration. + * + * @see https://www.typescriptlang.org/docs/handbook/decorators.html#method-decorators + * @returns {HandlerMethodDecorator} + */ public injectLambdaContext(): HandlerMethodDecorator { return (target, propertyKey, descriptor) => { const originalMethod = descriptor.value; @@ -123,18 +293,48 @@ class Logger implements ClassThatLogs { }; } + /** + * If the sample rate feature is enabled, the calculation that determines whether the logs + * will actually be printed or not for this invocation is done when the Logger class is + * initialized. + * This method will repeat that calculation (with possible different outcome). + * + * @returns {void} + */ public refreshSampleRateCalculation(): void { this.setLogsSampled(); } + /** + * It sets the value of a flag static propriety that tracks whether + * the cold start evaluation already took place. + * + * @param {boolean} value + * @static + * @returns {void} + */ public static setColdStartEvaluatedValue(value: boolean): void { Logger.coldStartEvaluated = value; } + /** + * It sets the value of a flag static propriety that tracks whether + * the current Lambda invocation experienced a cold start. + * + * @static + * @param {boolean | undefined} value + * @returns {void} + */ public static setColdStartValue(value: boolean | undefined): void { Logger.coldStart = value; } + /** + * It sets the user-provided sample rate value. + * + * @param {number} [sampleRateValue] + * @returns {void} + */ public setSampleRateValue(sampleRateValue?: number): void { this.powertoolLogData.sampleRateValue = sampleRateValue || @@ -142,17 +342,43 @@ class Logger implements ClassThatLogs { this.getEnvVarsService().getSampleRateValue(); } + /** + * It prints a log item with level WARN. + * + * @param {LogItemMessage} input + * @param {Error | LogAttributes | unknown} extraInput + * @returns {void} + */ public warn(input: LogItemMessage, ...extraInput: LogItemExtraInput): void { this.processLogItem('WARN', input, extraInput); } + /** + * It stores information that is printed in all log items. + * + * @param {Partial} attributesArray + * @private + * @returns {void} + */ private addToPowertoolLogData(...attributesArray: Array>): void { attributesArray.forEach((attributes: Partial) => { this.powertoolLogData = merge(attributes, this.getPowertoolLogData()); }); } + /** + * It processes a particular log item so that it can be printed to stdout: + * - Merges ephemeral log attributes with persistent log attributes (printed for all logs) and additional info; + * - Formats all the log attributes; + * + * @private + * @param {LogLevel} logLevel + * @param {LogItemMessage} input + * @param {LogItemExtraInput} extraInput + * @returns {LogItem} + */ private createAndPopulateLogItem(logLevel: LogLevel, input: LogItemMessage, extraInput: LogItemExtraInput): LogItem { + // TODO: this method's logic is hard to understand, there is an opportunity here to simplify this logic. const unformattedBaseAttributes = merge({ logLevel, timestamp: new Date(), @@ -176,6 +402,14 @@ class Logger implements ClassThatLogs { return logItem; } + /** + * It evaluates whether the current Lambda invocation experienced a + * cold start. + * + * @private + * @static + * @returns {void} + */ private static evaluateColdStart(): void { const coldStartValue = Logger.getColdStartValue(); if (typeof coldStartValue === 'undefined') { @@ -189,30 +423,75 @@ class Logger implements ClassThatLogs { Logger.setColdStartEvaluatedValue(true); } + /** + * It returns the custom config service, an abstraction used to fetch environment variables. + * + * @private + * @returns {ConfigServiceInterface | undefined} + */ private getCustomConfigService(): ConfigServiceInterface | undefined { return this.customConfigService; } + /** + * It returns the instance of a service that fetches environment variables. + * + * @private + * @returns {EnvironmentVariablesService} + */ private getEnvVarsService(): EnvironmentVariablesService { return this.envVarsService; } + /** + * It returns the instance of a service that formats the structure of a + * log item's keys and values in the desired way. + * + * @private + * @returns {LogFormatterInterface} + */ private getLogFormatter(): LogFormatterInterface { return this.logFormatter; } + /** + * It returns the log level set for the Logger instance. + * + * @private + * @returns {LogLevel} + */ private getLogLevel(): LogLevel { return this.logLevel; } + /** + * It returns the persistent log attributes, which are the attributes + * that will be logged in all log items. + * + * @private + * @returns {LogAttributes} + */ private getPersistentLogAttributes(): LogAttributes { return this.persistentLogAttributes; } + /** + * It returns information that will be added in all log item by + * this Logger instance (different from user-provided persistent attributes). + * + * @private + * @returns {LogAttributes} + */ private getPowertoolLogData(): PowertoolLogData { return this.powertoolLogData; } + /** + * It returns the numeric sample rate value. + * + * @private + * @returns {number} + */ private getSampleRateValue(): number { if (!this.powertoolLogData?.sampleRateValue) { this.setSampleRateValue(); @@ -221,10 +500,24 @@ class Logger implements ClassThatLogs { return this.powertoolLogData?.sampleRateValue; } + /** + * It returns true if the provided log level is valid. + * + * @param {LogLevel} logLevel + * @private + * @returns {boolean} + */ private isValidLogLevel(logLevel?: LogLevel): boolean { return typeof logLevel === 'string' && logLevel.toUpperCase() in this.logLevelThresholds; } + /** + * It prints a given log with given log level. + * + * @param {LogLevel} logLevel + * @param {LogItem} log + * @private + */ private printLog(logLevel: LogLevel, log: LogItem): void { log.prepareForPrint(); @@ -233,6 +526,13 @@ class Logger implements ClassThatLogs { console[consoleMethod](JSON.stringify(log.getAttributes(), this.removeCircularDependencies())); } + /** + * It prints a given log with given log level. + * + * @param {LogLevel} logLevel + * @param {LogItem} log + * @private + */ private processLogItem(logLevel: LogLevel, input: LogItemMessage, extraInput: LogItemExtraInput): void { if (!this.shouldPrint(logLevel)) { return; @@ -241,9 +541,9 @@ class Logger implements ClassThatLogs { } /** - * When the data added in the log item when contains object references, - * JSON.stringify() doesn't try to solve them and throws an error: TypeError: cyclic object value. - * To mitigate this issue, this function will find and remove the cyclic references. + * When the data added in the log item contains object references, + * JSON.stringify() doesn't try to solve them and instead throws an error: TypeError: cyclic object value. + * To mitigate this issue, this method will find and remove all cyclic references. * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value * @private @@ -267,18 +567,49 @@ class Logger implements ClassThatLogs { }; } + /** + * Sets the Logger's customer config service instance, which will be used + * to fetch environment variables. + * + * @private + * @param {ConfigServiceInterface} customConfigService + * @returns {void} + */ private setCustomConfigService(customConfigService?: ConfigServiceInterface): void { this.customConfigService = customConfigService ? customConfigService : undefined; } + /** + * Sets the Logger's custom config service instance, which will be used + * to fetch environment variables. + * + * @private + * @param {ConfigServiceInterface} customConfigService + * @returns {void} + */ private setEnvVarsService(): void { this.envVarsService = new EnvironmentVariablesService(); } + /** + * It sets the log formatter instance, in charge of giving a custom format + * to the structured logs + * + * @private + * @param {LogFormatterInterface} logFormatter + * @returns {void} + */ private setLogFormatter(logFormatter?: LogFormatterInterface): void { this.logFormatter = logFormatter || new PowertoolLogFormatter(); } + /** + * It sets the Logger's instance log level. + * + * @private + * @param {LogLevel} logLevel + * @returns {void} + */ private setLogLevel(logLevel?: LogLevel): void { if (this.isValidLogLevel(logLevel)) { this.logLevel = (logLevel).toUpperCase(); @@ -301,12 +632,27 @@ class Logger implements ClassThatLogs { this.logLevel = Logger.defaultLogLevel; } + /** + * If the sample rate feature is enabled, it sets a property that tracks whether this Lambda function invocation + * will print logs or not. + * + * @private + * @returns {void} + */ private setLogsSampled(): void { const sampleRateValue = this.getSampleRateValue(); // TODO: revisit Math.random() as it's not a real randomization this.logsSampled = sampleRateValue !== undefined && (sampleRateValue === 1 || Math.random() < sampleRateValue); } + /** + * It configures the Logger instance settings that will affect the Logger's behaviour + * and the content of all logs. + * + * @private + * @param {LoggerOptions} options + * @returns {Logger} + */ private setOptions(options: LoggerOptions): Logger { const { logLevel, @@ -331,6 +677,15 @@ class Logger implements ClassThatLogs { return this; } + /** + * It adds important data to the Logger instance that will affect the content of all logs. + * + * @param {string} serviceName + * @param {Environment} environment + * @param {LogAttributes} persistentLogAttributes + * @private + * @returns {void} + */ private setPowertoolLogData( serviceName?: string, environment?: Environment, @@ -352,6 +707,15 @@ class Logger implements ClassThatLogs { ); } + /** + * It checks whether the current log item should/can be printed. + * + * @param {string} serviceName + * @param {Environment} environment + * @param {LogAttributes} persistentLogAttributes + * @private + * @returns {boolean} + */ private shouldPrint(logLevel: LogLevel): boolean { if (this.logLevelThresholds[logLevel] >= this.logLevelThresholds[this.getLogLevel()]) { return true; diff --git a/packages/logger/src/config/ConfigService.ts b/packages/logger/src/config/ConfigService.ts index 31663bc56c..4f38cf6ae6 100644 --- a/packages/logger/src/config/ConfigService.ts +++ b/packages/logger/src/config/ConfigService.ts @@ -1,21 +1,62 @@ import { ConfigServiceInterface } from '.'; +/** + * Abstract class ConfigService + * + * This class defines common methods and variables that can be set by the developer + * in the runtime. + * + * @class + * @abstract + * @implements {ConfigServiceInterface} + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + */ abstract class ConfigService implements ConfigServiceInterface { - // Custom environment variables + /** + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + * @protected + */ protected currentEnvironmentVariable = 'ENVIRONMENT'; protected logLevelVariable = 'LOG_LEVEL'; protected sampleRateValueVariable = 'POWERTOOLS_LOGGER_SAMPLE_RATE'; protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; + /** + * It returns the value of an environment variable that has given name. + * + * @param {string} name + * @returns {string} + */ public abstract get(name: string): string; + /** + * It returns the value of the ENVIRONMENT environment variable. + * + * @returns {string} + */ public abstract getCurrentEnvironment(): string; + /** + * It returns the value of the LOG_LEVEL environment variable. + * + * @returns {string} + */ public abstract getLogLevel(): string; + /** + * It returns the value of the POWERTOOLS_LOGGER_SAMPLE_RATE environment variable. + * + * @returns {string|undefined} + */ public abstract getSampleRateValue(): number | undefined; + /** + * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. + * + * @returns {string} + */ public abstract getServiceName(): string; } diff --git a/packages/logger/src/config/ConfigServiceInterface.ts b/packages/logger/src/config/ConfigServiceInterface.ts index 3659acea66..0e9b62a409 100644 --- a/packages/logger/src/config/ConfigServiceInterface.ts +++ b/packages/logger/src/config/ConfigServiceInterface.ts @@ -1,13 +1,46 @@ +/** + * Interface ConfigServiceInterface + * + * @interface + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + */ interface ConfigServiceInterface { + /** + * It returns the value of an environment variable that has given name. + * + * @param {string} name + * @returns {string} + */ get(name: string): string + /** + * It returns the value of the ENVIRONMENT environment variable. + * + * @returns {string} + */ getCurrentEnvironment(): string + /** + * It returns the value of the LOG_LEVEL environment variable. + * + * @returns {string} + */ getLogLevel(): string + /** + * It returns the value of the POWERTOOLS_LOGGER_SAMPLE_RATE environment variable. + * + * @returns {string|undefined} + */ getSampleRateValue(): number | undefined + /** + * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. + * + * @returns {string} + */ getServiceName(): string } diff --git a/packages/logger/src/config/EnvironmentVariablesService.ts b/packages/logger/src/config/EnvironmentVariablesService.ts index 6553e93166..588af64a01 100644 --- a/packages/logger/src/config/EnvironmentVariablesService.ts +++ b/packages/logger/src/config/EnvironmentVariablesService.ts @@ -1,5 +1,18 @@ import { ConfigService } from '.'; +/** + * Class EnvironmentVariablesService + * + * This class is used to return environment variables that are available in the runtime of + * the current Lambda invocation. + * These variables can be a mix of runtime environment variables set by AWS and + * variables that can be set by the developer additionally. + * + * @class + * @extends {ConfigService} + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + */ class EnvironmentVariablesService extends ConfigService { // Reserved environment variables @@ -9,46 +22,97 @@ class EnvironmentVariablesService extends ConfigService { private memoryLimitInMBVariable = 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE'; private xRayTraceIdVariable = '_X_AMZN_TRACE_ID'; + /** + * It returns the value of an environment variable that has given name. + * + * @param {string} name + * @returns {string} + */ public get(name: string): string { return process.env[name]?.trim() || ''; } + /** + * It returns the value of the AWS_REGION environment variable. + * + * @returns {string} + */ public getAwsRegion(): string { return this.get(this.awsRegionVariable); } + /** + * It returns the value of the ENVIRONMENT environment variable. + * + * @returns {string} + */ public getCurrentEnvironment(): string { return this.get(this.currentEnvironmentVariable); } + /** + * It returns the value of the AWS_LAMBDA_FUNCTION_MEMORY_SIZE environment variable. + * + * @returns {string} + */ public getFunctionMemory(): number { const value = this.get(this.memoryLimitInMBVariable); return Number(value); } + /** + * It returns the value of the AWS_LAMBDA_FUNCTION_NAME environment variable. + * + * @returns {string} + */ public getFunctionName(): string { return this.get(this.functionNameVariable); } + /** + * It returns the value of the AWS_LAMBDA_FUNCTION_VERSION environment variable. + * + * @returns {string} + */ public getFunctionVersion(): string { return this.get(this.functionVersionVariable); } + /** + * It returns the value of the LOG_LEVEL environment variable. + * + * @returns {string} + */ public getLogLevel(): string { return this.get(this.logLevelVariable); } + /** + * It returns the value of the POWERTOOLS_LOGGER_SAMPLE_RATE environment variable. + * + * @returns {string|undefined} + */ public getSampleRateValue(): number | undefined { const value = this.get(this.sampleRateValueVariable); return (value && value.length > 0) ? Number(value) : undefined; } + /** + * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. + * + * @returns {string} + */ public getServiceName(): string { return this.get(this.serviceNameVariable); } + /** + * It returns the value of the _X_AMZN_TRACE_ID environment variable. + * + * @returns {string} + */ public getXrayTraceId(): string { return this.get(this.xRayTraceIdVariable); } diff --git a/packages/logger/src/formatter/LogFormatter.ts b/packages/logger/src/formatter/LogFormatter.ts index 594e50cb7d..29b47f99fd 100644 --- a/packages/logger/src/formatter/LogFormatter.ts +++ b/packages/logger/src/formatter/LogFormatter.ts @@ -1,10 +1,29 @@ import { LogFormatterInterface } from '.'; import { LogAttributes, UnformattedAttributes } from '../types'; +/** + * This class defines and implements common methods for the formatting of log attributes. + * + * @class + * @abstract + * @implements {LogFormatterInterface} + */ abstract class LogFormatter implements LogFormatterInterface { + /** + * It formats key-value pairs of log attributes. + * + * @param {UnformattedAttributes} attributes + * @returns {LogAttributes} + */ public abstract formatAttributes(attributes: UnformattedAttributes): LogAttributes; + /** + * It formats a given Error parameter. + * + * @param {Error} error + * @returns {LogAttributes} + */ public formatError(error: Error): LogAttributes { return { name: error.name, @@ -14,10 +33,22 @@ abstract class LogFormatter implements LogFormatterInterface { }; } + /** + * It formats a date into a string in simplified extended ISO format (ISO 8601). + * + * @param {Date} now + * @returns {string} + */ public formatTimestamp(now: Date): string { return now.toISOString(); } + /** + * It returns a string containing the location of an error, given a particular stack trace. + * + * @param stack + * @returns {string} + */ public getCodeLocation(stack?: string): string { if (!stack) { return ''; diff --git a/packages/logger/src/formatter/LogFormatterInterface.ts b/packages/logger/src/formatter/LogFormatterInterface.ts index 04e3b69e3f..1139443c28 100644 --- a/packages/logger/src/formatter/LogFormatterInterface.ts +++ b/packages/logger/src/formatter/LogFormatterInterface.ts @@ -1,9 +1,24 @@ import { LogAttributes, UnformattedAttributes } from '../types'; +/** + * @interface + */ interface LogFormatterInterface { + /** + * It formats key-value pairs of log attributes. + * + * @param {UnformattedAttributes} attributes + * @returns {PowertoolLog} + */ formatAttributes(attributes: UnformattedAttributes): LogAttributes + /** + * It formats a given Error parameter. + * + * @param {Error} error + * @returns {LogAttributes} + */ formatError(error: Error): LogAttributes } diff --git a/packages/logger/src/formatter/PowertoolLogFormatter.ts b/packages/logger/src/formatter/PowertoolLogFormatter.ts index f29e1b5dd8..c4bd7bc34b 100644 --- a/packages/logger/src/formatter/PowertoolLogFormatter.ts +++ b/packages/logger/src/formatter/PowertoolLogFormatter.ts @@ -2,8 +2,21 @@ import { LogFormatter } from '.'; import { UnformattedAttributes } from '../types'; import { PowertoolLog } from '../types/formats'; +/** + * This class is used to transform a set of log key-value pairs + * in the AWS Lambda Powertools' default structure log format. + * + * @class + * @extends {LogFormatter} + */ class PowertoolLogFormatter extends LogFormatter { + /** + * It formats key-value pairs of log attributes. + * + * @param {UnformattedAttributes} attributes + * @returns {PowertoolLog} + */ public formatAttributes(attributes: UnformattedAttributes): PowertoolLog { return { cold_start: attributes.lambdaContext?.coldStart, diff --git a/packages/logger/src/middleware/middy.ts b/packages/logger/src/middleware/middy.ts index e06b19e156..d0353962a3 100644 --- a/packages/logger/src/middleware/middy.ts +++ b/packages/logger/src/middleware/middy.ts @@ -1,6 +1,31 @@ import type { Logger } from '../Logger'; import middy from '@middy/core'; +/** + * A middy middleware that adds the current Lambda invocation's context inside all log items. + * + * ## Usage + * + * @example + * ```typescript + * import { Logger, injectLambdaContext } from "@aws-lambda-powertools/logger"; + * + * import middy from '@middy/core'; + * + * + * const logger = new Logger(); + * + * const lambdaHandler = async (_event: any, _context: any) => { + * logger.info("This is an INFO log with some context"); + * }; + * + * + * export const handler = middy(lambdaHandler).use(injectLambdaContext(logger)); + * ``` + * + * @param {Logger|Logger[]} target - The Tracer instance to use for tracing + * @returns {middy.MiddlewareObj} - The middy middleware object + */ const injectLambdaContext = (target: Logger | Logger[]): middy.MiddlewareObj => { const injectLambdaContextBefore = async (request: middy.Request): Promise => { const loggers = target instanceof Array ? target : [target]; diff --git a/packages/tracing/src/Tracer.ts b/packages/tracing/src/Tracer.ts index 12e9669aed..8ac49de38e 100644 --- a/packages/tracing/src/Tracer.ts +++ b/packages/tracing/src/Tracer.ts @@ -21,7 +21,7 @@ import { Segment, Subsegment } from 'aws-xray-sdk-core'; * * For more usage examples, see [our documentation](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/core/tracer/). * - * ### Functions usage with middlewares + * ### Functions usage with middleware * * If you use function-based Lambda handlers you can use the [captureLambdaHandler()](./_aws_lambda_powertools_tracer.Tracer.html) middy middleware to automatically: * * handle the subsegment lifecycle diff --git a/packages/tracing/tests/unit/middy.test.ts b/packages/tracing/tests/unit/middy.test.ts index 0bf588c522..5829ba25cd 100644 --- a/packages/tracing/tests/unit/middy.test.ts +++ b/packages/tracing/tests/unit/middy.test.ts @@ -14,7 +14,7 @@ jest.spyOn(console, 'debug').mockImplementation(() => null); jest.spyOn(console, 'warn').mockImplementation(() => null); jest.spyOn(console, 'error').mockImplementation(() => null); -describe('Middy middlewares', () => { +describe('Middy middleware', () => { const ENVIRONMENT_VARIABLES = process.env; const context = { callbackWaitsForEmptyEventLoop: true,