Rails アプリのエラーを Sentry で管理する & Slack 通知する

## 概要

* Sentry の使い方と Slack 通知の方法をまとめました
* Rails を例にしていますが、Sentry 自体の説明については他の言語でも流用できるのではないかと思います

## 導入

基本的には Gem (sentry-raven) を入れて、initializers などで設定するだけです。詳細な手順は下記を参照してください。

* https://qiita.com/mikaji/items/74fac3be5e1235e0b762
* https://docs.sentry.io/clients/ruby/integrations/rails/

接続先情報は、Sentry の Project 画面 -> Settings -> SDK Setup -> Client Keys (DSN) に載っています。

## 基本的な使い方

上記の設定をするだけで、Uncaught なエラーを全て Sentry に自動通知してくれます。

しかし Rails アプリの場合、エラーを `rescue_from` などでキャッチして、アプリ独自のエラー画面を表示したりするケースが多いはずです。その場合、エラー処理の中で `Raven.capture_exception(exception)` を使って明示的に通知する必要があります。

```ruby
class ApplicationController < ActionController::Base
  rescue_from Exception do |exception|
    Raven.capture_exception(exception)
    # アプリ独自のエラー画面を表示したりする
  end
  ...
end
```

## Context の活用

Sentry はデフォルトでも基本的な情報を付加してくれますが、Context を使うとさらに便利になります。

Context とは、ざっくり言うと、Key / Value を渡すとそれが Sentry のエラーレポート画面に表示されるというような機能です。やることは、このあと紹介する Context 設定用メソッドを、`Raven.capture_exception` の実行前に実行するだけです。

Context にはいくつか種類があり、適切なものを選んで使うことで最大のメリットが得られるようになっています。

### 公式ドキュメント

* https://docs.sentry.io/clients/ruby/context/
* https://docs.sentry.io/enriching-error-data/context/

### User Context

ユーザー情報を扱うのに便利な Context です。

```ruby
Raven.user_context(id: current_user&.id, username: current_user&.name)
```

下記の Key は特別な意味があります。逆に、 **これらの Key を設定しないとあまり恩恵が得られない** ので注意してください。

* id
* username
* email
* ip_address

User Context を設定すると、エラーレポート画面にユーザー情報が表示されるようになったり、ユーザーごとのエラー遭遇率を見れるようになったりします。特に email を設定すると Gravaters からアイコンを引っ張ってきたり、個別にメッセージを送ったりできるようです。

<img width="1102" alt="user_context_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/66421/27efb9fa-f84c-0791-e452-d657cc9a56b6.png">

### Tags Context

エラーをタグ管理したいときに便利な Context です。

```ruby
Raven.tags_context(event_name: @event&.name)
```

シンプルに、与えた Key / Value がタグとして付与されて、表示 & 検索ができるようになります。

<img width="592" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/66421/9dfab4b8-5989-ff29-fb12-9b5e9f5646b7.png">

### Extra Context

その他雑多な情報をとりあえずエラーに付与したいときに便利な Context です。

```ruby
Raven.extra_context(params: params.to_unsafe_h, url: request.url)
```

雑にハッシュを丸ごと投げても大丈夫ですが、200KB が上限になっているので気をつけてください。

<img width="612" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/66421/e57e2965-d1f4-0619-bb06-a4d41960b9b0.png">


どんな情報でも、最悪この Context が受け皿になってくれます。ただし、ユーザー情報を扱うなら User Context を、検索用の情報を作りたいなら Tags Context を使った方が、上述のようなメリットが得られるのでおすすめです。こちらが情報を正しく構造化して渡せば、Sentry 側がそれを活かしたメリットを生み出してくれるようになっています。気持ちがいいですね。

## Slack 通知

まず（Project ではなく）Organization の Settings に行き、Integrations から Slack を Install します。

<img width="1059" alt="slack_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/66421/cbce686e-b6c3-1fb1-985c-280d5bc288df.png">

次に Project の Settings -> Alerts -> Rules -> (+) New Alert Rule から、通知ポリシーを設定します。 `Take these actions` から Slack っぽい内容のものを選び、チャンネル名などを設定すれば OK です。

### おすすめ設定

* `show tags *** in notification` は `environment` を選んでおくと、Slack 上でどの環境のエラーかがパッとわかるようになります。
* 通知条件は下記がおすすめです。その種のエラーが初めて起きた時と、Resolve or Ignore したはずのエラーが再発した時に、1度だけ通知が飛びます。
    * Every time `any` of these conditions are met:
        * `An issue is first seen`
        * `An issue changes state from resolved to unresolved`
        * `An issue changes state from ignored to unresolved`

<img width="410" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/66421/e67c1711-8ffd-e68e-0e9a-63413841353d.png">