GoogleアナリティクスでJavascriptエラー収集 という投稿を見て、PHP(サーバーサイド)でもできるかも?と、軽い思いつきで作ってみた。
以前、ガラケーでもGoogle Analyticsに記録するとかをちょこっとやったことがあったので、それを応用した感じ。
まずは単体の関数。
function exception_ga($errno, $msg, $file, $line){
$types = array(
E_ERROR => 'ERROR',
E_WARNING => 'WARNING',
E_PARSE => 'PARSE',
E_NOTICE => 'NOTICE',
E_CORE_ERROR => 'FATAL',
E_CORE_WARNING => 'CORE_WARNING',
E_COMPILE_ERROR => 'COMPILE_ERROR',
E_COMPILE_WARNING => 'COMPILE_WARNING',
E_USER_ERROR => 'USER_ERROR',
E_USER_WARNING => 'USER_WARNING',
E_USER_NOTICE => 'USER_NOTICE',
E_STRICT => 'STRICT',
E_RECOVERABLE_ERROR => 'RECOVERABLE_ERROR',
E_DEPRECATED => 'DEPRECATED',
E_USER_DEPRECATED => 'USER_DEPRECATED',
);
$fatal = false;
if (
$errno === E_ERROR
|| $errno === E_CORE_ERROR
|| $errno === E_COMPILE_ERROR
|| $errno === E_RECOVERABLE_ERROR
) {
$fatal = true;
}
$description = $types[$errno].' - Line '.$line.': '.$msg;
$url = 'https://www.google-analytics.com/collect';
$data = array(
'v' => 1,
'ul' => 'ja',
'de' => 'UTF-8',
'tid' => 'UA-XXXXXXXX-X',
'dh' => (!empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n')),
'dl' => $file,
'dr' => (!empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null),
'an' => 'PHP', // 本来はアプリ名用データ
'av' => PHP_VERSION, // 本来はアプリバージョン用データ
't' => 'exception',
'exd' => $description,
'exf' => $fatal,
);
// http://php.net/manual/ja/function.uniqid.php#94959
$data['cid'] = sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0fff ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
if(!empty($_SERVER['HTTP_USER_AGENT'])){
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
$res = curl_exec($ch);
curl_close($ch);
var_dump($data);
}
それで、上記の関数を set_error_handler
とかで呼び出して情報を渡す。
// 普通のエラーのとき
set_error_handler(function ($errno, $msg, $file, $line) {
if (!(error_reporting() & $errno)) {
return;
}
exception_ga($errno, $msg, $file, $line);
});
// Fatalエラーとかも取るとき?(やってみたけど動かなかった)
register_shutdown_function(function() {
if ($error = error_get_last()) {
exception_ga($error['type'], $error['message'], $error['file'], $error['line']);
}
});
Google Analyticsの例外トラッキングを使ってるけど、少し特殊な設定として「アプリ名(キー名がan
)」に「PHP」を設定してる。
(念のためアプリバージョン av
でPHPのバージョンも設定してる)
こうしておくと、レポートでこういう感じに出る。
JavaScriptでもエラーを収集してたりすると、分かれてた方がいいかと思って。
ちなみに例外トラッキングは現時点ではカスタムレポートでないと見れないので、自分で作る必要がある。
好みによるけど、とりあえず以下のように作った。
アプリ名が最上層で、次にページ(エラーが起こったファイル)単位、その後にエラー内容が見られる形にしてる。
こんな感じで日本語のメッセージも問題なさそうだった。
表中の「クラッシュ」というのは関数内の「$fatal
」で設定してあり、致命的なエラーの場合にフラグが立つようにしてるけど、致命的なのでそもそもcurl_exec()
まで実行されないっぽい・・・?
勢いというか思いつきで書いたので、 curl_multi_exec()
とか使ってもっと丁寧に作る必要がありそう。