Sentryでイベントログ収集をしよう！ - Vue.js編 -

# はじめに
実際にシステムを運用する上でログからエラーの発生を検知して，原因を調べ，修正する時があるよね．．．
ログ収集では，AWSのCloudWatchなど使ったりすると思うのですが，今回はSentryというイベントログ収集ツールを紹介します．
何か間違ったことを書いていたら教えてくださると幸いです．

# 概要
- Sentryはいろんな言語で利用できる
- アプリケーションの利用ユーザのブラウザやOS情報を取得できる
- アプリケーションの利用ユーザの行動記録を収集できる
- ユーザ情報も設定すると，どのユーザがエラーは発生させたのか分かる
- 実際にJavaScriptのフレームワークVue.jsでSentryを利用する方法の紹介

# Sentryとは
Sentryはイベントログを収集するツールです．
https://sentry.io/welcome/
これを利用することで，エラーの原因の特定を補助してくれます！！！

## 利用できるプラットフォーム
現状利用できるプラットフォームは以下のような感じです．
JavaScriptで言うと，ReactやAngularなどメジャーなフレームワークで利用できます．
その他にも様々なプログラミング言語でも利用できるらしいです．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/ebe17841-79cc-4cc0-b4a1-01fb265cda1a.png)

## 出来ること
ログを収集するのですが，その中で出来ることは，以下のものがあります．

1. ユーザがサイトにアクセスしたブラウザやパソコンの情報を取得
2. ユーザ情報や付加情報を付けることが出来る
3. ユーザの行動記録を取得

※ここでのユーザはサイトにアクセスしている人のことを指します．

### 1. ユーザがサイトにアクセスしたブラウザやパソコンの情報を取得
これは，HTTPのHeaderにあるUser-Agentからデータを整形し，以下のように教えてくれます．
IEのバージョンで動かないJavaScriptのコードがあったりするので，エラーログの場合は，解決するための情報として利用できると思います．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/ddcb3265-8134-23a1-6de9-cdd44417d7b1.png)

### 2. ユーザ情報や付加情報を付けることが出来る
`USER`の部分の`ID`と`Email`と`Username`のユーザ情報を設定することができます．
また，`ADDITIONAL DATA`として，付加情報を自由に設定することができたりします．
これらの情報を設定することで，エラーログやワーニングログが発生した原因を発見することができたりするかもしれません．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/bcbc8752-2b6f-bfce-bf24-51652a96b200.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/2cce0029-d0f6-1d9f-1b01-4694a19d4e49.png)

### 3. ユーザの行動記録を取得
これは，以下のように，ユーザのページ遷移，クリック，XMLHttpRequestなどを時系列的に記録したものです．
こうすることで，ユーザがどのようなページ遷移を行い，どこをクリックしたのかがわかります．
行動記録があると，エラーが発生した場合の再現がしやすくなり，バグであれば素早く原因が発見できるかもしれません．
また，VuexやReduxを使っていた場合，ここにActionが発生した時の渡されるデータだったり，現在のStateなどの情報を記録するようにすると，エラーログやワーニングログの原因究明に役立つかもしれません．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/528814d6-d9b2-1b68-f6a2-d81d7f31d79c.png)

# Sentryの利用
## 今回の環境
以下の環境で行いました．

- Vue.js
    - 2.5.2

## プロジェクトの作成
今回はVueプロジェクトで利用して見るため，Vueを選択し，プロジェクト名を入力して作成しましょう．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/177aa55d-d6aa-0837-de14-207d046363fe.png)

## 導入
プロジェクト作成すると，CDNやnpmなどの導入方法があるので，説明通りすると良いです．
今回はnpmで利用した場合で紹介します．
まず初めにraven-jsをinstallします．
その後，Vue.jsのmain.js?でRaven Pluginを入れます．
これで導入自体は終わりです．

```bash:commandline
npm install raven-js --save
```

```javascript:main.js
import Vue from 'vue';
import Raven from 'raven-js';
import RavenVue from 'raven-js/plugins/vue';

Raven
    .config('https://xxxxx@sentry.io/xxxxx')
    .addPlugin(RavenVue, Vue)
    .install();
```

## ユーザ情報の付与
次はログを収集する上で誰がそのイベントログを発生させたのかを分かるように，ログにユーザ情報を付与しましょう．
以下のような感じです．

```javascript
import Raven from 'raven-js'

Raven.setUserContext({
  id: 12,
  username: 'ferretdayo',
  email: 'ferretdayo@example.com'
})
```

こうすることで，イベントログを発生させたユーザをSentryから見ることができます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/88e7f301-6b9a-4f35-dc28-4ce09b25a55f.png)

また，ユーザ情報(id, username, email, ip_address)以外に付与させたい！！という場合には，`setExtraContext`を利用することで，別途情報付け加えることができます．

```javascript
import Raven from 'raven-js'

Raven.setExtraContext({
  user_type: 0
})
```

Sentryには`ADDITIONAL DATA`の項目に表示されます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/b8ad7aa0-4561-d1a7-58ab-7d0ef4f514dd.png)

ここの詳細はドキュメントの[Capturing the User](https://docs.sentry.io/learn/context/#capturing-the-user)に書いています．

## ログの収集
実際にイベントログを発火させる方法について説明します．
イベントログを発生させるには`captureMessage`を利用します．

```javascript
import Raven from 'raven-js'

Raven.captureMessage('info log', {
    tags: { category: 'test' },
    level: 'info'
})
```
そうすると以下のようにイベントログがSentry側で表示されます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/9ae4aa9d-518a-e94a-5ecd-fe2e8eba572e.png)
選択すると，ログのメッセージである *info log* と`captureMessage`のオプションで追加したtagsが`TAGS`部分に追加されていることが確認できます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/bac22c1b-38c0-0cd2-bc3c-c72ddb99d578.png)

ログにもExceptionのようなもの関しては`captureMessage`ではなく，`captureException`が用意されています．その場合は，以下のようにします．

```javascript
import Raven from 'raven-js'

try {
    // do something
} catch (error) {
    Raven.captureException(error)
}
```

### captureMessageとcaptureExceptionのオプション
オプションには，以下の4つあります．

|     key|        備考|
|--------|-----------|
|   level|イベントログに関するログレベル．デフォルトは`error`．ログレベルには，`info`, `warning`, `error`の種類がある|
|  logger|イベントログを記録するために使用されたロガーの名前．Vue.jsでの利用言語はJavaScriptなので，デフォルトは`javascript`|
|    tags|イベントログに割り当てるタグ|
|   extra|イベントログに関連付ける任意のデータ|

詳細は公式ドキュメントの[Passing Additional Data](https://docs.sentry.io/clients/javascript/usage/#passing-additional-data)に書いています．

## ユーザの行動の記録
イベントログには，ユーザの行動をデフォルトで記録していますが，任意の行動を付け加えたいかもしれません．
その時には，`captureBreadcrumb`を利用します．

```javascript
import Raven from 'raven-js'

Raven.captureBreadcrumb({
  message: 'Item added to shopping cart',
  category: 'action',
  data: {
     isbn: 'xxx-yyyyyyy',
     amount: '2'
  }
})
```

この`captureBreadcrumb`が呼ばれると，ユーザの行動記録に以下の項目が追加されます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/d760459d-08b6-ba22-9efb-58dcb4c4c5eb.png)

Vuexを利用している場合は，その都度関連しているStateの情報や，Actions，MutationsのPayloadを行動記録として追加するとより詳細な履歴になると思います．

# その他

## 機密情報の扱い
ログに情報を付与する際，passwordやtokenなど機密性の高い情報は表示されないほうが良いと思います．
デフォルトでSentryでは，Data ScrubberオプションがONになっており，以下のデータはフィルターされ，データスクランブルされます．

- クレジットカードを含むように見える値
- 以下のKeyが含まれる場合
    - password
    - secret
    - passwd
    - api_key
    - apikey
    - access_token
    - auth_token
    - credentials
    - mysql_pwd
    - stripetoken
    - card[number]
- プロジェクトの設定で追加された値と一致するKey

以下のように，間違ってpasswordをログに含めてしまった場合でも表示されないようになっています．
これは，`setExtraContext`にpassword
のKeyを持つ値を入れた場合です．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/0c5e206a-6813-7ea6-9b46-620e6725132c.png)

## ユーザによるエラーレポート
HTTPの500などのエラーが起きた際，以下のようにユーザからのフィードバックを得る機能があります．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/68729f08-6df0-24ae-9e93-5223aff93cd3.png)

これは，1行`showReportDialog`を追加することで利用できます．

```javascript
import Raven from 'raven-js'

try {
   // todo something
} catch (err) {
   Raven.captureException(err)
   Raven.showReportDialog()
}
```

メールが送られると，実際にメールが来ます．また，Sentryのダッシュボードにも以下のように表示されます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116983/3302195a-921d-d05c-8af0-b29cb033efc6.png)

# まとめ
今回はフロントエンドでのイベントログの収集でSentryを利用する方法について紹介しました．
ログを発生するのに数行必要だったりするので，冗長かもしれませんが，ログを収集した時にユーザの行動記録もついてくるので，バグの発見には役立つのではないかと思います．
よければ利用してみてください．