LoginSignup
30

More than 5 years have passed since last update.

PHPのエラーを Google Analytics で記録する

Last updated at Posted at 2015-02-24

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のバージョンも設定してる)

こうしておくと、レポートでこういう感じに出る。

2015-02-24_235230.png

JavaScriptでもエラーを収集してたりすると、分かれてた方がいいかと思って。

ちなみに例外トラッキングは現時点ではカスタムレポートでないと見れないので、自分で作る必要がある。
好みによるけど、とりあえず以下のように作った。

2015-02-24_235625.png

アプリ名が最上層で、次にページ(エラーが起こったファイル)単位、その後にエラー内容が見られる形にしてる。
こんな感じで日本語のメッセージも問題なさそうだった。

2015-02-25_000506.png

表中の「クラッシュ」というのは関数内の「$fatal」で設定してあり、致命的なエラーの場合にフラグが立つようにしてるけど、致命的なのでそもそもcurl_exec()まで実行されないっぽい・・・?


勢いというか思いつきで書いたので、 curl_multi_exec() とか使ってもっと丁寧に作る必要がありそう。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30