diff --git a/docs/core/logger.md b/docs/core/logger.md index 1112eaec10..3193357f6a 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 @@ -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 @@ -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,45 +135,33 @@ 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" + ```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 implements LambdaInterface { + // Decorate your handler class method @logger.injectLambdaContext() - public handler() { + 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; ``` In each case, the printed log will look like this: @@ -173,7 +177,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 +217,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 +236,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 +249,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 +275,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 +304,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 +312,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 +332,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 +357,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 +370,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 +404,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 +421,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" } @@ -465,7 +469,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) => { // This log item (equal to log level 'ERROR') will be printed to standard output // in all Lambda invocations @@ -490,7 +494,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" } @@ -498,7 +502,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" } @@ -506,7 +510,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "INFO", "message": "This is an INFO 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" } @@ -514,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" } @@ -527,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" } @@ -540,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" } @@ -548,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" } @@ -556,7 +560,7 @@ For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda i "level": "INFO", "message": "This is an INFO 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" } @@ -564,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" } @@ -577,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" } @@ -585,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" @@ -596,7 +600,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, @@ -607,10 +611,12 @@ 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" } }); + }; ``` @@ -625,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 { @@ -666,7 +672,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", @@ -722,7 +728,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/metrics.md b/docs/core/metrics.md index 23f4691910..5d68a1ef92 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -54,27 +54,31 @@ 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). -!!! 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', + // serviceName: 'orders' + // }); ``` -=== "sam-template.yml" +=== "template.yml" ```yaml hl_lines="9 10" Resources: @@ -84,50 +88,48 @@ 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', serviceName: 'orders' }); - export const handler = async (event: any, context: Context) => { + export const handler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.publishStoredMetrics(); } ``` + === "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', serviceName: '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.publishStoredMetrics(); } ``` !!! 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. @@ -142,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); @@ -182,29 +184,25 @@ You can call `addMetric()` with the same name multiple times. The values will be ``` ### 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', + serviceName: '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); } ``` @@ -217,31 +215,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 metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: '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', serviceName: '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); } ``` @@ -250,32 +248,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', serviceName: 'orders' }); + const DEFAULT_DIMENSIONS = { 'environment': 'prod', 'foo': 'bar' }; + export class MyFunction implements 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 `publishStoredMetrics()`. 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" @@ -285,52 +285,97 @@ 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 `publishStoredMetrics` as follows: + +!!! warning + Metrics, dimensions and namespace validation still applies. + +=== "handler.ts" + + ```typescript hl_lines="7" + import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; + + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); -#### Using Middy middleware + export const handler = async (_event: any, _context: any) => { + metrics.addMetric('successfulBooking', MetricUnits.Count, 10); + metrics.publishStoredMetrics(); + }; + ``` + +=== "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" + ```typescript hl_lines="1-2 7 10-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', serviceName: '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)); -``` + ``` === "Example CloudWatch Logs excerpt" ```json hl_lines="2 7 10 15 22" { - "bookingConfirmation": 1.0, + "successfulBooking": 1.0, "_aws": { - "Timestamp": 1592234975665, - "CloudWatchMetrics": [ - { - "Namespace": "exampleApplication", - "Dimensions": [ - [ - "service" - ] - ], - "Metrics": [ - { - "Name": "bookingConfirmation", - "Unit": "Count" - } + "Timestamp": 1592234975665, + "CloudWatchMetrics": [ + { + "Namespace": "serverlessAirline", + "Dimensions": [ + [ + "service" ] + ], + "Metrics": [ + { + "Name": "successfulBooking", + "Unit": "Count" } ] }, - "service": "exampleService" + "service": "orders" } ``` @@ -343,83 +388,61 @@ 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" + + ```typescript hl_lines="8" + import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; + import { LambdaInterface } from '@aws-lambda-powertools/commons'; -const metrics = new Metrics({namespace:"exampleApplication", service:"exampleService"}); + const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); -export class MyFunction { + export class MyFunction implements LambdaInterface { - @metrics.logMetrics() - public handler(_event: TEvent, _context: Context, _callback: Callback): void | Promise { - metrics.addMetric('bookingConfirmation', MetricUnits.Count, 1); + @metrics.logMetrics() + public async handler(_event: any, _context: any): Promise { + metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + } } -} -``` + ``` === "Example CloudWatch Logs excerpt" ```json hl_lines="2 7 10 15 22" { - "bookingConfirmation": 1.0, + "successfulBooking": 1.0, "_aws": { - "Timestamp": 1592234975665, - "CloudWatchMetrics": [ - { - "Namespace": "exampleApplication", - "Dimensions": [ - [ - "service" - ] - ], - "Metrics": [ - { - "Name": "bookingConfirmation", - "Unit": "Count" - } + "Timestamp": 1592234975665, + "CloudWatchMetrics": [ + { + "Namespace": "successfulBooking", + "Dimensions": [ + [ + "service" ] + ], + "Metrics": [ + { + "Name": "successfulBooking", + "Unit": "Count" } ] }, - "service": "exampleService" + "service": "orders" } ``` - -#### Manually - -You can manually flush the metrics with `publishStoredMetrics` 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); - const metricsObject = metrics.serializeMetrics(); - metrics.publishStoredMetrics(); - console.log(JSON.stringify(metricsObject)); -}; -``` - #### 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', serviceName: '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) @@ -430,16 +453,15 @@ 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="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', serviceName: 'orders' }); - const lambdaHandler = async (event: any, context: Context) => { + const lambdaHandler = async (_event: any, _context: any) => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); } @@ -449,17 +471,16 @@ 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 { 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' }); + const metrics = new Metrics({namespace: 'serverlessAirline', serviceName: 'orders' }); - export class MyFunction { + export class MyFunction implements 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); } } @@ -468,7 +489,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. @@ -478,25 +499,27 @@ 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 -```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 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', serviceName: 'orders' }); - export const handler = middy(lambdaHandler) - .use(logMetrics(metrics)); -``` + const lambdaHandler = async (_event: any, _context: any) => { + metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetadata('bookingId', '7051cd10-6283-11ec-90d6-0242ac120003'); + } + + export const handler = middy(lambdaHandler) + .use(logMetrics(metrics)); + ``` === "Example CloudWatch Logs excerpt" @@ -504,8 +527,16 @@ You can add high-cardinality data as part of your Metrics log with `addMetadata` { "successfulBooking": 1.0, "_aws": { - "Timestamp": 1592234975665, - "CloudWatchMetrics": [ + "Timestamp": 1592234975665, + "CloudWatchMetrics": [ + { + "Namespace": "serverlessAirline", + "Dimensions": [ + [ + "service" + ] + ], + "Metrics": [ { "Namespace": "exampleApplication", "Dimensions": [ @@ -522,7 +553,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" } ``` @@ -537,16 +568,15 @@ 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="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', serviceName: '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); @@ -558,21 +588,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', serviceName: 'orders' }); - export class MyFunction { + class Lambda implements 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); @@ -583,4 +613,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 6c02b8d363..84cdacb652 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 = Tracer(); // Sets service via env var - // OR tracer = 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 = Tracer(); // Sets service via env var - // OR tracer = 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 = Tracer(); // Sets service via env var - // OR tracer = 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,60 @@ 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" + + !!! 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 implements LambdaInterface { + // Decorate your handler class method + @tracer.captureLambdaHandler() + public async handler(_event: any, _context: any): Promise { + /* ... */ + } + } + + 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,47 +201,18 @@ 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); } ``` ### Methods -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 = 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; - ``` +You can trace other Class methods using the `captureMethod` decorator or any arbitrary function using manual instrumentation. === "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 +225,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,45 +245,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); - ... + /* ... */ } ``` +=== "Decorator" + + ```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 implements LambdaInterface { + // Decorate your class method + @tracer.captureMethod() + public getChargeId(): string { + /* ... */ + return 'foo bar'; + } + + public async handler(_event: any, _context: any): Promise { + /* ... */ + } + } + + export const myFunction = new Lambda(); + export const handler = myFunction.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 v2 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')); ``` -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" @@ -300,8 +315,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 +351,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