Terraform で Newrelic の通知設定をする

世の中にまるで 3rd party 資料がなかったので書いておく。

参考文献

* [Provider: New Relic - Terraform](https://www.terraform.io/docs/providers/newrelic/index.html)
* [GitHub - terraform-providers/terraform-provider-newrelic: Terraform New Relic provider](https://github.com/terraform-providers/terraform-provider-newrelic)
* [REST API calls for New Relic Alerts
](https://docs.newrelic.com/docs/alerts/rest-api-alerts/new-relic-alerts-rest-api/rest-api-calls-new-relic-alerts)
* [New Relic API Explorer](https://rpm.newrelic.com/api/explore/alerts_policies/list)

# Provider (api_key) の設定

```
provider "newrelic" {
  api_key = xxxx
}
```

New Relic には API Key が３種類ある:

1. **REST API Key**: Account Settings > API Keys から作成
1. **User API Key**: Account Settings > Users and Roles > User > (例: sonots) > API Keys から作成
1. **Admin User's API Key**: Account Settings > API Keys > Admin user's API Key > ユーザの右側のリフレッシュボタンを押して作成。ユーザに Owner または Admin 権限が必要。

Admin User's API Key だけが通知設定に利用可能。

所感: 個人に紐づけないといけないのは厳しい


# アラートチャンネルの作成

## メール

メールは[サンプル](https://www.terraform.io/docs/providers/newrelic/r/alert_channel.html)に書いてある

```
resource "newrelic_alert_channel" "foo" {
  name = "foo"
  type = "email"

  configuration = {
    recipients              = "foo@example.com"
    include_json_attachment = "1"
  }
}
```

## Slack

サンプルも何もなく、どう設定すれば良いのかわからなかったがソースコードを読み解くと次のようにするとできた。

```
resource "newrelic_alert_channel" "slack" {
  name = "foo"
  type = "slack"

  configuration = {
    channel = "channel" # Channel Name
    url     = "https://hooks.slack.com/services/xxxx/xxxx/xxx" # Webhook URL
  }
}
```

困った事に terraform apply をすると毎回 destory & create が行われる。[issues/130](https://github.com/terraform-providers/terraform-provider-newrelic/issues/130) を投げたところ、configuration は秘匿情報を含むフィールドであるため、変更があったのかどうかが分からなくなって毎回作り直しになってしまっているらしい。

解決策としては「気にしない」か、

```
resource "newrelic_alert_channel" "slack" {
  name = "foo"
  type = "slack"

  configuration = {
    channel = "channel" # Channel Name
    url     = "https://hooks.slack.com/services/xxxx/xxxx/xxx" # Webhook URL
  }

  # As default, type "slack" always recreates the resource. This is because `configuration` has
  # sensitive data in it and doesn't know when it changes. Ignore its changes.
  # ref. https://github.com/terraform-providers/terraform-provider-newrelic/issues/130
  # NOTE: When you need to modify `configuration`, comment out below temporarily. 
  lifecycle {
    ignore_changes = ["configuration"]
  }
}
```

のようにして configuration の変更検知をしないようにするか、とのこと。
変更検知をしないようにすると、もちろん、変更をしても反映されなくなってしまうので注意。

## その他

ソースコードを読むと configuration の設定項目のキー名がわかる

https://github.com/terraform-providers/terraform-provider-newrelic/blob/master/newrelic/resource_newrelic_alert_channel.go

値は...勘...?

# APM の監視設定

[newrelic_alert_condition](https://www.terraform.io/docs/providers/newrelic/r/alert_condition.html) というのが APM の監視設定。
INFRASTRUCTURE など他のメトリクスは別のAPIになるので、設定方法も別のようだ。罠い...

```
resource "newrelic_alert_condition" "foo" {
  policy_id = "${newrelic_alert_policy.foo.id}"

  name        = "foo"
  type        = "apm_app_metric"
  entities    = ["${data.newrelic_application.app.id}"]
  metric      = "apdex"
  runbook_url = "https://www.example.com"

  term {
    duration      = 5
    operator      = "below"
    priority      = "critical"
    threshold     = "0.75"
    time_function = "all"
  }
}
```

entities とは...? となるわけだが、これは Application ID か Browser ID。ref. [Manage entities in Alerts conditions
](https://docs.newrelic.com/docs/alerts/rest-api-alerts/new-relic-alerts-rest-api/manage-entities-alerts-conditions)

Application ID は Web UI からなら、APM > Applications > Name から選択すると URL が `https://rpm.newrelic.com/accounts/アカウントID/applications/アプリケーションID` のようになるのでそこからわかる。

API からなら

```
curl -X GET 'https://api.newrelic.com/v2/applications.json' -H 'X-Api-Key: xxxx'
```

のようにすると

```
{
  "applications": [
    {
      "id": アプリケーションID,
```

のように出力されるのでそこからわかる。

# INFRASTRUCUTRE の監視設定

newrelic_alert_condition ではなく [newrelic_infra_alert_condition](https://www.terraform.io/docs/providers/newrelic/r/infra_alert_condition.html) を使う。
FYI: INFRASTRUCTURE は買収した会社の機能が元になっているのでAPIも別というのが現況らしい

```
resource "newrelic_infra_alert_condition" "cpu" {
  policy_id = "${newrelic_alert_policy.alert.id}"

  name       = "High cpu usage"
  type       = "infra_metric"
  event      = "SystemSample"
  select     = "cpuPercent"
  comparison = "above"
  where      = "(`hostname` LIKE '%${var.env}%')"

  critical {
    duration      = 3     # min
    value         = 70    # %
    time_function = "all"
  }
}
```

event...? select...? となるわけだが、`event` に指定できる値は [Default Infrastructure events](https://docs.newrelic.com/docs/infrastructure/new-relic-infrastructure/data-instrumentation/default-infrastructure-events) のページに載っている。

`select` に指定できる値はイベントのリンクをクリックした先のページで参照することができる。たとえば `SystemSample` の場合は https://docs.newrelic.com/attribute-dictionary?attribute_name=&events_tids%5B%5D=8407