From 1e17d071ac1d308a97d520c97ecd56d755d309bc Mon Sep 17 00:00:00 2001 From: Florian CHAZAL Date: Thu, 30 Dec 2021 17:40:44 +0100 Subject: [PATCH 01/24] chore(test): test --- test | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test diff --git a/test b/test new file mode 100644 index 0000000000..e69de29bb2 From 62d6c9ea01d4188b72fbcbb4db32034e4aae8552 Mon Sep 17 00:00:00 2001 From: Florian CHAZAL Date: Mon, 3 Jan 2022 09:03:05 +0100 Subject: [PATCH 02/24] docs(metrics): remove serializeMetrics and fix cloudwatch excerpt --- docs/core/metrics.md | 73 +++++++++++++++++++++++--------------------- test | 0 2 files changed, 39 insertions(+), 34 deletions(-) delete mode 100644 test diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 9a9f906311..3ca93a0d6e 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -106,6 +106,7 @@ You can create metrics using `addMetric`, and you can create dimensions for all export const handler = async (event: any, context: Context) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.purgeStoredMetrics(); } ``` === "Metrics with custom dimensions" @@ -120,6 +121,7 @@ You can create metrics using `addMetric`, and you can create dimensions for all export const handler = async (event: any, context: Context) => { metrics.addDimension('environment', 'prod'); metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.purgeStoredMetrics(); } ``` @@ -242,21 +244,22 @@ If you do not the middleware or decorator, you have to flush your metrics manual See below an example of how to automatically flush metrics with the Middy-compatible `logMetrics` middleware. +=== "handler.ts" -```typescript hl_lines="3 8 11-12" - import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; - import middy from '@middy/core'; + ```typescript hl_lines="3 8 11-12" + import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; + import { Context } from 'aws-lambda'; + import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'exampleApplication' , service: 'exampleService' }); + const metrics = new Metrics({ namespace: 'exampleApplication' , service: 'exampleService' }); - const lambdaHandler = async (event: any, context: Context) => { - metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); - } + const lambdaHandler = async (event: any, context: Context) => { + metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); + } - export const handler = middy(lambdaHandler) - .use(logMetrics(metrics)); -``` + export const handler = middy(lambdaHandler) + .use(logMetrics(metrics)); + ``` === "Example CloudWatch Logs excerpt" @@ -295,20 +298,22 @@ See below an example of how to automatically flush metrics with the Middy-compat The `logMetrics` decorator of the metrics utility can be used when your Lambda handler function is implemented as method of a Class. -```typescript hl_lines="8" -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; -import { Context, Callback } from 'aws-lambda'; +=== "handler.ts" -const metrics = new Metrics({namespace:"exampleApplication", service:"exampleService"}); + ```typescript hl_lines="8" + import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; + import { Context, Callback } from 'aws-lambda'; -export class MyFunction { + const metrics = new Metrics({namespace:"exampleApplication", service:"exampleService"}); - @metrics.logMetrics() - public handler(_event: TEvent, _context: Context, _callback: Callback): void | Promise { - metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); + export class MyFunction { + + @metrics.logMetrics() + public handler(_event: TEvent, _context: Context, _callback: Callback): void | Promise { + metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); + } } -} -``` + ``` === "Example CloudWatch Logs excerpt" @@ -353,9 +358,7 @@ const metrics = new Metrics(); const lambdaHandler: Handler = async () => { metrics.addMetric('test-metric', MetricUnits.Count, 10); - const metricsObject = metrics.serializeMetrics(); metrics.purgeStoredMetrics(); - console.log(JSON.stringify(metricsObject)); }; ``` @@ -435,20 +438,22 @@ You can add high-cardinality data as part of your Metrics log with `addMetadata` !!! warning **This will not be available during metrics visualization** - Use **dimensions** for this purpose -```typescript hl_lines="8" - import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; - import middy from '@middy/core'; +=== "handler.ts" - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + ```typescript hl_lines="8" + import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; + import { Context } from 'aws-lambda'; + import middy from '@middy/core'; - const lambdaHandler = async (event: any, context: Context) => { - metrics.addMetadata('bookingId', '7051cd10-6283-11ec-90d6-0242ac120003'); - } + const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); - export const handler = middy(lambdaHandler) - .use(logMetrics(metrics)); -``` + const lambdaHandler = async (event: any, context: Context) => { + metrics.addMetadata('bookingId', '7051cd10-6283-11ec-90d6-0242ac120003'); + } + + export const handler = middy(lambdaHandler) + .use(logMetrics(metrics)); + ``` === "Example CloudWatch Logs excerpt" diff --git a/test b/test deleted file mode 100644 index e69de29bb2..0000000000 From b1bc7f9673e9609a4f12d62591daf50ed999dcd7 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 3 Jan 2022 10:41:45 +0100 Subject: [PATCH 03/24] fix: tracer construct initializer --- docs/core/tracer.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 6c02b8d363..5d8d45e367 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -82,8 +82,8 @@ You can quickly start by importing the `Tracer` class, initialize it outside the import { Tracer } from '@aws-lambda-powertools/tracer'; import middy from '@middy/core'; - const tracer = Tracer(); // Sets service via env var - // OR tracer = Tracer({ service: 'example' }); + const tracer = new Tracer(); // Sets service via env var + // OR tracer = new Tracer({ service: 'example' }); export const handler = middy(async (_event: any, _context: any) => { ... @@ -95,8 +95,8 @@ You can quickly start by importing the `Tracer` class, initialize it outside the ```typescript hl_lines="1 3 7" import { Tracer } from '@aws-lambda-powertools/tracer'; - const tracer = Tracer(); // Sets service via env var - // OR tracer = Tracer({ service: 'example' }); + const tracer = new Tracer(); // Sets service via env var + // OR tracer = new Tracer({ service: 'example' }); class Lambda { @tracer.captureLambdaHandler() @@ -114,8 +114,8 @@ You can quickly start by importing the `Tracer` class, initialize it outside the ```typescript hl_lines="1 3 7 9-10 13-14 20 23 27 29" import { Tracer } from '@aws-lambda-powertools/tracer'; - const tracer = Tracer(); // Sets service via env var - // OR tracer = Tracer({ service: 'serverlessAirline' }); + const tracer = new Tracer(); // Sets service via env var + // OR tracer = new Tracer({ service: 'serverlessAirline' }); export const handler = async (_event: any, context: any) => { const segment = tracer.getSegment(); // This is the facade segment (the one that is created by AWS Lambda) @@ -198,7 +198,7 @@ You can trace other methods using the `captureMethod` decorator or manual instru ```typescript hl_lines="6" import { Tracer } from '@aws-lambda-powertools/tracer'; - const tracer = Tracer(); + const tracer = new Tracer(); class Lambda { @tracer.captureMethod() From c63fdd66a53a88e712683d65a2aec67956f3f3f0 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 3 Jan 2022 19:12:32 +0100 Subject: [PATCH 04/24] Conformed tracer & logger --- docs/core/logger.md | 99 ++++++++++---------- docs/core/tracer.md | 217 +++++++++++++++++++++++--------------------- 2 files changed, 168 insertions(+), 148 deletions(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 39dd62e694..312c77ba07 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -59,7 +59,7 @@ For a **complete list** of supported environment variables, refer to [this secti // You can also pass the parameters in the constructor // const logger = new Logger({ // logLevel: "WARN", - // serviceName: "shopping-cart-api" + // serviceName: "serverlessAirline" // }); ``` @@ -74,7 +74,7 @@ For a **complete list** of supported environment variables, refer to [this secti Environment: Variables: LOG_LEVEL: WARN - POWERTOOLS_SERVICE_NAME: shopping-cart-api + POWERTOOLS_SERVICE_NAME: serverlessAirline ``` ### Standard structured keys @@ -105,7 +105,23 @@ Key | Example **function_arn**: `string` | `arn:aws:lambda:eu-central-1:123456789012:function:shopping-cart-api-lambda-prod-eu-central-1` **function_request_id**: `string` | `c6af9ac6-7b61-11e6-9a41-93e812345678` -=== "Middleware" +=== "Manual" + + ```typescript hl_lines="7" + 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"); + + }; + ``` + +=== "Middy Middleware" !!! note Middy comes bundled with Logger, so you can just import it when using the middleware. @@ -119,30 +135,14 @@ Key | Example const logger = new Logger(); - const lambdaHandler = async () => { + const lambdaHandler = async (_event: any, _context: any) => { logger.info("This is an INFO log with some context"); }; - const handler = middy(lambdaHandler) + export const handler = middy(lambdaHandler) .use(injectLambdaContext(logger)); ``` -=== "Manual" - - ```typescript hl_lines="7" - import { Logger } from "@aws-lambda-powertools/logger"; - - const logger = new Logger(); - - const lambdaHandler = async (_event, context) => { - - logger.addContext(context); - - logger.info("This is an INFO log with some context"); - - }; - ``` - === "Decorator" ```typescript hl_lines="7" @@ -151,13 +151,16 @@ Key | Example const logger = new Logger(); class Lambda { - + // Decorate your handler class method @logger.injectLambdaContext() - public handler() { + public handler(_event: any, _context: any) { logger.info("This is an INFO log with some context"); } } + + export const handlerClass = new Lambda(); + export const handler = handlerClass.handler; ``` In each case, the printed log will look like this: @@ -173,7 +176,7 @@ In each case, the printed log will look like this: "function_name": "shopping-cart-api-lambda-prod-eu-central-1", "level": "INFO", "message": "This is an INFO log with some context", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T21:21:08.921Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -213,7 +216,7 @@ You can append additional persistent keys and values in the logs generated durin // } // }); - const lambdaHandler: Handler = async () => { + export const handler = async (_event: any, _context: any) => { // This info log will print all extra custom attributes added above // Extra attributes: logger object with name and version of the logger library, awsAccountId, awsRegion @@ -232,7 +235,7 @@ You can append additional persistent keys and values in the logs generated durin { "level": "INFO", "message": "This is an INFO log", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T21:49:58.084Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456", "aws_account_id": "123456789012", @@ -245,7 +248,7 @@ You can append additional persistent keys and values in the logs generated durin { "level": "INFO", "message": "This is another INFO log", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T21:49:58.088Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456", "aws_account_id": "123456789012", @@ -271,7 +274,7 @@ You can append additional keys and values in a single log item passing them as p const logger = new Logger(); - const lambdaHandler = async () => { + export const handler = async (_event: any, _context: any) => { const myImportantVariable = { foo: "bar" @@ -300,7 +303,7 @@ You can append additional keys and values in a single log item passing them as p { "level": "INFO", "message": "This is a log with an extra variable", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:06:17.463Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456", "data": { foo: "bar" } @@ -308,7 +311,7 @@ You can append additional keys and values in a single log item passing them as p { "level": "INFO", "message": "This is a log with 2 extra variables", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:06:17.466Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456", "data": { "foo": "bar" }, @@ -328,7 +331,7 @@ The error will be logged with default key name `error`, but you can also pass yo const logger = new Logger(); - const lambdaHandler = async () => { + export const handler = async (_event: any, _context: any) => { try { throw new Error("Unexpected error #1"); @@ -353,7 +356,7 @@ The error will be logged with default key name `error`, but you can also pass yo { "level": "ERROR", "message": "This is an ERROR log #1", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:12:39.345Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456", "error": { @@ -366,7 +369,7 @@ The error will be logged with default key name `error`, but you can also pass yo { "level": "ERROR", "message": "This is an ERROR log #2", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:12:39.377Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456", "myCustomErrorKey": { @@ -400,7 +403,7 @@ This can be useful for example if you want to enable multiple Loggers with diffe logLevel: "ERROR" }); - const lambdaHandler: Handler = async () => { + export const handler = async (_event: any, _context: any) => { logger.info("This is an INFO log, from the parent logger"); logger.error("This is an ERROR log, from the parent logger"); @@ -417,21 +420,21 @@ This can be useful for example if you want to enable multiple Loggers with diffe { "level": "INFO", "message": "This is an INFO log, from the parent logger", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:32:54.667Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } { "level": "ERROR", "message": "This is an ERROR log, from the parent logger", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:32:54.670Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } { "level": "ERROR", "message": "This is an ERROR log, from the child logger", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:32:54.670Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -464,7 +467,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i sampleRateValue: 0.5 }); - const lambdaHandler = async () => { + export const handler = async (_event: any, _context: any) => { // 0.5 means that you have 50% chance that these logs will be printed logger.info("This is INFO log #1"); @@ -485,7 +488,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "INFO", "message": "This is INFO log #1", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.334Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -493,7 +496,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "INFO", "message": "This is INFO log #2", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.337Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -501,7 +504,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "INFO", "message": "This is INFO log #3", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.338Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -509,7 +512,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "INFO", "message": "This is INFO log #4", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.338Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -528,7 +531,7 @@ You can customize the structure (keys and values) of your log items by passing a const logger = new Logger({ logFormatter: new MyCompanyLogFormatter(), logLevel: "DEBUG", - serviceName: "shopping-cart-api", + serviceName: "serverlessAirline", sampleRateValue: 0.5, persistentLogAttributes: { awsAccountId: process.env.AWS_ACCOUNT_ID, @@ -539,11 +542,13 @@ You can customize the structure (keys and values) of your log items by passing a }, }); - const lambdaHandler: Handler = async (event, context) => { + export const handler = async (event, _context) => { + logger.addContext(context); logger.info("This is an INFO log", { correlationIds: { myCustomCorrelationId: "foo-bar-baz" } }); - }; + +}; ``` This is how the `MyCompanyLogFormatter` (dummy name) would look like: @@ -598,7 +603,7 @@ This is how the printed log would look: ```json { "message": "This is an INFO log", - "service": "shopping-cart-api", + "service": "serverlessAirline", "awsRegion": "eu-central-1", "correlationIds": { "awsRequestId": "c6af9ac6-7b61-11e6-9a41-93e812345678", @@ -654,7 +659,7 @@ describe('MyUnitTest', () => { test('Lambda invoked successfully', async () => { - const testEvent = { test: 'test' }; + const testEvent = { test: 'test' }; await handler(testEvent, dummyContext); }); diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 5d8d45e367..31804e2f72 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -35,22 +35,34 @@ npm install @aws-lambda-powertools/tracer ### Utility settings -The library requires one setting. You can set it as environment variables, or pass it in the constructor. +The library has one optional setting. You can set it as environment variable, or pass it in the constructor. -These settings will be used across all traces emitted: +This setting will be used across all traces emitted: Setting | Description | Environment variable | Constructor parameter ------------------------------------------------- |------------------------------------------------------------------------------------------------| ------------------------------------------------- | ------------------------------------------------- -**Service name** | Sets an annotation with the **name of the service** across all traces e.g. `shopping-cart-api` | `POWERTOOLS_SERVICE_NAME` | `serviceName` +**Service name** | Sets an annotation with the **name of the service** across all traces e.g. `serverlessAirline` | `POWERTOOLS_SERVICE_NAME` | `serviceName` For a **complete list** of supported environment variables, refer to [this section](./../index.md#environment-variables). +!!! note + Before your use this utility, your AWS Lambda function [must have permissions](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html#services-xray-permissions) to send traces to AWS X-Ray. -### Permissions +#### Example using AWS Serverless Application Model (SAM) -Before your use this utility, your AWS Lambda function [must have permissions](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html#services-xray-permissions) to send traces to AWS X-Ray. +=== "handler.ts" -> Example using AWS Serverless Application Model (SAM) + ```typescript hl_lines="1 4" + import { Tracer } from "@aws-lambda-powertools/tracer"; + + // Tracer parameter fetched from the environment variables (see template.yaml tab) + const tracer = new Tracer(); + + // You can also pass the parameter in the constructor + // const tracer = new Tracer({ + // serviceName: "serverlessAirline" + // }); + ``` === "template.yml" @@ -63,59 +75,19 @@ Before your use this utility, your AWS Lambda function [must have permissions](h Tracing: Active Environment: Variables: - POWERTOOLS_SERVICE_NAME: example + POWERTOOLS_SERVICE_NAME: serverlessAirline ``` ### Lambda handler You can quickly start by importing the `Tracer` class, initialize it outside the Lambda handler, and instrument your function. -=== "Middleware" - - !!! note - Middy comes bundled with Tracer, so you can just import it when using the middleware. - - !!! tip "Using Middy for the first time?" - Learn more about [its usage and lifecycle in the official Middy documentation](https://github.com/middyjs/middy#usage){target="_blank"}. - - ```typescript hl_lines="1-2 4 7 9" - import { Tracer } from '@aws-lambda-powertools/tracer'; - import middy from '@middy/core'; - - const tracer = new Tracer(); // Sets service via env var - // OR tracer = new Tracer({ service: 'example' }); - - export const handler = middy(async (_event: any, _context: any) => { - ... - }).use(captureLambdaHandler(tracer)); - ``` - -=== "Decorator" - - ```typescript hl_lines="1 3 7" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer(); // Sets service via env var - // OR tracer = new Tracer({ service: 'example' }); - - class Lambda { - @tracer.captureLambdaHandler() - public handler(event: any, context: any) { - ... - } - } - - export const handlerClass = new Lambda(); - export const handler = handlerClass.handler; - ``` - === "Manual" - ```typescript hl_lines="1 3 7 9-10 13-14 20 23 27 29" + ```typescript hl_lines="6 8-9 12-13 19 22 26 28" import { Tracer } from '@aws-lambda-powertools/tracer'; - const tracer = new Tracer(); // Sets service via env var - // OR tracer = new Tracer({ service: 'serverlessAirline' }); + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); export const handler = async (_event: any, context: any) => { const segment = tracer.getSegment(); // This is the facade segment (the one that is created by AWS Lambda) @@ -129,7 +101,7 @@ You can quickly start by importing the `Tracer` class, initialize it outside the let res; try { - res = ... + /* ... */ // Add the response as metadata tracer.addResponseAsMetadata(res, process.env._HANDLER); } catch (err) { @@ -139,7 +111,7 @@ You can quickly start by importing the `Tracer` class, initialize it outside the } finally { // Close subsegment (the AWS Lambda one is closed automatically) subsegment.close(); - // Set the facade segment as active again + // Set back the facade segment as active again tracer.setSegment(segment); } @@ -147,12 +119,55 @@ You can quickly start by importing the `Tracer` class, initialize it outside the } ``` +=== "Middy Middleware" + + !!! note + Middy comes bundled with Tracer, so you can just import it when using the middleware. + + !!! tip "Using Middy for the first time?" + Learn more about [its usage and lifecycle in the official Middy documentation](https://github.com/middyjs/middy#usage){target="_blank"}. + + ```typescript hl_lines="1-2 11 13" + import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; + import middy from '@middy/core'; + + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + + const lambdaHandler = async (_event: any, _context: any) => { + /* ... */ + } + + // Wrap the handler with middy + export const handler = middy(lambdaHandler) + // Use the middleware by passing the Tracer instance as a parameter + .use(captureLambdaHandler(tracer)); + ``` + +=== "Decorator" + + ```typescript hl_lines="7" + import { Tracer } from '@aws-lambda-powertools/tracer'; + + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + + class Lambda { + // Decorate your handler class method + @tracer.captureLambdaHandler() + public handler(event: any, context: any) { + /* ... */ + } + } + + export const handlerClass = new Lambda(); + export const handler = handlerClass.handler; + ``` + When using the `captureLambdaHandler` decorator or middleware, Tracer performs these additional tasks to ease operations: * Handles the lifecycle of the subsegment * Creates a `ColdStart` annotation to easily filter traces that have had an initialization overhead -* Creates a `ServiceName` annotation to easily filter traces that have a specific service name -* Captures any response, or full exceptions generated by the handler, and include as tracing metadata +* Creates a `Service` annotation to easily filter traces that have a specific service name +* Captures any response, or full exceptions generated by the handler, and include them as tracing metadata ### Annotations & Metadata @@ -181,7 +196,7 @@ When using the `captureLambdaHandler` decorator or middleware, Tracer performs t const tracer = new Tracer({ serviceName: 'serverlessAirline' }); export const handler = async (_event: any, _context: any) => { - const res = someLogic(); + const res; /* ... */ tracer.putMetadata('paymentResponse', res); } ``` @@ -190,38 +205,9 @@ When using the `captureLambdaHandler` decorator or middleware, Tracer performs t You can trace other methods using the `captureMethod` decorator or manual instrumentation. -!!! info - We currently support a middleware for tracing methods, [let us know](https://github.com/awslabs/aws-lambda-powertools-typescript/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=) if you'd like to see one! - -=== "Decorator" - - ```typescript hl_lines="6" - import { Tracer } from '@aws-lambda-powertools/tracer'; - - const tracer = new Tracer(); - - class Lambda { - @tracer.captureMethod() - public getChargeId(): string { - ... - return 'foo bar' - } - - public handler(event: any, context: any) { - const chargeId = this.getChargeId(); - const payment = collectPayment(chargeId); - ... - } - } - - export const handlerClass = new Lambda(); - export const getChargeId = handlerClass.getChargeId; - export const handler = handlerClass.handler; - ``` - === "Manual" - ```typescript hl_lines="6 8-9 15 23 25" + ```typescript hl_lines="6 8-9 15 18 23 25" import { Tracer } from '@aws-lambda-powertools/tracer'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); @@ -234,7 +220,7 @@ You can trace other methods using the `captureMethod` decorator or manual instru let res; try { - res = await someLogic(); // Do something + /* ... */ // Add the response as metadata tracer.addResponseAsMetadata(res, 'chargeId'); } catch (err) { @@ -254,41 +240,69 @@ You can trace other methods using the `captureMethod` decorator or manual instru export const handler = async (_event: any, _context: any) => { const chargeId = this.getChargeId(); const payment = collectPayment(chargeId); - ... + /* ... */ + } + ``` + +=== "Middy Middleware" + + !!! info + We currently support a middleware for tracing methods, [let us know](https://github.com/awslabs/aws-lambda-powertools-typescript/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=) if you'd like to see one! + +=== "Decorator" + + ```typescript hl_lines="7" + import { Tracer } from '@aws-lambda-powertools/tracer'; + + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + + class Lambda { + // Decorate your class method + @tracer.captureMethod() + public getChargeId(): string { + /* ... */ + return 'foo bar'; + } + + public handler(event: any, context: any) { + /* ... */ + } } + + export const handlerClass = new Lambda(); + export const handler = handlerClass.handler; ``` ### Patching AWS SDK clients -Tracer can patch [AWS SDK clients](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-awssdkclients.html) and create traces when your application makes calls to AWS services. +Tracer can patch any [AWS SDK clients](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-awssdkclients.html) and create traces when your application makes calls to AWS services. !!! info - The following snippet assumes you are using [**AWS SDK v3** for JavaScript](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/) + The following snippet assumes you are using the [**AWS SDK v3** for JavaScript](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/) -You can patch any AWS SDK clients by calling `captureAWSv3Client` method: +You can patch any AWS SDK clients by calling the `captureAWSv3Client` method: === "index.ts" - ```typescript hl_lines="6" + ```typescript hl_lines="5" import { S3Client } from "@aws-sdk/client-s3"; import { Tracer } from '@aws-lambda-powertools/tracer'; - const tracer = new Tracer(); - const client = new S3Client({}); - tracer.captureAWSv3Client(client); + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + const client = tracer.captureAWSv3Client(new S3Client({})); ``` !!! info - The following two snippets assume you are using [**AWS SDK v2** for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/welcome.html) + The following two snippets assume you are using the [**AWS SDK v2** for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/welcome.html) -You can patch all AWS SDK clients by calling `captureAWS` method: +You can patch all AWS SDK clients by calling the `captureAWS` method: === "index.ts" ```typescript hl_lines="4" import { Tracer } from '@aws-lambda-powertools/tracer'; - const tracer = new Tracer(); + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); const AWS = tracer.captureAWS(require('aws-sdk')); ``` @@ -300,8 +314,8 @@ If you're looking to shave a few microseconds, or milliseconds depending on your import { S3 } from "aws-sdk"; import { Tracer } from '@aws-lambda-powertools/tracer'; - const tracer = new Tracer(); - const s3 = tracer.captureAWSClient(new S3({ apiVersion: "2006-03-01" })); + const tracer = new Tracer({ serviceName: 'serverlessAirline' }); + const s3 = tracer.captureAWSClient(new S3()); ``` ## Advanced @@ -336,9 +350,10 @@ This is useful when you need a feature available in X-Ray that is not available import { Logger } from '@aws-lambda-powertools/logger'; import { Tracer } from '@aws-lambda-powertools/tracer'; - const logger = new Logger(); - const tracer = new Tracer() - tracer.provider.setLogger(logger) + const serviceName = 'serverlessAirline'; + const logger = new Logger({ serviceName: serviceName }); + const tracer = new Tracer({ serviceName: serviceName }); + tracer.provider.setLogger(logger); ``` ## Testing your code From a93e905cab02327f7cfc179c9bc29f2d412e47aa Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:02:20 +0100 Subject: [PATCH 05/24] Added changes from #376 --- docs/core/metrics.md | 276 +++++++++++++++++++++++-------------------- docs/core/tracer.md | 22 ++-- 2 files changed, 164 insertions(+), 134 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 3ca93a0d6e..a57e848096 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -58,23 +58,27 @@ Setting | Description | Environment variable | Constructor parameter For a **complete list** of supported environment variables, refer to [this section](./../index.md#environment-variables). -!!! tip "Use your application or main service as the metric namespace to easily group all metrics" +!!! tip + Use your application name or main service as the metric namespace to easily group all metrics -> Example using AWS Serverless Application Model (SAM) +#### Example using AWS Serverless Application Model (SAM) -=== "index.ts" +=== "handler.ts" - ```typescript hl_lines="5 7" + ```typescript hl_lines="1 4" import { Metrics } from '@aws-lambda-powertools/metrics'; - - // Sets metric namespace and service via env var + // Metrics parameters fetched from the environment variables (see template.yaml tab) const metrics = new Metrics(); - // OR Sets metric namespace, and service as a metrics parameters - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + + // You can also pass the parameters in the constructor + // const metrics = new Metrics({ + // namespace: 'serverlessAirline', + // service: 'orders' + // }); ``` -=== "sam-template.yml" +=== "template.yml" ```yaml hl_lines="9 10" Resources: @@ -84,41 +88,37 @@ For a **complete list** of supported environment variables, refer to [this secti Runtime: nodejs14.x Environment: Variables: - POWERTOOLS_SERVICE_NAME: payment + POWERTOOLS_SERVICE_NAME: orders POWERTOOLS_METRICS_NAMESPACE: serverlessAirline ``` - You can initialize Metrics anywhere in your code - It'll keep track of your aggregate metrics in memory. ### Creating metrics -You can create metrics using `addMetric`, and you can create dimensions for all your aggregate metrics using `addDimension` method. +You can create metrics using the `addMetric` method, and you can create dimensions for all your aggregate metrics using the `addDimension` method. === "Metrics" - ```typescript hl_lines="8" + ```typescript hl_lines="6" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; - - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - export const handler = async (event: any, context: Context) => { + export const handler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); metrics.purgeStoredMetrics(); } ``` + === "Metrics with custom dimensions" - ```typescript hl_lines="8-9" + ```typescript hl_lines="6-7" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; - - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - export const handler = async (event: any, context: Context) => { + export const handler = async (_event: any, _context: any) => { metrics.addDimension('environment', 'prod'); metrics.addMetric('successfulBooking', MetricUnits.Count, 1); metrics.purgeStoredMetrics(); @@ -126,39 +126,35 @@ You can create metrics using `addMetric`, and you can create dimensions for all ``` !!! tip "Autocomplete Metric Units" - `MetricUnit` enum facilitate finding a supported metric unit by CloudWatch. Alternatively, you can pass the value as a string if you already know them e.g. "Count". + Use the `MetricUnit` enum to easily find a supported metric unit by CloudWatch. Alternatively, you can pass the value as a string if you already know them e.g. "Count". !!! note "Metrics overflow" - CloudWatch EMF supports a max of 100 metrics per batch. Metrics utility will flush all metrics when adding the 100th metric. Subsequent metrics, e.g. 101th, will be aggregated into a new EMF object, for your convenience. + CloudWatch EMF supports a max of 100 metrics per batch. Metrics will automatically propagate all the metrics when adding the 100th metric. Subsequent metrics, e.g. 101th, will be aggregated into a new EMF object, for your convenience. !!! warning "Do not create metrics or dimensions outside the handler" Metrics or dimensions added in the global scope will only be added during cold start. Disregard if that's the intended behaviour. ### Adding default dimensions -You can use add default dimensions to your metrics by passing them as parameters in 4 ways: +You can add default dimensions to your metrics by passing them as parameters in 4 ways: * in the constructor -* in the Middy middleware +* in the [Middy-compatible](https://github.com/middyjs/middy){target=_blank} middleware * using the `setDefaultDimensions` method * in the decorator -If you'd like to remove them at some point, you can use `clearDefaultDimensions` method. -See examples below: - === "constructor" - ```typescript hl_lines="7" + ```typescript hl_lines="6" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; const metrics = new Metrics({ - namespace:"serverlessAirline", - service:"orders", - defaultDimensions: { 'environment': 'prod', 'anotherDimension': 'whatever' } + namespace: 'serverlessAirline', + service: 'orders', + defaultDimensions: { 'environment': 'prod', 'foo': 'bar' } }); - export const handler = async (event: any, context: Context) => { + export const handler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } ``` @@ -171,31 +167,31 @@ See examples below: !!! tip "Using Middy for the first time?" Learn more about [its usage and lifecycle in the official Middy documentation](https://github.com/middyjs/middy#usage){target="_blank"}. - ```typescript hl_lines="5" + ```typescript hl_lines="1-2 11 13" import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; import middy from '@middy/core'; const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - const lambdaHandler = async (event: any, context: Context) => { + const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } + // Wrap the handler with middy export const handler = middy(lambdaHandler) - .use(logMetrics(metrics, { defaultDimensions:{ 'environment': 'prod', 'anotherDimension': 'whatever' } })); + // Use the middleware by passing the Metrics instance as a parameter + .use(logMetrics(metrics, { defaultDimensions:{ 'environment': 'prod', 'foo': 'bar' } })); ``` === "setDefaultDimensions method" - ```typescript hl_lines="5" + ```typescript hl_lines="4" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); - metrics.setDefaultDimensions({ 'environment': 'prod', 'anotherDimension': 'whatever' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + metrics.setDefaultDimensions({ 'environment': 'prod', 'foo': 'bar' }); - export const handler = async (event: any, context: Context) => { + export const handler = async (event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } ``` @@ -204,32 +200,34 @@ See examples below: ```typescript hl_lines="9" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context, Callback } from 'aws-lambda'; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); - const DEFAULT_DIMENSIONS = {"environment": "prod", "another": "one"}; - - export class MyFunction { + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const DEFAULT_DIMENSIONS = { 'environment': 'prod', 'foo': 'bar' }; + export class MyFunction extends LambdaInterface { + // Decorate your handler class method @metrics.logMetrics({defaultDimensions: DEFAULT_DIMENSIONS}) - public handler(_event: TEvent, _context: Context, _callback: Callback): void | Promise { + public handler(_event: any, _context: any): Promise { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } } ``` +If you'd like to remove them at some point, you can use the `clearDefaultDimensions` method. + ### Flushing metrics -As you finish adding all your metrics, you need to serialize and "flush them" (= print them to standard output). +As you finish adding all your metrics, you need to serialize and "flush them" by calling `purgeStoredMetrics()`. This will print the metrics to standard output. You can flush metrics automatically using one of the following methods: +* manually * [Middy-compatible](https://github.com/middyjs/middy){target=_blank} middleware * class decorator -* manually Using the Middy middleware or decorator will **automatically validate, serialize, and flush** all your metrics. During metrics validation, if no metrics are provided then a warning will be logged, but no exception will be raised. -If you do not the middleware or decorator, you have to flush your metrics manually. +If you do not use the middleware or decorator, you have to flush your metrics manually. !!! warning "Metric validation" @@ -239,38 +237,84 @@ If you do not the middleware or decorator, you have to flush your metrics manual * Namespace is set only once (or none) * Metric units must be [supported by CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html) +#### Manually + +You can manually flush the metrics with `purgeStoredMetrics` as follows: + +!!! warning + Metrics, dimensions and namespace validation still applies. + +=== "handler.ts" -#### Using Middy middleware + ```typescript hl_lines="7" + import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; + + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + + export const handler = async (_event: any, _context: any) => { + metrics.addMetric('successfulBooking', MetricUnits.Count, 10); + metrics.purgeStoredMetrics(); + }; + ``` + +=== "Example CloudWatch Logs excerpt" + + ```json hl_lines="2 7 10 15 22" + { + "successfulBooking": 1.0, + "_aws": { + "Timestamp": 1592234975665, + "CloudWatchMetrics": [ + { + "Namespace": "successfulBooking", + "Dimensions": [ + [ + "service" + ] + ], + "Metrics": [ + { + "Name": "successfulBooking", + "Unit": "Count" + } + ] + } + ] + }, + "service": "orders" + } + ``` + +#### Middy middleware See below an example of how to automatically flush metrics with the Middy-compatible `logMetrics` middleware. === "handler.ts" - ```typescript hl_lines="3 8 11-12" - import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; - import middy from '@middy/core'; + ```typescript hl_lines="1-2 7 10-11" + import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; + import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'exampleApplication' , service: 'exampleService' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - const lambdaHandler = async (event: any, context: Context) => { - metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); - } + const lambdaHandler = async (_event: any, _context: any) => { + metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + } - export const handler = middy(lambdaHandler) - .use(logMetrics(metrics)); + export const handler = middy(lambdaHandler) + .use(logMetrics(metrics)); ``` === "Example CloudWatch Logs excerpt" ```json hl_lines="2 7 10 15 22" { - "bookingConfirmation": 1.0, + "successfulBooking": 1.0, "_aws": { "Timestamp": 1592234975665, "CloudWatchMetrics": [ { - "Namespace": "exampleApplication", + "Namespace": "serverlessAirline", "Dimensions": [ [ "service" @@ -278,14 +322,14 @@ See below an example of how to automatically flush metrics with the Middy-compat ], "Metrics": [ { - "Name": "bookingConfirmation", + "Name": "successfulBooking", "Unit": "Count" } ] } ] }, - "service": "exampleService" + "service": "orders" } ``` @@ -302,15 +346,15 @@ The `logMetrics` decorator of the metrics utility can be used when your Lambda h ```typescript hl_lines="8" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context, Callback } from 'aws-lambda'; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; - const metrics = new Metrics({namespace:"exampleApplication", service:"exampleService"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - export class MyFunction { + export class MyFunction extends LambdaInterface { @metrics.logMetrics() - public handler(_event: TEvent, _context: Context, _callback: Callback): void | Promise { - metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); + public async handler(_event: any, _context: any): Promise { + metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } } ``` @@ -319,12 +363,12 @@ The `logMetrics` decorator of the metrics utility can be used when your Lambda h ```json hl_lines="2 7 10 15 22" { - "bookingConfirmation": 1.0, + "successfulBooking": 1.0, "_aws": { "Timestamp": 1592234975665, "CloudWatchMetrics": [ { - "Namespace": "exampleApplication", + "Namespace": "successfulBooking", "Dimensions": [ [ "service" @@ -332,49 +376,29 @@ The `logMetrics` decorator of the metrics utility can be used when your Lambda h ], "Metrics": [ { - "Name": "bookingConfirmation", + "Name": "successfulBooking", "Unit": "Count" } ] } ] }, - "service": "exampleService" + "service": "orders" } ``` - -#### Manually - -You can manually flush the metrics with `purgeStoredMetrics` as follows: - -!!! warning - Metrics, dimensions and namespace validation still applies. - -```typescript hl_lines="8" -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - -const metrics = new Metrics(); - -const lambdaHandler: Handler = async () => { - metrics.addMetric('test-metric', MetricUnits.Count, 10); - metrics.purgeStoredMetrics(); -}; -``` - #### Throwing a RangeError when no metrics are emitted If you want to ensure that at least one metric is emitted before you flush them, you can use the `raiseOnEmptyMetrics` parameter and pass it to the middleware or decorator: -```typescript hl_lines="12" +```typescript hl_lines="11" import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; import middy from '@middy/core'; - const metrics = new Metrics({namespace:"exampleApplication", service:"exampleService"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - const lambdaHandler = async (event: any, context: Context) => { - metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); + const lambdaHandler = async (_event: any, _context: any) => { + metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } export const handler = middy(lambdaHandler) @@ -387,14 +411,13 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o === "logMetrics middleware" - ```typescript hl_lines="12" + ```typescript hl_lines="11" import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; import middy from '@middy/core'; - const metrics = new Metrics({namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - const lambdaHandler = async (event: any, context: Context) => { + const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } @@ -406,15 +429,14 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o ```typescript hl_lines="9" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context, Callback } from 'aws-lambda'; - import middy from '@middy/core'; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; const metrics = new Metrics({namespace: 'serverlessAirline', service: 'orders' }); - export class MyFunction { + export class MyFunction extends LambdaInterface { @metrics.logMetrics({ captureColdStartMetric: true }) - public handler(_event: TEvent, _context: Context, _callback: Callback): void | Promise { + public async handler(_event: any, _context: any): Promise { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } } @@ -423,7 +445,7 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o If it's a cold start invocation, this feature will: * Create a separate EMF blob solely containing a metric named `ColdStart` -* Add `function_name`, `service` and default dimensions +* Add the `function_name`, `service` and default dimensions This has the advantage of keeping cold start metric separate from your application metrics, where you might have unrelated dimensions. @@ -433,7 +455,7 @@ This has the advantage of keeping cold start metric separate from your applicati ### Adding metadata -You can add high-cardinality data as part of your Metrics log with `addMetadata` method. This is useful when you want to search highly contextual information along with your metrics in your logs. +You can add high-cardinality data as part of your Metrics log with the `addMetadata` method. This is useful when you want to search highly contextual information along with your metrics in your logs. !!! warning **This will not be available during metrics visualization** - Use **dimensions** for this purpose @@ -442,12 +464,12 @@ You can add high-cardinality data as part of your Metrics log with `addMetadata` ```typescript hl_lines="8" import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; import middy from '@middy/core'; - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - const lambdaHandler = async (event: any, context: Context) => { + const lambdaHandler = async (_event: any, _context: any) => { + metrics.addMetric('successfulBooking', MetricUnits.Count, 1); metrics.addMetadata('bookingId', '7051cd10-6283-11ec-90d6-0242ac120003'); } @@ -464,7 +486,7 @@ You can add high-cardinality data as part of your Metrics log with `addMetadata` "Timestamp": 1592234975665, "CloudWatchMetrics": [ { - "Namespace": "exampleApplication", + "Namespace": "serverlessAirline", "Dimensions": [ [ "service" @@ -479,7 +501,7 @@ You can add high-cardinality data as part of your Metrics log with `addMetadata` } ] }, - "service": "booking", + "service": "orders", "bookingId": "7051cd10-6283-11ec-90d6-0242ac120003" } ``` @@ -496,14 +518,13 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr === "logMetrics middleware" - ```typescript hl_lines="12 14 15" + ```typescript hl_lines="11 13-14" import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; - import { Context } from 'aws-lambda'; import middy from '@middy/core'; - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - const lambdaHandler = async (event: any, context: Context) => { + const lambdaHandler = async (_event: any, _context: any) => { metrics.addDimension('metricUnit', 'milliseconds'); // This metric will have the "metricUnit" dimension, and no "metricType" dimension: metrics.addMetric('latency', MetricUnits.Milliseconds, 56); @@ -515,21 +536,21 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr } export const handler = middy(lambdaHandler) - .use(logMetrics(metrics, { captureColdStartMetric: true } })); + .use(logMetrics(metrics)); ``` === "logMetrics decorator" - ```typescript hl_lines="14 16 17" + ```typescript hl_lines="14 16-17" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - import { Context, Callback } from 'aws-lambda'; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - export class MyFunction { + class Lambda extends LambdaInterface { @metrics.logMetrics() - public handler(_event: TEvent, _context: Context, _callback: Callback): void | Promise { + public async handler(_event: any, _context: any): Promise { metrics.addDimension('metricUnit', 'milliseconds'); // This metric will have the "metricUnit" dimension, and no "metricType" dimension: metrics.addMetric('latency', MetricUnits.Milliseconds, 56); @@ -540,4 +561,7 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr singleMetric.addMetric('orderSubmitted', MetricUnits.Count, 1); } } + + export const myFunction = new Lambda(); + export const handler = myFunction.handler; ``` diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 31804e2f72..2a8521a793 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -145,15 +145,20 @@ You can quickly start by importing the `Tracer` class, initialize it outside the === "Decorator" - ```typescript hl_lines="7" + !!! info + Decorators can only be attached to a class declaration, method, accessor, property, or parameter. Therefore, if you prefer to write your handler as a standard function rather than a Class method, use the middleware or the manual instrumentations instead. + See the [official TypeScript documentation](https://www.typescriptlang.org/docs/handbook/decorators.html) for more details. + + ```typescript hl_lines="8" import { Tracer } from '@aws-lambda-powertools/tracer'; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - class Lambda { + class Lambda extends LambdaInterface { // Decorate your handler class method @tracer.captureLambdaHandler() - public handler(event: any, context: any) { + public handler(_event: any, _context: any) { /* ... */ } } @@ -251,12 +256,13 @@ You can trace other methods using the `captureMethod` decorator or manual instru === "Decorator" - ```typescript hl_lines="7" + ```typescript hl_lines="8" import { Tracer } from '@aws-lambda-powertools/tracer'; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - class Lambda { + class Lambda extends LambdaInterface { // Decorate your class method @tracer.captureMethod() public getChargeId(): string { @@ -264,13 +270,13 @@ You can trace other methods using the `captureMethod` decorator or manual instru return 'foo bar'; } - public handler(event: any, context: any) { + public async handler(_event: any, _context: any): Promise { /* ... */ } } - export const handlerClass = new Lambda(); - export const handler = handlerClass.handler; + export const myFunction = new Lambda(); + export const handler = myFunction.handler; ``` ### Patching AWS SDK clients From 8d7a93ee85617cb54846c4afe1a8a9ea45c30276 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:08:54 +0100 Subject: [PATCH 06/24] Added lambdaInterface to logger examples --- docs/core/logger.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 19fbf1d5fc..0383c0d589 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -145,22 +145,23 @@ Key | Example === "Decorator" - ```typescript hl_lines="7" + ```typescript hl_lines="8" import { Logger } from "@aws-lambda-powertools/logger"; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; const logger = new Logger(); - class Lambda { + class Lambda extends LambdaInterface { // Decorate your handler class method @logger.injectLambdaContext() - public handler(_event: any, _context: any) { + public async handler(_event: any, _context: any): Promise { logger.info("This is an INFO log with some context"); } } - export const handlerClass = new Lambda(); - export const handler = handlerClass.handler; + export const myFunction = new Lambda(); + export const handler = myFunction.handler; ``` In each case, the printed log will look like this: From 479820fc7b573660ad7eb7df3ca77e9bf9c84c5a Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:50:06 +0100 Subject: [PATCH 07/24] docs: update docs/core/logger.md Co-authored-by: Sara Gerion <47529391+saragerion@users.noreply.github.com> --- docs/core/logger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 0383c0d589..3963c81909 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -154,7 +154,7 @@ Key | Example class Lambda extends LambdaInterface { // Decorate your handler class method @logger.injectLambdaContext() - public async handler(_event: any, _context: any): Promise { + public async handler(_event: any, _context: any): Promise { logger.info("This is an INFO log with some context"); } From 6b473bdd3da902dba613caf90af41af97afd46e9 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:51:56 +0100 Subject: [PATCH 08/24] docs: updated return type for all async handlers --- docs/core/metrics.md | 8 ++++---- docs/core/tracer.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 6f3898a83d..0b69a3c20e 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -256,7 +256,7 @@ You can add default dimensions to your metrics by passing them as parameters in export class MyFunction extends LambdaInterface { // Decorate your handler class method @metrics.logMetrics({defaultDimensions: DEFAULT_DIMENSIONS}) - public handler(_event: any, _context: any): Promise { + public handler(_event: any, _context: any): Promise { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } } @@ -399,7 +399,7 @@ The `logMetrics` decorator of the metrics utility can be used when your Lambda h export class MyFunction extends LambdaInterface { @metrics.logMetrics() - public async handler(_event: any, _context: any): Promise { + public async handler(_event: any, _context: any): Promise { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } } @@ -480,7 +480,7 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o export class MyFunction extends LambdaInterface { @metrics.logMetrics({ captureColdStartMetric: true }) - public async handler(_event: any, _context: any): Promise { + public async handler(_event: any, _context: any): Promise { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } } @@ -602,7 +602,7 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr class Lambda extends LambdaInterface { @metrics.logMetrics() - public async handler(_event: any, _context: any): Promise { + public async handler(_event: any, _context: any): Promise { metrics.addDimension('metricUnit', 'milliseconds'); // This metric will have the "metricUnit" dimension, and no "metricType" dimension: metrics.addMetric('latency', MetricUnits.Milliseconds, 56); diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 2a8521a793..bd79b766d3 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -158,7 +158,7 @@ You can quickly start by importing the `Tracer` class, initialize it outside the class Lambda extends LambdaInterface { // Decorate your handler class method @tracer.captureLambdaHandler() - public handler(_event: any, _context: any) { + public async handler(_event: any, _context: any): Promise { /* ... */ } } @@ -270,7 +270,7 @@ You can trace other methods using the `captureMethod` decorator or manual instru return 'foo bar'; } - public async handler(_event: any, _context: any): Promise { + public async handler(_event: any, _context: any): Promise { /* ... */ } } From 1714eb62d0a4e1374d040659eef0b2f50d11de54 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:53:12 +0100 Subject: [PATCH 09/24] docs: update docs/core/metrics.md Co-authored-by: Sara Gerion <47529391+saragerion@users.noreply.github.com> --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 0b69a3c20e..382b3de26b 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -266,7 +266,7 @@ If you'd like to remove them at some point, you can use the `clearDefaultDimensi ### Flushing metrics -As you finish adding all your metrics, you need to serialize and "flush them" by calling `purgeStoredMetrics()`. This will print the metrics to standard output. +As you finish adding all your metrics, you need to serialize and "flush them" by calling `publishStoredMetrics()`. This will print the metrics to standard output. You can flush metrics automatically using one of the following methods: From f07c5456df9269497b55c717f754e49274dafc58 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:53:28 +0100 Subject: [PATCH 10/24] docs: update docs/core/metrics.md Co-authored-by: Sara Gerion <47529391+saragerion@users.noreply.github.com> --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 382b3de26b..bab3188b0e 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -287,7 +287,7 @@ If you do not use the middleware or decorator, you have to flush your metrics ma #### Manually -You can manually flush the metrics with `purgeStoredMetrics` as follows: +You can manually flush the metrics with `publishStoredMetrics` as follows: !!! warning Metrics, dimensions and namespace validation still applies. From d0d0c29f1082d7ba61fbcf15223d0ddb4ce4cf38 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:53:47 +0100 Subject: [PATCH 11/24] docs: update docs/core/metrics.md Co-authored-by: Sara Gerion <47529391+saragerion@users.noreply.github.com> --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index bab3188b0e..41a6e92f6a 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -301,7 +301,7 @@ You can manually flush the metrics with `publishStoredMetrics` as follows: export const handler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 10); - metrics.purgeStoredMetrics(); + metrics.publishStoredMetrics(); }; ``` From 482b6d8a8099fcb8533ac1dba6c9450de4e7f289 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 18:54:38 +0100 Subject: [PATCH 12/24] docs: updated all references to publishStoredMetrics --- docs/core/metrics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 41a6e92f6a..c2e2646ed3 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -107,7 +107,7 @@ You can create metrics using the `addMetric` method, and you can create dimensio export const handler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); - metrics.purgeStoredMetrics(); + metrics.publishStoredMetrics(); } ``` @@ -121,7 +121,7 @@ You can create metrics using the `addMetric` method, and you can create dimensio export const handler = async (_event: any, _context: any) => { metrics.addDimension('environment', 'prod'); metrics.addMetric('successfulBooking', MetricUnits.Count, 1); - metrics.purgeStoredMetrics(); + metrics.publishStoredMetrics(); } ``` From ac7587af47872a57da5818872e1163c6cf911800 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 19:06:31 +0100 Subject: [PATCH 13/24] docs: replaced extends w/ implements keyword in classes --- docs/core/logger.md | 6 +++--- docs/core/metrics.md | 8 ++++---- docs/core/tracer.md | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 3963c81909..8862aa4bc9 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -151,7 +151,7 @@ Key | Example const logger = new Logger(); - class Lambda extends LambdaInterface { + class Lambda implements LambdaInterface { // Decorate your handler class method @logger.injectLambdaContext() public async handler(_event: any, _context: any): Promise { @@ -589,7 +589,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i ### Custom Log formatter (Bring Your Own Formatter) -You can customize the structure (keys and values) of your log items by passing a custom log formatter, an object that extends the `LogFormatter` abstract class. +You can customize the structure (keys and values) of your log items by passing a custom log formatter, an object that implements the `LogFormatter` abstract class. === "handler.ts" @@ -631,7 +631,7 @@ This is how the `MyCompanyLogFormatter` (dummy name) would look like: // Replace this line with your own type type MyCompanyLog = LogAttributes; - class MyCompanyLogFormatter extends LogFormatter { + class MyCompanyLogFormatter implements LogFormatter { public formatAttributes(attributes: UnformattedAttributes): MyCompanyLog { return { diff --git a/docs/core/metrics.md b/docs/core/metrics.md index c2e2646ed3..f9885bd24d 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -253,7 +253,7 @@ You can add default dimensions to your metrics by passing them as parameters in const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); const DEFAULT_DIMENSIONS = { 'environment': 'prod', 'foo': 'bar' }; - export class MyFunction extends LambdaInterface { + export class MyFunction implements LambdaInterface { // Decorate your handler class method @metrics.logMetrics({defaultDimensions: DEFAULT_DIMENSIONS}) public handler(_event: any, _context: any): Promise { @@ -396,7 +396,7 @@ The `logMetrics` decorator of the metrics utility can be used when your Lambda h const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - export class MyFunction extends LambdaInterface { + export class MyFunction implements LambdaInterface { @metrics.logMetrics() public async handler(_event: any, _context: any): Promise { @@ -477,7 +477,7 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o const metrics = new Metrics({namespace: 'serverlessAirline', service: 'orders' }); - export class MyFunction extends LambdaInterface { + export class MyFunction implements LambdaInterface { @metrics.logMetrics({ captureColdStartMetric: true }) public async handler(_event: any, _context: any): Promise { @@ -599,7 +599,7 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); - class Lambda extends LambdaInterface { + class Lambda implements LambdaInterface { @metrics.logMetrics() public async handler(_event: any, _context: any): Promise { diff --git a/docs/core/tracer.md b/docs/core/tracer.md index bd79b766d3..b8f0de773a 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -155,7 +155,7 @@ You can quickly start by importing the `Tracer` class, initialize it outside the const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - class Lambda extends LambdaInterface { + class Lambda implements LambdaInterface { // Decorate your handler class method @tracer.captureLambdaHandler() public async handler(_event: any, _context: any): Promise { @@ -262,7 +262,7 @@ You can trace other methods using the `captureMethod` decorator or manual instru const tracer = new Tracer({ serviceName: 'serverlessAirline' }); - class Lambda extends LambdaInterface { + class Lambda implements LambdaInterface { // Decorate your class method @tracer.captureMethod() public getChargeId(): string { From 2539fbb3ac12bcebae13c2578a3663d0954c4f49 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 22:59:14 +0100 Subject: [PATCH 14/24] docs: switched to serviceName according to #401 --- docs/core/metrics.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index f9885bd24d..312bea82f6 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -74,7 +74,7 @@ For a **complete list** of supported environment variables, refer to [this secti // You can also pass the parameters in the constructor // const metrics = new Metrics({ // namespace: 'serverlessAirline', - // service: 'orders' + // serviceName: 'orders' // }); ``` @@ -103,7 +103,7 @@ You can create metrics using the `addMetric` method, and you can create dimensio ```typescript hl_lines="6" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); export const handler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); @@ -116,7 +116,7 @@ You can create metrics using the `addMetric` method, and you can create dimensio ```typescript hl_lines="6-7" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); export const handler = async (_event: any, _context: any) => { metrics.addDimension('environment', 'prod'); @@ -144,7 +144,7 @@ You can call `addMetric()` with the same name multiple times. The values will be import { Context } from 'aws-lambda'; - const metrics = new Metrics({namespace:"serverlessAirline", service:"orders"}); + const metrics = new Metrics({namespace:"serverlessAirline", serviceName:"orders"}); export const handler = async (event: any, context: Context) => { metrics.addMetric('performedActionA', MetricUnits.Count, 2); @@ -198,7 +198,7 @@ You can add default dimensions to your metrics by passing them as parameters in const metrics = new Metrics({ namespace: 'serverlessAirline', - service: 'orders', + serviceName: 'orders', defaultDimensions: { 'environment': 'prod', 'foo': 'bar' } }); @@ -219,7 +219,7 @@ You can add default dimensions to your metrics by passing them as parameters in import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); @@ -236,7 +236,7 @@ You can add default dimensions to your metrics by passing them as parameters in ```typescript hl_lines="4" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); metrics.setDefaultDimensions({ 'environment': 'prod', 'foo': 'bar' }); export const handler = async (event: any, _context: any) => { @@ -250,7 +250,7 @@ You can add default dimensions to your metrics by passing them as parameters in import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; import { LambdaInterface } from '@aws-lambda-powertools/commons'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); const DEFAULT_DIMENSIONS = { 'environment': 'prod', 'foo': 'bar' }; export class MyFunction implements LambdaInterface { @@ -297,7 +297,7 @@ You can manually flush the metrics with `publishStoredMetrics` as follows: ```typescript hl_lines="7" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); export const handler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 10); @@ -343,7 +343,7 @@ See below an example of how to automatically flush metrics with the Middy-compat import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); @@ -394,7 +394,7 @@ The `logMetrics` decorator of the metrics utility can be used when your Lambda h import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; import { LambdaInterface } from '@aws-lambda-powertools/commons'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); export class MyFunction implements LambdaInterface { @@ -439,7 +439,7 @@ If you want to ensure that at least one metric is emitted before you flush them, import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); @@ -459,7 +459,7 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); @@ -475,7 +475,7 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; import { LambdaInterface } from '@aws-lambda-powertools/commons'; - const metrics = new Metrics({namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({namespace: 'serverlessAirline', serviceName: 'orders' }); export class MyFunction implements LambdaInterface { @@ -510,7 +510,7 @@ You can add high-cardinality data as part of your Metrics log with the `addMetad import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); @@ -574,7 +574,7 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; import middy from '@middy/core'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); const lambdaHandler = async (_event: any, _context: any) => { metrics.addDimension('metricUnit', 'milliseconds'); @@ -597,7 +597,7 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; import { LambdaInterface } from '@aws-lambda-powertools/commons'; - const metrics = new Metrics({ namespace: 'serverlessAirline', service: 'orders' }); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); class Lambda implements LambdaInterface { From 6e06130093b52f2e209a2ae0529206a376613bf7 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 4 Jan 2022 23:00:57 +0100 Subject: [PATCH 15/24] docs: switched to serviceName according to #401 --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 312bea82f6..1daf06a86d 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -54,7 +54,7 @@ These settings will be used across all metrics emitted: Setting | Description | Environment variable | Constructor parameter ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- **Metric namespace** | Logical container where all metrics will be placed e.g. `serverlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace` -**Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `service` +**Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `serviceName` For a **complete list** of supported environment variables, refer to [this section](./../index.md#environment-variables). From a5dbd92d9630395d2da7db6455319f67dc7cd858 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 09:58:11 +0100 Subject: [PATCH 16/24] docs: update docs/core/tracer.md Co-authored-by: Florian Chazal --- docs/core/tracer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index b8f0de773a..0c84c2c73c 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -301,7 +301,7 @@ You can patch any AWS SDK clients by calling the `captureAWSv3Client` method: !!! info The following two snippets assume you are using the [**AWS SDK v2** for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/welcome.html) -You can patch all AWS SDK clients by calling the `captureAWS` method: +You can patch all AWS SDK v2 clients by calling the `captureAWS` method: === "index.ts" From faee18908c5eb25a14379585ab9179a3cf621111 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 09:58:46 +0100 Subject: [PATCH 17/24] docs: update docs/core/metrics.md Co-authored-by: Florian Chazal --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 1daf06a86d..50645581d9 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -471,7 +471,7 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o === "logMetrics decorator" - ```typescript hl_lines="9" + ```typescript hl_lines="8" import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; import { LambdaInterface } from '@aws-lambda-powertools/commons'; From d05e421b3ff79c6f61e6ced52206b6d50aa159ff Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 09:59:06 +0100 Subject: [PATCH 18/24] docs: update docs/core/tracer.md Co-authored-by: Florian Chazal --- docs/core/tracer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 0c84c2c73c..ac4666257d 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -252,7 +252,7 @@ You can trace other methods using the `captureMethod` decorator or manual instru === "Middy Middleware" !!! info - We currently support a middleware for tracing methods, [let us know](https://github.com/awslabs/aws-lambda-powertools-typescript/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=) if you'd like to see one! + We currently don't support middleware for tracing methods, [let us know](https://github.com/awslabs/aws-lambda-powertools-typescript/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=) if you'd like to see one! === "Decorator" From 2145f90a399c539b9acdca52f55d0e26a49cc12c Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 09:59:19 +0100 Subject: [PATCH 19/24] docs: update docs/core/logger.md Co-authored-by: Florian Chazal --- docs/core/logger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 8862aa4bc9..3ce0edf406 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -617,7 +617,7 @@ You can customize the structure (keys and values) of your log items by passing a logger.info("This is an INFO log", { correlationIds: { myCustomCorrelationId: "foo-bar-baz" } }); -}; + }; ``` This is how the `MyCompanyLogFormatter` (dummy name) would look like: From bfe774aa4a3a32ff25259e292d6d703bfe96d7e1 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 10:10:10 +0100 Subject: [PATCH 20/24] docs: update note on patching all modules --- docs/core/tracer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index ac4666257d..44b0dc6445 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -312,7 +312,7 @@ You can patch all AWS SDK v2 clients by calling the `captureAWS` method: const AWS = tracer.captureAWS(require('aws-sdk')); ``` -If you're looking to shave a few microseconds, or milliseconds depending on your function memory configuration, you can patch specific clients using `captureAWSClient`: +If you're looking to shave a few microseconds, or milliseconds depending on your function memory configuration, you can patch only specific AWS SDK v2 clients using `captureAWSClient`: === "index.ts" From fffc291b41d88246bd4a2826cdb1b924b1a08c2a Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 10:31:09 +0100 Subject: [PATCH 21/24] docs: updated text in captureMethod section --- docs/core/tracer.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 44b0dc6445..84cdacb652 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -208,7 +208,7 @@ When using the `captureLambdaHandler` decorator or middleware, Tracer performs t ### Methods -You can trace other methods using the `captureMethod` decorator or manual instrumentation. +You can trace other Class methods using the `captureMethod` decorator or any arbitrary function using manual instrumentation. === "Manual" @@ -249,11 +249,6 @@ You can trace other methods using the `captureMethod` decorator or manual instru } ``` -=== "Middy Middleware" - - !!! info - We currently don't support middleware for tracing methods, [let us know](https://github.com/awslabs/aws-lambda-powertools-typescript/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=) if you'd like to see one! - === "Decorator" ```typescript hl_lines="8" From d982318d16e9c34c3798f9eae39b01c892775500 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 10:47:49 +0100 Subject: [PATCH 22/24] docs: update docs/core/metrics.md Co-authored-by: ijemmy --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 50645581d9..ca6d010d6e 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -453,7 +453,7 @@ If you want to ensure that at least one metric is emitted before you flush them, You can optionally capture cold start metrics with the `logMetrics` middleware or decorator via the `captureColdStartMetric` param. -=== "logMetrics middleware" +=== "Middy Middleware" ```typescript hl_lines="11" import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; From 7853925118c30d15b6878eecefa996f7b0423b22 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 10:48:12 +0100 Subject: [PATCH 23/24] docs: update docs/core/metrics.md Co-authored-by: ijemmy --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index ca6d010d6e..5d68a1ef92 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -568,7 +568,7 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr **unique metric = (metric_name + dimension_name + dimension_value)** -=== "logMetrics middleware" +=== "Middy Middleware" ```typescript hl_lines="11 13-14" import { Metrics, MetricUnits, logMetrics } from '@aws-lambda-powertools/metrics'; From ce9e3d89c9e5cba6d9fae7a5f2102acfe8b80db7 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Jan 2022 10:48:45 +0100 Subject: [PATCH 24/24] docs: updated other references to serverlessAirline --- docs/core/logger.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 3ce0edf406..3193357f6a 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -86,7 +86,7 @@ Key | Example | Note **level**: `string` | `INFO` | Logging level set for the Lambda function"s invocation **message**: `string` | `Query performed to DynamoDB` | A descriptive, human-readable representation of this log item **sampling_rate**: `float` | `0.1` | When enabled, it prints all the logs of a percentage of invocations, e.g. 10% -**service**: `string` | `shopping-cart-api` | A unique name identifier of the service this Lambda function belongs to, by default `service_undefined` +**service**: `string` | `serverlessAirline` | A unique name identifier of the service this Lambda function belongs to, by default `service_undefined` **timestamp**: `string` | `2011-10-05T14:48:00.000Z` | Timestamp string in simplified extended ISO format (ISO 8601) **xray_trace_id**: `string` | `1-5759e988-bd862e3fe1be46a994272793` | When [tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"}, it shows X-Ray Trace ID **error**: `Object` | `{ name: "Error", location: "/my-project/handler.ts:18", message: "Unexpected error #1", stack: "[stacktrace]"}` | Optional - An object containing information about the Error passed to the logger @@ -518,7 +518,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "WARN", "message": "This is a WARN log that has 50% chance of being printed", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.338Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -531,7 +531,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "ERROR", "message": "This is an ERROR log", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.334Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -544,7 +544,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "ERROR", "message": "This is an ERROR log", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.334Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -552,7 +552,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "DEBUG", "message": "This is a DEBUG log that has 50% chance of being printed", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.337Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -568,7 +568,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "WARN", "message": "This is a WARN log that has 50% chance of being printed", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.338Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" } @@ -581,7 +581,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "ERROR", "message": "This is an ERROR log", "sampling_rate": "0.5", - "service": "shopping-cart-api", + "service": "serverlessAirline", "timestamp": "2021-12-12T22:59:06.334Z", "xray_trace_id": "abcdef123456abcdef123456abcdef123456" }