DatadogでフロントエンドのJSエラーを収集してサービス改善

この記事は、[弁護士ドットコム Advent Calendar 2019 - Qiita](https://qiita.com/advent-calendar/2019/bengo4com) の11日目の記事です。

# 要約
- DatadogでブラウザーのJSエラーの収集を始めた。
- 1日に発生するJSエラー数を、1/4まで削減することができた。
- エラー発生検知が、数時間から15分以内になった。

# サービスの課題

以前、[Sentry](https://sentry.io/welcome/)を弁護士ドットコムサービスが稼働しているowned k8sの片隅で運用していたが、運用負荷が高く、廃止。 :cry:
サーバーサイドの監視は、きちんとやっていましたが、フロントの監視がおざなりになってました。

一部のページでは、Google Tag Manager経由で自作エラー検知スクリプトを埋め込んでいました。しかし、エラーを、Google Analyticsにイベント通知しているが、情報が少なく、エラーが追えませんでした。

結果、JSやフロントエンドのエラーは検知できませんでした。

フロントで障害が起きていても気づけません。 :scream:
お問い合わせがきてから、バグ発覚。 :fire:

# なぜDatadogを採用したのか

弁護士ドットコムでは全社的にDatadogを導入してサービスの監視を行っています。
そのため、運用を一元化するため、可能ならばDatadogに寄せたいという意図はありました。:thinking:

ただ、Sentry有料版なども含めて検討しましたが、下記の点からDatadogに軍配が上がりました。
導入当時は、private ベータ版だったのが懸念でしたが、先日GAになりました。安心ですね。

- JSライブラリを読み込むだけなので、導入が簡単
- 費用が安い
  - 変動費: $2.5 (1 million log / month)
  - 固定費: $1.52
- マネージドサービスなので、運用が簡単
- 綺麗なダッシュボードやモニター機能が充実している

# 導入方法

##1. クライアントトークンの発行

メニューの`Integrations`から、`APIs`を選択し、設定画面に入り、クライアントトークンを発行します。
セキュリティ上の理由から、API キーを使用することはできません。

![client_tokens.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/8fb10df1-7ced-f4ca-ca84-a2dcf472641f.png)


## 2. jsロガーの構築

全ページに、下記設定を行うことで、全てのエラーログが、Datadogに送信されます。

```html
<html>
  <head>
    <title>Example to send logs to Datadog</title>
    <script type="text/javascript" src="https://www.datadoghq-browser-agent.com/datadog-logs-us.js"></script>
    <script>
      // クライアントトークンを設定します
      DD_LOGS.init({
        clientToken: <CLIENT_TOKEN>,
        // false に設定すると、js およびコンソールエラーの自動収集がオフに
        forwardErrorsToLogs: true,
      });
      // 送信するログレベルを設定
      DD_LOGS.logger.setLevel('error')


      // オプション
      // グローバルメタデータ属性を追加します。一度に 1 つの属性を追加できます
      DD_LOGS.addLoggerGlobalContext(<META_KEY>, <META_VALUE>);
    </script>
    ...
  </head>
...
</html>
```

送信されたエラーは、綺麗なグラフで可視化されます。

![スクリーンショット 2019-12-10 13.58.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/019c057a-1c8b-2bcf-a67b-239f376a8c43.png)

ブラウザの種別、バージョン等は、自動でDatadogが収集します。
エラーをクリックすることで、より詳しい情報が見れます。

![スクリーンショット 2019-12-10 14.00.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/8d234abf-3f94-aac7-3cc6-ba949e05551f.png)


## 3.カスタムログの送信

JSでtry-catchしている箇所は、エラーが送信できないので、明示的に送る必要があります。

```javascript

DD_LOGS.logger.log(<MESSAGE>, <JSON_ATTRIBUTES>, <STATUS>)
```

## 4.一定数以上のJSエラー発生で、slackへアラートをあげる

メニューの`Monitors`から、`new Moniter+`で、アラート設定画面に入り、Logsを選択します。

![スクリーンショット 2019-12-10 12.29.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/db67dc07-f96d-d215-7e62-bc0d85ca2ab4.png)

下記の様に、`Source:browser`を指定します。
アラートする閾値を設定し、通知するチャンネルを指定します。
普段のエラー数のグラフを見ながら、閾値が設定できるので、わかりやすいです。
通知メッセージで、`is_alert`などで条件を設定した場合、アラート種別にあった文章が表示されます。

![スクリーンショット 2019-12-10 12.14.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/abc0ba73-8300-4b8d-cc84-43d08fe0f794.png)

下記のように通知されます。
灰色の枠のところには詳しい条件式が表示され、一番多く発生しているエラーログが表示されます。

ある程度は、エラー文言によりパターンで分類してくれます。

<img width="720" alt="スクリーンショット 2019-12-10 13.52.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/0628fc74-708e-c595-01bc-661969f7a99f.png">

# 運用で困ったこと

## 修正できないエラーで、アラートがあがる

アラートをあげる条件式で、細かいクエリーを指定できます。
エラー内容を部分一致で設定し、除外しました。

<img width="1335" alt="スクリーンショット 2019-12-10 14.22.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/8a8e5772-4505-8077-31c0-949ad9419014.png">

## 中国から来たbotがアラートを大量にあげる

ログが流し込まれる時に、パイプラインという処理があります。
ここで設定した条件に合致するログは取り込まないといった設定が可能です。
ログに流す、割合を指定することができるので、一部だけログに流すような細かいコントロールもできます。

![スクリーンショット 2019-12-10 14.26.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525723/798866d2-2c2b-ed49-9f48-faf2f6c799fd.png)

# 何が改善したか

## 1日に発生するエラー数を、1/4まで削減

エラーログを集め始めたら、既存のページで、毎日5万以上のエラーが出ていることがわかりました。
業務の合間に、少しずつ直して、1.2万程度までエラーを削減できました。

ブラウザや、ネットワーク起因のもあり、全て対応するのはなかなか難しいです。
しかしながら、少しずつ対応策を検討し、修正を進めております。

## エラー発生検知が数時間から、10分以内

エラーの発生検知を自動でできるようになったので、障害対応が迅速になりました。
今までは、お問い合わせが来るまで気づかなかったこともあったので、激的な短縮です。

# まとめ

ブラウザでのエラーは、サーバーのエラーと違い、ユーザー側で発生しているので、エラーを集めるのは大変という印象があります。

しかし、昨今SPAの需要が多くなり、それとともにJSの役割は大きくなっています。
そのため、エラー検知をして、対処していくことが大切だと思います。

弊社も、弁護士が利用するページは、一部reactで構築されています。
キャッシュ起因のJSのエラーにより、メニューバーが表示されないなどのバグが発生したこともあります。

いくらテストを頑張って書いたとしても、全てのエラーを事前に防ぐのは、難しいです。
だからこそ、エラーの収集と監視を強化して、堅牢なサービスを目指して、改善していきたいと思います。

# おまけ

こちらでもDatadogを取り上げているので、ぜひ読んでみてください。

[Datadog の監視設定を Terraform で管理する - 弁護士ドットコム Advent Calendar 2019 6日目](https://qiita.com/t2ynkmr/items/96a1e005c4c609fe10b0)

Datadog のロゴの犬の名前は、「[Bits](https://www.datadoghq.com/ja/about/press/resources/)」 らしいですよ。