こんにちは、UX開発部の橋口です。
Webサービスを開発するうえで、JavaScriptは絶対的に使われる技術だと思います。
みなさんもJavaScriptでエラーの調査をする際に、クライアントで実行されるためエラーの内容やどこで発生したかが分からなかったり、問い合わせ内容の再現ができず困ったことがあるのではないでしょうか?
解決の糸口を作るためには、クライアントサイドで発生したエラーに関する情報を収集してあげる必要があります。
JavaScriptのエラーログも収集できる著名な製品もありますが、クラウド環境への導入の場合には高額になってしまったり、独自に解析する場合でも、環境などを用意するのも大変ですし管理も大変です。
そこで、今回の記事はトレジャーデータサービス by IDCFにJavaScriptのエラーログを収集する方法について紹介します。
課題
JavaScriptのエラーを収集するにあたり問題になった2つの課題と解決策をご紹介します。
JavaScriptの性質
先ほども挙げましたが、JavaScriptはクライアントサイドで実行されるスクリプトです。
最新のブラウザであればエラー発生時にスタックトレースなど調査時に有益な情報が取得できますが、閲覧してくれる方全員が最新のブラウザを使ってくれるとは限りません。
そのため、古いバージョンであっても、擬似的なスタックトレースが取得できるstacktrace.jsを今回は使用します。
収集にあたって
stacktrace.jsにはJSON形式でエラーの情報をPOSTしてくれるメソッドがありますが、今まで収集してこなかったため実際にどのぐらいのエラーが集まってくるか見当がつかず、収集側にどれだけのキャパシティを用意すべきなのか想定もできません。
そのため、今回は、キャパシティー管理が不要なうえ※1に、後日の解析が容易なトレジャーデータサービス by IDCFにエラーを収集します。
※1 全体で1.5億件、月間1,000万件まではスタータープランに入ります。詳細はこちら
実際に収集してみよう
ここまでは、課題などを上げてきました。
ここからは、実際にトレジャーデータサービス by IDCFへ収集する為の準備をしましょう。
DBの設定
まずはじめに、データベースや、テーブルを作成します。
左上から二番目のDatabasesアイコンをクリックします。
新しいデータベースを作成します。
新しいテーブルを作成します。
writeKeyの取得
javascriptには書き込み専用のwriteKeyをセットします。 しかし、データベースやテーブルごとに制限をかけることができないので専用のアカウントを作成するのがオススメです。 writeKeyはMy profileから確認できます。
画面左下のアイコンをクリックしMy profileをクリックします。
API Keysをクリックします。
認証をするとAPIキーが表示されるのでwriteKeyを控えます。ない場合はCREATEを押して作成しましょう。
サンプルコード
必要な情報が揃ったので実際にエラーログをトレジャーデータサービス by IDCFに送信して見ましょう。
今回はイベントリスナに window.onerror
を用いますが、 window.addEventListener
を使用することも可能です。
また、スタックトレースの部分を改行で連結しています。
今回はサンプルのためhtmlファイルに直接記載していますが、必要に応じてJavaScriptファイルにすることをおすすめします。
<html> <head> <!-- Treasure Data --> <script type="text/javascript"> !function(t,e){if(void 0===e[t]){e[t]=function(){e[t].clients.push(this),this._init=[Array.prototype.slice.call(arguments)]},e[t].clients=[];for(var r=function(t){return function(){return this["_"+t]=this["_"+t]||[],this["_"+t].push(Array.prototype.slice.call(arguments)),this}},s=["addRecord","set","trackEvent","trackPageview","trackClicks","ready","fetchGlobalID","fetchUserSegments"],a=0;a<s.length;a++){var c=s[a];e[t].prototype[c]=r(c)}var n=document.createElement("script");n.type="text/javascript",n.async=!0,n.src=("https:"===document.location.protocol?"https:":"http:")+"//cdn.treasuredata.com/sdk/1.9.2/td.min.js";var i=document.getElementsByTagName("script")[0];i.parentNode.insertBefore(n,i)}}("Treasure",this); </script> <!-- StackTrace.JS --> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/stacktrace.js/2.0.0/stacktrace.min.js"> <!-- javascript error collector --> <script type="text/javascript"> var td = new Treasure({ host: 'idcf.in.treasuredata.com', // 書き込み専用のwriteKeyを記載します writeKey: 'YOUR_WRITE_ONLY_APIKEY_IS_HERE', // データベース名を記載します database: 'DATABASE_NAME' }); // Enable cross-domain tracking // td.set('$global', 'td_global_id', 'td_global_id'); var callback = function(stackframes) { return stackframes.map(function(sf) { return sf.toString(); }).join('\n'); }; var errback = function() { return null; }; window.onerror = function(msg, file, line, col, error) { // callback is called with an Array[StackFrame] var stack = StackTrace.fromError(error).then(callback).catch(errback); stack.then(function(stringifiedStack) { td.set({ msg: msg, url: file, line: line, column: col || null, stack: stringifiedStack }); // テーブル名を記載します td.trackEvent('TABLE_NAME'); }); }; </script> </head> <body> sample </body> </html>
実際にエラーログを収集すると、次のようにDB内のテーブルに格納されます。
さいごに
IDCFクラウドでもJavaScriptエラーログを取得中です。
どの画面でどの行でどのようなエラーが発生しているかデータベースに記録されるため、リリース後に新規にエラーが発生していないか、定常的に顧客のUXを低下させるような不具合が発生していないかの確認に役立てています。
改善にとても役立つのでみなさんの作成されるWebアプリケーションでもエラーログの継続的な収集と解析をお勧めいたします。