Terraformを使ったNewRelicのアラート設定

## やること

今回は、`newrelic_nrql_alert_condition`を設定していきます。
特に詰まりそうな、部分を重点的に説明できるといいかなと思います。

## ソースコード

簡単にterraform module化しているので、必要なかたはソースからダウンロードしてみてください。

- https://github.com/fnaoto/sample-terraform/tree/master/newrelic_alert

## terraform provider について

参考URL

- https://registry.terraform.io/providers/newrelic/newrelic/latest/docs

NewRelicのprodiverでは、以下が必須の設定項目になっています。

- account_id (アカウントID)
    - `NEW_RELIC_ACCOUNT_ID` の環境変数で代用可能
- api_key (APIキー)
    - `NEW_RELIC_API_KEY` の環境変数で代用可能
    - NRAKから始まるキー
- region (リージョン)
    - `US` もしくは `EU`

```terraform

provider "newrelic" {
  account_id = "<Your Account ID>"
  api_key = "<Your Personal API Key>"    # usually prefixed with 'NRAK'
  region = "US"                          # Valid regions are US and EU
}
```

`newrelic_insights_event` 以外は、基本的に api_key の設定でOKです。

## newrelic_nrql_alert_condition について

これを使うと、NRQLを使って確認できるメトリクスであれば、ほとんどのアラートを設定できます。
ちなみに、 `newrelic_alert_policy` (policy) に対して、複数のアラートを設定可能です。

これの何が嬉しいかというと、
今までAPMとInfrastructureのアラートを設定するときは、 `newrelic_alert_condition` と `newrelic_infra_alert_condition ` 2つのresourceを使い分けないといけなかったのですが、これがあれば `1つのresouceで設定可能` になります。
さらに、NRQLをそのまま使用できるので、既存のダッシュボードの設定から、`View query`でNRQLをコピーしてそのまま貼り付けるだけでアラートをコード化できます。

![スクリーンショット 2020-12-19 21.53.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259386/189a63e0-613b-9d60-f235-45ab651ef384.png)


参考URL

- https://registry.terraform.io/providers/newrelic/newrelic/latest/docs/resources/nrql_alert_condition

### APMのSlow Queryアラートを設定してみる

where句に設定可能な、演算子(NRQL)はこちらを参照ください

- https://docs.newrelic.co.jp/docs/query-your-data/nrql-new-relic-query-language/get-started/nrql-syntax-clauses-functions#sel-where


newrelic_nrql_alert_condition の設定項目で難しいところ

- `type`
    - おそらく、どの条件でアラート設定をするかというもの
        - 参考: https://docs.newrelic.com/docs/alerts/new-relic-alerts/defining-conditions
    - baseline と outliner も設定可能だけど、通常のアラートであれば static でOK
- `value_function`
    - single_value と sum が設定可能、たぶんメトリクスの集計方法
        - single_value だと合計値じゃないので、`メトリクスがないところはデータなし`となる
- `violation_time_limit`
    - この時間を設定していると、アラート発生から時間経過後になにかしらの自動設定が可能
    - ちなみに、TerraformのドキュメントにはDEPRECATEDと書いてあったけど、`violation_time_limit_seconds`のほうが、terraform plan時にDEPRECATEDになっていた、ドキュメントのミス？？
- nrql -> `evaluation_offset`
    - よくわからないけど、3分にしておく
    - グラフを表示するときに使う設定？
    - NRQLで設定したクエリの開始時間？？
- critical/warning -> `threshold_occurrences`
    - 閾値を超えた値の評価方法
        - `all`: すべての値が閾値を超えている
        - `at_least_once`: 1つ以上の値が閾値を超えている
    - value_functionでsumを選んだ場合は、 `at_least_once`のみ設定可能

moduleのサンプル

```terraform:modules/nrql_alert/main.tf

resource "newrelic_alert_policy" "alert" {
  name = var.name
}

resource "newrelic_nrql_alert_condition" "alert" {
  policy_id            = newrelic_alert_policy.alert.id
  type                 = var.type
  name                 = var.name
  value_function       = var.value_function
  violation_time_limit = var.violation_time_limit

  nrql {
    query             = var.query
    evaluation_offset = var.evaluation_offset
  }

  dynamic "critical" {
    for_each = var.critical
    content {
      operator              = critical.value.operator
      threshold             = critical.value.threshold
      threshold_duration    = critical.value.threshold_duration
      threshold_occurrences = critical.value.threshold_occurrences
    }
  }

  dynamic "warning" {
    for_each = var.warning
    content {
      operator              = warning.value.operator
      threshold             = warning.value.threshold
      threshold_duration    = warning.value.threshold_duration
      threshold_occurrences = warning.value.threshold_occurrences
    }
  }
}
```

```terraform:modules/nrql_alert/variables.tf

variable "name" {
  type = string
}

variable "type" {
  type = string
}

variable "value_function" {
  type = string
}

variable "violation_time_limit" {
  type    = string
  default = "ONE_HOUR"
}

variable "query" {
  type = string
}

variable "evaluation_offset" {
  type    = number
  default = 3
}

variable "critical" {
  type = list(any)
}

variable "warning" {
  type    = list(any)
  default = []
}
```

module呼び出し側のサンプル

```terraform:newrelic_alert/nrql_alert_mysql_slow_query.tf

module "nrql_alert_mysql_slow_query" {
  source         = "../modules/newrelic/nrql_alert"
  name           = "${local.name} slow query"
  type           = "static"
  value_function = "sum"

# query
## ヒアドキュメントを使うとわかりやすいので、おすすめ
## apm_app_name はAPMの設定で付けている名前に変更する

  query = <<EOF
   SELECT average(apm.service.datastore.operation.duration) * 1000 
   FROM Metric 
   WHERE  (appName = '${var.apm_app_name}') 
   AND ((metricTimesliceName = 'Datastore/operation/MySQL/show' AND datastoreType = 'MySQL')) 
   FACET `metricTimesliceName`
EOF

# critical
## operator は閾値の下か上かどちらでアラートを出すか
## threshold_duration は秒単位なので、 300secで5分

  critical = [
    {
      operator              = "above"
      threshold             = 10
      threshold_duration    = 300
      threshold_occurrences = "at_least_once"
    }
  ]

  warning = [
    {
      operator              = "above"
      threshold             = 5
      threshold_duration    = 300
      threshold_occurrences = "at_least_once"
    }
  ]
}

```

### アラートの確認方法

`Alerts & AI` -> `Polices` -> `newrelic-sample-default slow query`

![スクリーンショット 2020-12-19 22.02.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259386/1e28b569-f35c-9f64-f69c-53afae5d05dd.png)

ちゃんと`Preview chart`が表示されていることを確認

![スクリーンショット 2020-12-19 21.45.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259386/5b49a2fb-c32f-be89-0cca-647d7a506e21.png)

`Thresholds`の設定値も確認

![スクリーンショット 2020-12-19 22.32.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259386/3cb7709a-ecdd-3246-4a80-93562743aba6.png)