経緯
サービスを利用してるエンドユーザーから「うまく動作しない」という連絡があったときに、
クライアント依存の問題だとフロントエンドのエラーログを見ないと推測が難しいケースがある。
なので、ログを集めるコードを作った。
導入対象となったサイト
仕事で運用してるレガシーな環境。超レガシー。
7年ぐらい前に構築されたサイトなので、jqueryバリバリ。
もちろんパッケージ管理もされてない。
方針
本当はSentryを使いたかったけど、前述の通りパッケージ管理もされておらず、
導入コストが大きそうなので自前で作成。
基本方針は、
- ライブラリに依存しないようにする
- nativeのjavascriptで処理するようにする
- エラーが発生したらhttp通信でサーバー側にエラー情報を送ってDB格納
- ハンドリングされてるエラーはとりあえず想定なし。例外エラーだけを対象
的な感じ。
コード
javascript
var gSendLog = function(log){
//XMLHttpRequestオブジェクトの生成
var request = new XMLHttpRequest();
//イベントハンドラ設定
request.onload = function (event) {
if (request.readyState === 4) {
if (request.status === 200) {
console.log(request.statusText); // success
} else {
console.log(request.statusText); // error
}
}
};
request.onerror = function (event) {
console.log(event.type); // error
};
//open("request method", URL, true or false))
request.open("get", "/top/api/asp/get_jslog.asp?" + log, true);
XMLHttpRequest.responseType = 'html';
//Call
request.send(null);
}
var gSetLogger = function(){
window.onerror = function (msg, file, line, column, err) {
/*
msg: error message
file: file path
line: row number
column: column number
err: error object
console.log(msg + ':' + file + ':' + line + ':' + column);
*/
var strLog = "msg=" + encodeURIComponent(msg)
strLog += "&file=" + encodeURIComponent(file)
strLog += "&line=" + encodeURIComponent(line)
strLog += "&col=" + encodeURIComponent(column)
strLog += "&stack=" + encodeURIComponent(err.stack)
strLog += "&ua=" + encodeURIComponent(window.navigator.userAgent)
strLog += "&platform=" + encodeURIComponent(navigator.platform)
strLog += "&referrer=" + encodeURIComponent(document.referrer)
gSendLog(strLog);
};
}
//Call
gSetLogger();
gSetLogでonerrorをグローバルでキャッチしてエラー情報作成したら、
gSendLogで、ajaxでAPIコールしてサーバー側でDBに記録。
ちょっと手をぬいてGETで送っちゃってますが、jsonにしてNoSQLに
入れる方がログ管理的にはいい気がします。
あと、ここには書いてませんが、サーバー側でアクセス元IPを取得して、一緒に記録するようにしてます。
備考
ハンドリングされてるエラーの箇所で「gSendLog」をコールすれば同じようにDB記録できます。