AWS Lambda Powertools for TypeScript is currently released as a beta developer preview and is intended strictly for feedback purposes only.
This version is not stable, and significant breaking changes might incur as part of the upcoming production-ready release.
If you're new to Amazon CloudWatch, there are two terminologies you must be aware of before using this utility:
Namespace. It's the highest level container that will group multiple metrics from multiple services for a given application, for example ServerlessEcommerce.
Dimensions. Metrics metadata in key-value format. They help you slice and dice metrics visualization, for example ColdStart metric by Payment service.
The Metrics utility must always be instantiated outside of the Lambda handler. In doing this, subsequent invocations processed by the same instance of your function can reuse these resources. This saves cost by reducing function run time. In addition, Metrics can track cold start and emit the appropriate metrics.
The library requires two settings. You can set them as environment variables, or pass them in the constructor.
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
serviceName
For a complete list of supported environment variables, refer to this section.
Tip
Use your application name or main service as the metric namespace to easily group all metrics
Example using AWS Serverless Application Model (SAM)¶
The Metrics utility is instantiated outside of the Lambda handler. In doing this, the same instance can be used across multiple invocations inside the same execution environment. This allows Metrics to be aware of things like whether or not a given invocation had a cold start or not.
1 2 3 4 5 6 7 8 910
import{Metrics}from'@aws-lambda-powertools/metrics';// Metrics parameters fetched from the environment variables (see template.yaml tab)constmetrics=newMetrics();// You can also pass the parameters in the constructor// const metrics = new Metrics({// namespace: 'serverlessAirline',// serviceName: 'orders'// });
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".
Metrics overflow
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.
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.
You can call addMetric() with the same name multiple times. The values will be grouped together in an array.
1 2 3 4 5 6 7 8 910
import{Metrics,MetricUnits}from'@aws-lambda-powertools/metrics';import{Context}from'aws-lambda';constmetrics=newMetrics({namespace:'serverlessAirline',serviceName:'orders'});exportconsthandler=async(event:any,context:Context):Promise<void>=>{metrics.addMetric('performedActionA',MetricUnits.Count,2);// do something else...metrics.addMetric('performedActionA',MetricUnits.Count,1);};
import{Metrics,MetricUnits,logMetrics}from'@aws-lambda-powertools/metrics';importmiddyfrom'@middy/core';constmetrics=newMetrics({namespace:'serverlessAirline',serviceName:'orders'});constlambdaHandler=async(_event:any,_context:any):Promise<void>=>{metrics.addMetric('successfulBooking',MetricUnits.Count,1);};// Wrap the handler with middyexportconsthandler=middy(lambdaHandler)// Use the middleware by passing the Metrics instance as a parameter.use(logMetrics(metrics,{defaultDimensions:{'environment':'prod','foo':'bar'}}));
import{Metrics,MetricUnits}from'@aws-lambda-powertools/metrics';import{LambdaInterface}from'@aws-lambda-powertools/commons';constmetrics=newMetrics({namespace:'serverlessAirline',serviceName:'orders'});constDEFAULT_DIMENSIONS={'environment':'prod','foo':'bar'};exportclassMyFunctionimplementsLambdaInterface{// Decorate your handler class method@metrics.logMetrics({defaultDimensions:DEFAULT_DIMENSIONS})publicasynchandler(_event:any,_context:any):Promise<void>{metrics.addMetric('successfulBooking',MetricUnits.Count,1);}}
If you'd like to remove them at some point, you can use the clearDefaultDimensions method.
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:
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 thrown.
If you do not use the middleware or decorator, you have to flush your metrics manually.
Metric validation
If metrics are provided, and any of the following criteria are not met, a RangeError exception will be thrown:
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, check the middleware or manual method sections instead.
See the official TypeScript documentation for more details.
The logMetrics decorator of the metrics utility can be used when your Lambda handler function is implemented as method of a Class.
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 throwOnEmptyMetrics parameter and pass it to the middleware or decorator:
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
import{Metrics,MetricUnits,logMetrics}from'@aws-lambda-powertools/metrics';importmiddyfrom'@middy/core';constmetrics=newMetrics({namespace:'serverlessAirline',serviceName:'orders'});constlambdaHandler=async(_event:any,_context:any):Promise<void>=>{metrics.addDimension('metricUnit','milliseconds');// This metric will have the "metricUnit" dimension, and no "metricType" dimension:metrics.addMetric('latency',MetricUnits.Milliseconds,56);constsingleMetric=metrics.singleMetric();// This metric will have the "metricType" dimension, and no "metricUnit" dimension:singleMetric.addDimension('metricType','business');singleMetric.addMetric('orderSubmitted',MetricUnits.Count,1);};exportconsthandler=middy(lambdaHandler).use(logMetrics(metrics));
1 2 3 4 5 6 7 8 910111213141516171819202122
import{Metrics,MetricUnits}from'@aws-lambda-powertools/metrics';import{LambdaInterface}from'@aws-lambda-powertools/commons';constmetrics=newMetrics({namespace:'serverlessAirline',serviceName:'orders'});classLambdaimplementsLambdaInterface{@metrics.logMetrics()publicasynchandler(_event:any,_context:any):Promise<void>{metrics.addDimension('metricUnit','milliseconds');// This metric will have the "metricUnit" dimension, and no "metricType" dimension:metrics.addMetric('latency',MetricUnits.Milliseconds,56);constsingleMetric=metrics.singleMetric();// This metric will have the "metricType" dimension, and no "metricUnit" dimension:singleMetric.addDimension('metricType','business');singleMetric.addMetric('orderSubmitted',MetricUnits.Count,1);}}exportconstmyFunction=newLambda();exportconsthandler=myFunction.handler;