Dev Study
AWSサービスの内部原理 コース

71. ログとメトリクスの境界は溶ける — 抽出(メトリクスフィルタ)と埋め込み(EMF)という2つの変換

「イベントの記録」であるログから「数値の時系列」であるメトリクスが生まれる2つの経路を、上から下への変換の流れとして図で追っていきます。

① ログとメトリクスは同じ事実の別表現

ログイベント個々の記録: いつ・何が起きたか
この変換に2つの経路がある
メトリクス数値の時系列: 1分間にエラー何回か
メトリクスフィルタ経路1: ログの外側から監視(抽出)
EMF経路2: ログの中に規約を埋め込む(埋め込み)
  • 構造化ログ(機械が読める形式でログを書く)というCS基礎の応用が、経路2(EMF)の前提になる。
  • ログ→メトリクスの変換は、CS基礎でいうETL(抽出・変換・格納)の最小例。Kinesisで見た「追記ログ(不変のイベント列)からいろいろなビューを後から作る」発想の可観測性版でもある。

イベント(記録)と集計(時系列)は相互に導出できる。CloudWatchはその変換に「外から抽出する」経路と「中に埋め込む」経路の2つを用意している。

② メトリクスフィルタ: 外から数える

ログイベント流入ロググループへ
マッチした行ごとに
フィルタパターン例: 行に "Error" を含むか
ログの中身は変えない
発行先を自分で決める
metric value発行値 = 1 を発行
名前空間+メトリクス名例: ErrorCount メトリクス
  • 公式: metric value =「The numerical value to publish to the metric each time a matching log is found. …if you're counting the occurrences of a particular term like "Error", the value will be "1" for each occurrence」。metric name の例に「ErrorCount」がそのまま載っている。
  • 値は1固定ではなく、転送バイト数のようにログ中の実数値で増やすこともできる。

メトリクスフィルタはログを書き換えず、外から照合して「マッチのたびに数える」。名前空間・メトリクス名・値の3つを自分で決める。

③ 遡及しない・歯抜けになる

フィルタ作成 t0
マッチが無い1分間はどうなるか
t0より前遡及しない(発行なし)
t0より後ここからのイベントだけ数える
さらに前提の制約
default未設定何も報告しない(歯抜け=スポッティ)
default value=00 を報告(連続した時系列)
Standardクラスのみメトリクスフィルタが使えるロググループ
  • 公式:「Filters do not retroactively filter data. Filters only publish the metric data points for events that happen after the filter was created.」
  • 公式: default value =「By setting this to 0, you ensure that data is reported during every such period, preventing "spotty" metrics」。ただし「If no logs are ingested during a one-minute period, then no value is reported」— そもそもログが1件も流入しない1分間には 0 すら出ない。
  • 公式:「If you assign dimensions to a metric created by a metric filter, you can't assign a default value for that metric.」— ディメンションを付けたフィルタには default value を設定できない。
  • 公式:「Metric filters are supported only for log groups in the Standard log class.」

メトリクスフィルタは「作成後のイベントだけ」を数え、無マッチ期間は既定で歯抜けになる。default value=0 で時系列を連続させられるが、ログ自体が無い期間は 0 も出ず、ディメンション付きのフィルタでは default value 自体が使えない。

④ EMF: ログに規約を埋め込む

EMFログ1本決められた規約のJSONとして書く
CloudWatch Logs が取り込み時に自動抽出
_awsメタデータ=抽出方法の宣言: Namespace / Dimensions([["functionVersion"]]) / Metrics({Name:"time", Unit:"Milliseconds"})
Timestamp: 1574109732004(UNIXミリ秒)
ルート直下実データ: functionVersion="$LATEST", time=100
Name:"time" がこの値を名前参照
ログ1本詳細の調査に使える
メトリクスtime=100 が発行される
1回の書き込みで両方が手に入る
  • ルートは `_aws`(Metadata object)を必ず持ち、その中の `CloudWatchMetrics`(MetricDirective の配列)と `Timestamp` はどちらも必須メンバー。Timestamp は「the number of milliseconds after Jan 1, 1970 00:00:00 UTC」。
  • MetricDefinition の `Name` は Target member への「Reference values」で、値はルート直下(ネスト不可)にあり、数値または数値の配列でなければならない。
  • EMF文書全体は標準のログイベントと同じく最大 1 MB。
  • 利点: PutMetricData API を呼ばずにログ1本でログとメトリクスの両方が手に入り、メトリクスで異常を見つけたら同じログで詳細を調べられる。

EMFは「宣言(_aws)」と「実データ(ルート直下)」を1つのJSONに同居させ、名前参照でつなぐ。ログを規約通りに書くだけで、CloudWatchが取り込み時にメトリクスを抜き出す。

⑤ EMFの容量と解像度

CloudWatchMetrics_aws の中の宣言(MetricDirective)
各メトリクスごとに解像度を選ぶ
DimensionsDimensionSet 1個あたり最大30キー(空でも可)
MetricsMetricDefinition 最大100個
StorageResolution=1高解像度(最小1秒粒度)
StorageResolution=60標準解像度(1分粒度)・既定
  • 公式:「A DimensionSet MUST NOT contain more than 30 dimension keys. A DimensionSet MAY be empty.」
  • 公式:「This array MUST NOT contain more than 100 MetricDefinition objects.」さらに1つのメトリクス値を数値の配列にする場合「Numeric array metric targets MUST NOT have more than 100 members.」
  • StorageResolution=1 で「sub-minute resolution down to one second」、未指定なら既定 60。

EMFは DimensionSet最大30キー・Metrics最大100定義という枠の中で宣言する。StorageResolution=1 を指定すれば1秒粒度の高解像度メトリクスも同じ1本のログから得られる。

⑥ 高カーディナリティの課金爆発

ディメンションメトリクスの一意な識別子の一部
ユニークな組み合わせごとに別メトリクスが生まれる
低カーディナリティ例: functionVersion($LATEST / v1 / v2)
高カーディナリティ例: requestId(毎回ユニークなID)
少数のメトリクス課金は安定
メトリクス増殖リクエスト数だけ増える → 課金爆発
  • メトリクスフィルタ側の公式:「dimensions … Because dimensions are part of the unique identifier for a metric, whenever a unique name/value pair is extracted from your logs, you are creating a new variation of that metric.」
  • EMF側の公式:「If you unintentionally create metrics based on high-cardinality dimensions (such as `requestId`), the embedded metric format will by design create a custom metric corresponding to each unique dimension combination.」「Every DimensionSet used creates a new metric in CloudWatch.」
  • 「キーの取り方が結果を支配する」のは、DynamoDBのパーティションキー(値の分布が物理的な置き場所を決める)と同型の原理。ここではキーのカーディナリティが課金を決める。

どちらの経路でも、ディメンションはキーであり、ユニークな組み合わせごとに別メトリクスが生まれる。第1レッスンで見た「ディメンション=キー」の原理が、ここでは「キーのカーディナリティが課金を決める」として効いてくる。

公式ドキュメントで詳しく ↗