可観測性¶
ログ¶
全 Lambda は @aws-lambda-powertools/logger で構造化 JSON ログを出力する (Issue #78)。
標準 attribute:
| attribute | 由来 | 用途 |
|---|---|---|
level |
logger | INFO / WARN / ERROR |
message |
logger | 人間向け文字列 (検索 key 兼用) |
service |
logger | Lambda 名 (deliver / webhook-backlog 等) |
function_request_id |
logger.addContext |
Lambda 1 実行を一意に識別 |
cold_start |
logger.addContext |
Cold start invocation か |
tenant |
withLogContext |
配信スコープ内のテナント slug |
issueKey |
withLogContext |
Backlog 課題 key (deliver / webhook-backlog) |
error.name / error.message / error.stack |
toLogError(err) |
失敗ログに必ず付与 |
| 種類 | 内容 | 保管 |
|---|---|---|
| アプリログ | 構造化 JSON(INFO/WARN/ERROR) | CloudWatch Logs 30 日 |
| 監査ログ | 状態遷移 / 外部 API 呼び出し / シークレット参照 | DB 12 ヶ月以上 |
| 配信ログ | DeliveryRun, リトライ, 通数 | DB 12 ヶ月以上 |
| クリックログ | リダイレクタ受信ログ | DB 12 ヶ月以上 |
ログレベル¶
POWERTOOLS_LOG_LEVEL 環境変数で上書き可能 (default INFO)。LOG_LEVEL は fallback。
CloudWatch Logs Insights クエリ集¶
CloudWatch コンソール → Logs Insights で実行する。Log group は /aws/lambda/automedia-<service>。
複数 Lambda 横断は Logs Insights 画面で対象 log group を複数選択する。
配信 1 件のフルトレース (issueKey)¶
fields @timestamp, service, level, message, error.message
| filter issueKey = "BATO-15"
| sort @timestamp asc
webhook-backlog → deliver の流れが時系列で並ぶ。X-Ray と突合する場合は function_request_id か _X_AMZN_TRACE_ID (= xray_trace_id attribute) を控える。
tenant 別の配信エラー集計 (直近 24h)¶
fields @timestamp, service, message, error.message
| filter level = "ERROR" and service = "deliver"
| stats count() by tenant
tenant は withDeliveryScope で全 deliver ログに付与される。
失敗種別 (message) 集計¶
message は logger.error('...') の固定文字列なので失敗カテゴリの分類 key として使える。
配信スキップ (lock 取得失敗 / channel disabled / dry_run) の件数¶
fields @timestamp, tenant, issueKey, message
| filter service = "deliver" and (message = "lock not acquired — skip" or message like /skip/)
| stats count() by tenant
スキップは正常動作だが、同一 tenant で頻発する場合は二重 invoke (Schedule 重複 / scan 救済) を疑う。
AI 生成 fallback の頻度 (deliver)¶
fields @timestamp, tenant, issueKey, error.message
| filter message = "AI generation failed — fallback to dumb content"
| sort @timestamp desc
| limit 50
Claude API 障害 / workspace 設定ミス / token 切れの早期発見用。
Cold start ratio¶
filter @type = "REPORT" or (level = "INFO" and message = "deliver invoked")
| stats sum(cold_start) as cold, count() as total by service
| display service, cold, total, cold * 100 / total as cold_pct
cold_start が異常に高い場合は memory_size / provisioned concurrency を検討する。
Backlog status 遷移失敗 (Issue #109 / #142)¶
fields @timestamp, tenant, issueKey, statusName, error.message
| filter message like /status update failed/ or message like /resolveStatusId/
| sort @timestamp desc
automedia実行済み / automediaエラー への自動遷移ができていないケースを検出する。発生時は project の status 名が運用と乖離していないか確認する (available_names attribute を見る)。
Defensive invalidate の頻度 (webhook-backlog, Issue #128)¶
fields @timestamp, tenant, issueKey
| filter message like /invalidating defensively/
| stats count() by tenant, bin(1h)
InvalidateDefensive Custom Metric (Alarm) と併用。短時間に集中するなら Backlog payload 仕様変更を疑う。
Secrets 鮮度 watch (secret-watch)¶
fields @timestamp, message
| filter service = "secret-watch" and level >= "WARN"
| sort @timestamp desc
| limit 100
secrets expiring critical (<= 7d) / secrets stale critical (>= 120d since update) 等の WARN/ERROR を直近で確認する。
1 配信の所要時間 (deliver invoke から配信完了まで)¶
fields @timestamp, message
| filter service = "deliver" and (message = "deliver invoked" or message = "content built" or message like /status updated/)
| sort @timestamp asc
content built (AI / template 確定) と status updated (configured 完了) の差分が配信 latency の主要部分。
配信失敗の自動リトライ (Issue #77)¶
deliver Lambda が SQS で 3 連続失敗すると deliver-dlq に到達する。deliver-retry Lambda が DLQ を event source として消費し、時間差で再度 deliver-queue に SendMessage する。
SQS:deliver-queue → deliver Lambda
↓ 3 SQS 受信失敗
SQS:deliver-dlq
↓ event source (batch=1)
deliver-retry Lambda
├─ dispatched marker 有り → drop (dedup)
├─ status == automediaエラー → drop (人手 review 待ち)
├─ retry_count < N → EventBridge Schedule at(now+delay) →
│ SQS:deliver-queue SendMessage
└─ retry_count == N → SNS publish (最終失敗通知)
| retry | delay (default) | 環境変数で上書き可 |
|---|---|---|
| 0 → 1 | 10 分 | RETRY_DELAYS_SEC=600,3600,21600 |
| 1 → 2 | 1 時間 | |
| 2 → 3 | 6 時間 | |
| 3 以降 | 最終失敗 → SNS |
最終失敗時の SNS 通知¶
- topic:
automedia-alarms(統合) - MessageAttributes:
type=deliver_final_failure,severity=high,tenant,issueKey - Message body は JSON (
tenant/issueKey/retry_count/first_failed_at/backlog_url/log_search_url) - Backlog にも「自動リトライ後も失敗しました。手動で status を automedia承認 に戻すことで再配信できます」コメントを残す
運営者の手介入 (最終失敗時)¶
- SNS / Backlog コメントで通知を受ける
log_search_urlまたは Logs Insights で原因を調査- 原因修正後、Backlog 課題の status を automedia承認 に戻すと webhook-backlog 経由で再配信される
Logs Insights クエリ: retry 集計¶
fields @timestamp, tenant, issueKey, message, retry_count, max_retries
| filter service = "deliver-retry"
| sort @timestamp desc
| limit 50
短期間に retry が集中する場合は upstream API (Backlog / LINE / HubSpot / Claude) 側の障害を疑う。
X-Ray (分散トレース)¶
全 Lambda は tracing_config { mode = "Active" } で X-Ray active tracing を有効化 (Issue #78 Phase 3, aws/tofu/lambda.tf)。AWSXRayDaemonWriteAccess を for_each で全 role に attach 済み。
subsegment 構成 (deliver, Issue #78 Phase 4)¶
aws/lambdas/deliver/src/xray.ts の captureClient / captureAsync で以下を subsegment 化する。X-Ray service map から各依存先が独立ノードとして見える。
| subsegment 名 | 対象 | 計装方法 |
|---|---|---|
DynamoDB |
acquireDeliverLock / releaseDeliverLock |
SDK v3 middleware (captureAWSv3Client) |
SecretsManager |
getProviderSecret |
SDK v3 middleware |
S3 |
loadProjectConfig / loadOptionalTemplate |
SDK v3 middleware |
Backlog.getIssue / Backlog.postComment / Backlog.fetchProjectStatuses / Backlog.patchIssueStatus |
Backlog API | 手動 (captureAsync) |
Claude.messages.create |
Claude Platform on AWS | 手動 (captureAsync) |
LINE.broadcast |
LINE Messaging API | 手動 (captureAsync) |
HubSpot.createBlogPost |
HubSpot CMS Blog API | 手動 (captureAsync) |
annotation (X-Ray 検索 key)¶
subsegment に addAnnotation 済みのため、X-Ray コンソールから filter expression で絞り込める:
annotation.issueKey = "BATO-15"— 課題 1 件のトレース全件annotation.tenant = "acme"— tenant 別annotation.model = "claude-sonnet-4-6"— モデル別annotation.projectKey = "BATO"— Backlog project 別
CloudWatch Logs ↔ X-Ray の突合¶
powertools logger は xray_trace_id attribute を全ログ行に付与する (active tracing 有効時は自動)。
- X-Ray コンソール:
xray_trace_idの値を「Trace ID」検索に入れる - Logs Insights:
filter xray_trace_id = "1-xxx-xxx"で同 trace の全 log を抽出
fetch ベース API が手動 capture な理由¶
Node 組み込み fetch (Node 20) は undici を使い node:https を経由しない。そのため captureHTTPsGlobal では自動補足できず、Backlog / LINE / HubSpot / Claude の各 API call は captureAsync('<service>.<op>', async (sub) => {...}) で個別にラップしている。
メトリクス¶
- 配信成功率(プロジェクト × チャネル × 1h)
- 配信遅延(schedule から send までの差分)
- API エラーレート(チャネル別)
- Queue 長 / 滞留時間
- GitHub テンプレ取得時間 / キャッシュヒット率
automedia/WebhookBacklog::InvalidateDefensive(Issue #128)automedia/Sync::ProjectConfigInvalid(Issue #113)automedia/SecretWatch::SecretExpiringCritical/SecretStale*(Issue #79 / #114)
アラート¶
| トリガ | 重要度 |
|---|---|
| 配信失敗連続 N 件 | High |
| トークン期限 7 日以内 | Medium |
| Queue 滞留 5 分超 | High |
| Scheduler 遅延 2 分超 | Medium |
| クリック計測 200/min 超(不正アクセスの疑い) | Low |
通知先¶
- 高重要: PagerDuty / Slack
#alerts-automedia - 中低: メール / Backlog コメント
運用ダッシュボード¶
- 当日の配信予定一覧
- 直近 24 時間の配信結果
- 失敗中の課題一覧
- トークン期限近接の一覧