Stackdriver Logging を Datadog Logs に転送して Terraform で通知設定する

[Stackdriverでエラーログ通知](https://qiita.com/sonots/items/64b9ee1e2d39eaf57ac9)を設定してみたものの、ヒットした行がSlack通知に表示されないため使いづらかった。

Datadog Logsの通知ならエラーログがSlack通知に表示できる。そこで、Stackdriver Logging に入ってきているログを Datadog Logs に転送して、エラー通知をしてみた記録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/0bdd2239-0e20-4331-5fc3-951ef6e3c53e.png)

cite: https://docs.datadoghq.com/monitors/monitor_types/log/#notifications-and-log-samples

# Stackdriver Logging の Datadog Logs への転送

See https://docs.datadoghq.com/integrations/google_cloud_platform/#log-collection

1. Create a new Cloud Pub/Sub.
1. Validate your Datadog domain so that logs can be pushed from GCP to Datadog.
1. Setup the Pub/Sub to forward logs to Datadog.
1. Configure exports from Stackdriver logs to the Pub/Sub.

このうち 2. のステップの Cloud Search Console と [Domain Verification](https://console.cloud.google.com/apis/credentials/domainverification) の設定は手動でやらざるを得なかったので、 https://docs.datadoghq.com/integrations/google_cloud_platform/#validate-the-datadog-domain のドキュメントを参考に手動で実施する。


1, 3, 4 の Pub/Sub および Cloud Logging Sink の設定は Terraform 化できたので、.tf ファイルを示しておく。例えば k8s_pod のログを Datadog Logs に転送する設定は以下のようになる。

```
resource "google_pubsub_topic" "export-logs-to-datadog" {
  name = "export-logs-to-datadog"
}

resource "google_pubsub_subscription" "export-logs-to-datadog" {
  name  = "export-logs-to-datadog"
  topic = "${google_pubsub_topic.export-logs-to-datadog.name}"

  push_config {
    # NOTE: Need to do domain verification. See https://docs.datadoghq.com/integrations/google_cloud_platform/#validate-the-datadog-domain
    push_endpoint = "https://gcp-intake.logs.datadoghq.com/v1/input/${var.datadog_api_key}"
  }

  depends_on = ["google_pubsub_topic.export-logs-to-datadog"]
}

# Tips: If you have a configuration error, the web console https://console.cloud.google.com/logs/exports?project=<project_id>
# will show a warning after waiting 10 sec at there.
resource "google_logging_project_sink" "export-logs-to-datadog" {
  name        = "export-logs-to-datadog"
  destination = "pubsub.googleapis.com/projects/${var.project}/topics/${google_pubsub_topic.export-logs-to-datadog.name}"

  # Add more resource.type with OR if you want to get more
  filter                 = "resource.type=\"k8s_pod\""
  unique_writer_identity = true

  depends_on = ["google_pubsub_topic.export-logs-to-datadog"]
}

resource "google_pubsub_topic_iam_member" "export-logs-to-datadog" {
  topic  = "${google_pubsub_topic.export-logs-to-datadog.name}"
  role   = "roles/pubsub.publisher"
  member = "${google_logging_project_sink.export-logs-to-datadog.writer_identity}"

  depends_on = [
    "google_pubsub_topic.export-logs-to-datadog",
    "google_logging_project_sink.export-logs-to-datadog",
  ]
}
```

`https://console.cloud.google.com/logs/exports?project=<your_project_id>` から Stackdriver Logging Sink の画面を開いて 10 sec ぐらい待って warning が出なければ成功しているはず。

Datadog > Logs > Search の画面から Source を gcp.k8s.pod にしてログが入ってきていることが確認できればOK。

# Datadog Logs の Pipeline の設定

この状態で Datadog Logs の通知設定をしても Message が通知に含まれなかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/c368869d-c628-4e4b-207c-4f272035f2c3.png)

Datadog で特別な意味合いを持つ Message フィールドを別途設定してあげる必要があるようだ。

https://docs.datadoghq.com/logs/processing/#edit-reserved-attributes

を参考に Logs > Configuration > Pipeline から Reserved attributes mapping を設定して、JSON payload のログ通知に含めたい文字列を持つフィールド `data.jsonPayload.message` を `Message` 属性に指定。よくよく確認すると timestamp, status も同様に mapping する必要があったので設定。

これは terraform では設定不可能だったので手動で設定。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/cc460822-1ba8-76d8-a1a6-3536e8beaff9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9641/f153e9d4-f576-cdb3-f63e-8611f0f6ddff.png)


# Datadog Logs の通知設定

こちらは terraform で設定できた。

```
# NOTE: You can check the query is configured on the view page such as https://app.datadoghq.com/monitors/<monitor_id>
# But, it is not shown on the edit page such as https://app.datadoghq.com/monitors#<monitor_id>/edit.
# It looks the field of edit page is `queryString` rather than `query`, but terraform does not support to configure it.
resource "datadog_monitor" "warning_k8s_pod_logging" {
  name    = "(${var.env}) WARNING K8s Pod Logging"
  type    = "log alert"
  message = "Too many warnings from k8s pod logs. Notify: @slack-dev_test_notice"
  query   = "logs(\"source:gcp.k8s.pod project_id:${var.gcp_project_id} status:warn\").index(\"main\").rollup(\"count\").last(\"5m\") > 10" # Minimum is 5m (min)

  thresholds {
    critical = 10.0
  }

  notify_no_data    = false
  no_data_timeframe = 2
  new_host_delay    = 300
  renotify_interval = 0
  timeout_h         = 0
  include_tags      = true
  notify_audit      = false
  tags              = ["env:${var.env}", "project_id:${var.gcp_project_id}"]

  enable_logs_sample = true # Include a sample of 10 logs in the alert notification
}
```

これで Datadog Logs を経由して Slack 通知でき、Slack 通知に10行までだが、ログ行を含めることができるようになった。

ただし、以下の点は問題になりそうだった。

* 集計間隔が最小でも 5 min (stackdriver は 1min が可能)
* (stackdriver でできるような)時間平均を閾値にするような機能がなく合計のみ
* (stackdriver でできるような)連続してX回閾値を超えたらアラートを飛ばすよう機能がない
* ~~Datadog Monitor から編集画面に飛ぶと query に何も設定されていないように見える~~ 対応された模様？
 
# おわりに

ところどころ手作業が必要だったが、Slack通知にログ行を含めることができるようになった。
Stackdriver 通知がログ行を含めるオプションを持ってくれていれば、こんな面倒はいらないのになぁ(ぼそり