Skip to content

diamondのcleanup-metric-cacheが処理する対象

メトリックが送られ続ける限りは、投稿時の処理で古くなったメトリックをDynamoDBへ移行している。そのため cleanup-metric-cache は投稿が止まったメトリックのみが対象となる。

MetricCache とは、DiamondストレージのうちRedis部分に相当する名称。

metricSetとは、特定の期間に投稿された(Diamondが扱う形式の)メトリック名がすべて保存されている巨大なSET構造のこと。特定の1分間に対応するmetricSetの粒度は以下の4つ存在する。

  • 1m … 60
  • 5m … 300
  • 1h … 3600
  • 1d … 86400

例えば 2025-09-01 12:53 (UTC)system.cpu.usage が投稿された場合、以下のmetricSetすべてにメトリック名が保存される。末尾の (n) はどれだけの期間でmetricSetが切り替わるのかを意味する。metricSet名の末尾はタイムスタンプで、これは n によって丸められている。

  • metricSet:60:1756728000 (4h)
  • metricSet:300:1756684800 (1d)
  • metricSetV2:3600-{0-1}:1756339200 (7d)
  • metricSetV2:86400-{0-4}:1734480000 (365d)

粒度と期間の関係などはdiamond-writer読解メモにも書いた。

  • diamond-writer/functions/cleanup-metric-cache/index.ts
  • diamond-writer/lib/diamondwriter.ts:cleanup
  • diamond-writer/lib/metricpurger.ts:cleanup
  • diamond-writer/lib/metriccache.ts

cleanup-metric-cache はEventBridgeで1分単位の実行が設定されているので1分ごとに1リクエスト発生する。

cleanup-metric-cache を実行したとき、現在時刻から20時間以上残っているメトリックを掃除する。例えば 2025-09-01 23:00 に起動したリクエストなら、そこから20時間前の 2025-09-01 03:00 より古いmetricSetを扱う。

[! Attention] 20時間前だと、最長のmetricSetである1日粒度がまだ更新中で困るような気もするが確認していない。

7日ごと毎週金曜日に cleanup-metric-cache の山があるのは、1時間粒度のmetricSetがそこで切り替わるから。実際にログを調査しても、1時間粒度のログはあるが1日粒度のものは無かった。では1日粒度は1年間ずっとDynamoDBに書き出されないのか?でいえば、1時間粒度で消去したメトリックに対して同じことをやっている。

const hourNames = await this.metricPurgers.hour.cleanup(timestamp);
await this.forcePurgeDayMetrics(hourNames);

metric-set-length.202x のグラフをみても、1日粒度のグラフは1時間粒度が消滅する時期と同じ頃に少し減少して、また戻るような動きをしている。

特定粒度を消すと決めた場合、2025-09-01 03:00 を起点とするなら、それを含めて10個前までの点に対応するmetricSetの中から2000個のメトリックを消す。例えば5分粒度なら 3:00, 2:55, 2:502:15 となる。この範囲ひとつをタイムウインドウと呼んでいる。

実装はdiamond-writer/functions/cleanup-metric-cache/index.ts にあるが、色々と省略すると以下のような処理が行われる。

const targetSteps = [0..9];
const diffHour = 60 * 60 * 20; // 20h以前をcleanup
for (const diff of targetSteps) {
// clean up from older time window
await diamondWriter.cleanup(Date.now() / 1000 - diffHour, diff);
}

DiamondWriter.cleanuppurgeMetric を呼び出し、そこで全ての粒度をまとめて扱う。

return Promise.all([
this.metricPurgers.onemin.purge(metric.name, metric.timestamp),
this.metricPurgers.fivemin.purge(metric.name, metric.timestamp),
this.metricPurgers.hour.purge(metric.name, metric.timestamp),
this.metricPurgers.day.purge(metric.name, metric.timestamp)
]);

このとき、1回の cleanup で扱うメトリックの数に上限があって、1日粒度のような巨大なmetricSetであっても、1リクエストで cleanup するメトリックは2,000個が上限となっている。余った分は次のリクエストで処理される。全てタイムウインドウを使い切っても処理できずに残ってしまったメトリックは失われることになるが、タイムウインドウが十分あるので滅多なことは起こらないだろう。