839の日記

業務とは関係ない趣味の話を書くブログです。

react, reduxで出たエラーをいい感じにsentryでトラッキングする

昔jsのエラーをsentryに送っていたとき特に何も考えずに送っていました。 その結果minifyされたコードを見せられ、ここでエラーが出たよ!と言われるもののさっぱり原因がわからない、という状況に困っていました。

今回はreactで起きたエラーをいい感じにsentryに送る方法について記事を書いています。 バックエンドはrailsで、webpacker(4.0.2)を使ってフロントでreactを使っています。

ひとまず、webpackerの設定を少しだけ変えてproductionでもmapファイルを作成するようにします。

process.env.NODE_ENV = process.env.NODE_ENV || 'production'

const environment = require('./environment')

module.exports = environment.toWebpackConfig()
module.exports.devtool = 'source-map'

config/webpack/production.jsmodule.exports.devtool = 'source-map'にします。 もともとは nosources-nource-map が指定されていると思いますが、sentryで快適にエラートラッキングをするために必要です。 変更をすると assets:precompile 時にmapファイルがいい感じに吐かれて、sentry上でエラートラッキングをするときにちゃんとコードが追えます。

f:id:husq:20190429231243p:plain
mapファイルがあるsentryのエラートラッキング

とりあえずこれをするだけでもだいぶエラートラッキングが快適になりました。 とはいえ、mapファイルがインターネットに全公開されているとminifyされているコードが全部読まれてしまいます。 chromeのdevtoolとかでファイルを見に行くといい感じにmappingしてくれるのでバレバレです。

自分の場合は別にあんまり困らないのですが、一応以下のようにnginxの設定をしてsentryだけmapファイルにアクセスできるようにしています。

location ^~ /packs/ {
  gzip_static on;

  set $response_file 1;
  if ($request_uri ~ 'map$') {
    set $response_file 0;
  }
  if ($remote_addr = 'xxx.xx.xxx.xxx') {
    set $response_file 1;
  }
  if ($response_file = '0') {
    return 403;
  }
}

自分は自前でsentryを立てているので、sentryサーバのIPを $remote_addr に指定して他の人が見れないようにしています。 SaaSのsentryを使っている場合はAPI経由でjsとmapファイルを送ることで見れるようにできるようですが、自分は確認していないです。 webpackerにどう組み込むかも考える必要がありますが、webpackではwebpack-sentry-pluginというpluginがあるようです。

次にreduxの部分をよしなに見れるようにします。 今回はraven-for-reduxというnpmを利用しています。 下記のように書いてセットすることができますが、時間が経つと変わるかもしれないのでリンク先からREADMEを読むことをおすすめします。

import Raven from "raven-js"; // Or, you might already have this as `window.Raven`.
import { createStore, applyMiddleware } from "redux";
import createRavenMiddleware from "raven-for-redux";

import { reducer } from "./my_reducer";

Raven.config("<YOUR_DSN>").install();

export default createStore(
    reducer,
    applyMiddleware(
        // Middlewares, like `redux-thunk` that intercept or emit actions should
        // precede `raven-for-redux`.
        createRavenMiddleware(Raven, {
            // Optionally pass some options here.
        })
    )
);

これを行うことでreduxのactionの推移やエラーが発生したときのstateが見れるようになります。

f:id:husq:20190429231410p:plainf:id:husq:20190429231434p:plain
redux action, state

action推移が見れるだけでも嬉しいですが、stateまで見れるのでかなり便利です。 サーバ側でいうとそのときのDB snapshotが送れるような感覚なので、かなりデバッグに役に立ちます。

ただ、業務要件だとactionやstateを秘密保護的な観点でそのままsentryに送れないケースがあるかもしれません。 その場合は似たようなものを自作するのが良いと思います。 リポジトリを見ると割と薄い実装だったので会社であればメンテナンスしても良いかな?と感じました。

ただ @sentry/browser の5系では raven-for-redux がちゃんと動かないバグがあるようです。 なので、対応されるのを待つか、4系を使ってみてください(自分は現在 4.6.1 を利用しています)。