⚖️

AWS Embedded Metricsを使ってメトリクスを保存してみた

2022/06/01に公開

はじめに

先日開催されたAWS SummitのAWS Lambda Performance Tuning Deep Dive〜本当に知りたいのは”ここ”だった 〜(AWS-46)
が最高だったので紹介されていたAWS Embedded Metricsを使ってみました。

要約

  • aws-embedded-metrics-nodeライブラリを使うとCloudWatch Logs経由でMetricsを発行できる
  • ライブラリのサポートがあるのでAWS SDKで直接CloudWatch MetricsへPutするより書きやすい
  • ログとして自由に情報を追加できるのでCloudWatch Logs Insightsを使うことでMetricsをより詳細な条件で分析ができる

Embedded Metrics Formatとは

Embedded Metrics Formatはログに埋め込まれたメトリクスを自動的にCloudWatch LogsからMetricsへ発行するように指示できるJSON仕様です。

Specification: Embedded metric format

sample
{
  "_aws": {
    "CloudWatchMetrics": [
      {
        "Metrics": [
          {
            "Name": "Time",
            "Unit": "Milliseconds"
          }
        ],
        ...
      }
    ]
  },
  "Time": 1
}

aws-embedded-metrics-nodeライブラリはこの仕様に準拠したログを発行することで間接的にメトリクス発行を行います。

aws-embedded-metricsライブラリ

aws-embedded-metricsライブラリはNode.js(型情報あり)/Python/Java/C#の4言語をサポートしています。
Using the client libraries to generate embedded metric format logs - Amazon CloudWatch

サンプル

API GatewayとLambdaで空データを返却するWebAPIを作成しました。言語はTypeScriptを使用しています。
メトリクスにはダミーデータを使用します。

import {APIGatewayProxyHandler} from 'aws-lambda';
import {metricScope, Unit} from 'aws-embedded-metrics';

const getRandom = (min: number, max: number): number =>
  Math.floor(Math.random() * (max + 1 - min)) + min;

const getFruit = () => {
  const fruits = ['apple', 'banana', 'orange'];
  return fruits[getRandom(0, fruits.length - 1)];
};

export const handler: APIGatewayProxyHandler = metricScope(
  metrics => async () => {
    metrics.setNamespace('DemoAwsEmbeddedMetrics');
    metrics.putDimensions({Service: 'MyService'});
    metrics.putMetric(
      'ProcessingLatency',
      getRandom(50, 150),
      Unit.Milliseconds
    );
    metrics.putMetric('Warnings', getRandom(0, 10), Unit.Count);
    metrics.setProperty('Fruit', getFruit());

    return {
      statusCode: 200,
      body: '',
    };
  }
);

記録されるメトリクスとログ

作成したAPIに継続的にアクセスしてログを生成します。今回はwatchcurlを使いました。

watch -n1 curl https://${APIGW_ENDPOINT_URL}

CloudWatch Logsにログが保存されています。
putMetricが複数回呼ばれたとしてもログとしては1件にまとまるようです。メトリクスを記録するためのものなのでこういう仕様なのでしょうか、このライブラリはあくまでもロガーとは別モノとして考えたほうが良さそうです。

CloudWatch Metricsにメトリクスが生成されています。

さらにログに対してCloudWatch Logs Insightsを使って以下の条件にしたがって分析を行います。

  • フルーツ=オレンジだけを対象
  • 5秒単位でWarningsの平均、ProcessingLatencyの平均、アクセス件数を集計する。
fields @timestamp, @message
| filter Fruit="orange"
| stats avg(Warnings), avg(ProcessingLatency), count(*) by bin(5s)

今回はフルーツという仮想の分類ですが実環境ではパスなどを対象にフィルタリングするために便利そうです。

あとがき

オブザーバービリティーの文脈でCloudWatch MetricsやDashboardの話が出てくるのは観測しつつも触ったことが無かったのでとりあえず試せて良かったです。ビジネスメトリクスをガンガン記録したくなりました。
以上でした!

Discussion