Introducing a better way to record custom metrics
Tags: aws, serverless, lambda, monitoring
Published: 2019-07-26 11:07:39

---
title: Introducing a better way to record custom metrics
published: true
tags: AWS,Serverless,Lambda,Monitoring
canonical_url: https://theburningmonk.com/2019/07/introducing-a-better-way-to-record-custom-metrics/
---

Many clients have asked me “_how do I record custom metrics from Lambda?_”.

Generally speaking, you can either:

- Publish custom metrics **synchronously** – e.g. send them at the end of an invocation.
- Publish custom metrics **asynchronously** by writing them to stdout first and then extracting them from CloudWatch Logs.

### Problems with sending custom metrics synchronously

The synchronous approach adds latency to invocations. This can be especially problematic when those extra milliseconds are experienced by our users. For example, if the user is waiting for an API response.

![](https://theburningmonk.com/wp-content/uploads/2019/07/img_5d3a26d65e330.png)

Individually, the delay might be negligible. CloudWatch metrics typically respond within tens of milliseconds. That is acceptable to most. But they can quickly compound when functions call one another via API Gateway.

![](https://theburningmonk.com/wp-content/uploads/2019/07/img_5d3a26ed2d82d.png)

Moreover, services are most fragile around their integration points – i.e. when they make network calls to other services. Publishing metrics to CloudWatch introduces another integration point that you need to harden.

If CloudWatch experiences an outage, surely you would still want your system to stay up, right? Similarly, if CloudWatch experiences elevated response time then you wouldn’t want your functions to timeout as a result!

Hence why I generally prefer to record custom metrics asynchronously, even though this approach also has its drawbacks:

- There is an additional delay in seeing the most recent metric data.
- It’s sending more data to CloudWatch Logs, which has a cost implication

![](https://theburningmonk.com/wp-content/uploads/2019/07/img_5d3a2701910ac.png)

- It introduces complexity because you need something to process the logs and turn them into metrics.

### Sending custom metrics asynchronously

In simple cases, where you have few custom metrics, [CloudWatch metric filters](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/MonitoringPolicyExamples.html) are the way to go. However, this approach does not scale with complexity – when you have lots of functions and custom metrics.

Instead, you can use a Lambda function.

To make it really easy for you to record custom metrics asynchronously, I have published a new application to the [Serverless Application Repository](https://serverlessrepo.aws.amazon.com/applications). You can also check out the source code on GitHub [here](https://github.com/theburningmonk/SAR-async-lambda-metrics).

#### Getting started

You can deploy the app via the AWS console [here](https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:374852340823:applications~async-custom-metrics), by clicking the `Deploy` button and follow the instructions.

![](https://theburningmonk.com/wp-content/uploads/2019/07/img_5d3a272c093e6.png)

Or you can deploy it as part of a CloudFormation stack with AWS SAM:

![](https://theburningmonk.com/wp-content/uploads/2019/07/img_5d3a274465d8d.png)

You can do the same via CloudFormation or the Serverless framework. You need to first add the following `Transform` though. For more details on how to do this with the Serverless framework, read this [post](https://dev.to/theburningmonk/how-to-include-serverless-repository-apps-in-serverless-yml-52md).

```
Transform: AWS::Serverless-2016-10-31
```

We announced this new app [live on Twitch](https://www.twitch.tv/videos/457316850) yesterday. You can go to the 21:00 mark and see how you can configure everything via CloudFormation, including subscribing all CloudWatch log groups to a Kinesis stream first, before subscribing this app to that stream.

#### Recording custom metrics

Once deployed, you would be able to record custom metrics by writing to `stdout` in this format:

`MONITORING|<value>|<unit>|<metric_name>|<namespace>|<dimensions>`

where:

- `value` is a `float`
- `unit` can be any of the [allowed CloudWatch metric units](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html)
- `namespace`: custom metrics would appear under this namespace, e.g.

![](https://theburningmonk.com/wp-content/uploads/2019/07/img_5d3a2762c805a.png)

- `dimensions`: comma-separated key-value pairs, e.g. `service=content-item,region=eu-west-1`

These messages would be processed and published as custom metrics in CloudWatch metrics. All without adding latency to your invocations!

### Future works

I hope you enjoy this new app, and please feel free to suggest improvements via GitHub [issues](https://github.com/theburningmonk/SAR-async-lambda-metrics/issues). Here are some ideas I have for making it more useful:

- Parse the `REPORT` messages at the end of an invocation and turn `Billed Duration`, `Memory Size` and `Memory Used` into metrics:

![](https://theburningmonk.com/wp-content/uploads/2019/07/img_5d3a278aeab9a.png)

- Since AppSync doesn’t report resolver metrics to CloudWatch, we can parse the [resolver logs](https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html) and report resolver duration as metrics.

 ![](https://theburningmonk.com/wp-content/uploads/2019/03/img_5c8ca195210d5.png)

Hi, my name is **Yan Cui**. I’m an **[AWS Serverless Hero](https://aws.amazon.com/developer/community/heroes/yan-cui/)** and the author of [**Production-Ready Serverless**](https://bit.ly/production-ready-serverless). I have run production workload at scale in AWS for nearly 10 years and I have been an architect or principal engineer with a variety of industries ranging from banking, e-commerce, sports streaming to mobile gaming. I currently work as an independent consultant focused on AWS and serverless.

You can contact me via [Email](mailto:theburningmonk.com), [Twitter](https://twitter.com/theburningmonk) and [LinkedIn](https://www.linkedin.com/in/theburningmonk/).

[Hire me.](https://theburningmonk.com/hire-me)

The post [Introducing a better way to record custom metrics](https://theburningmonk.com/2019/07/introducing-a-better-way-to-record-custom-metrics/) appeared first on [theburningmonk.com](https://theburningmonk.com).

 ![](http://feeds.feedburner.com/~r/theburningmonk/~4/rvnQRIDr9BQ)