Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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() とか使ってもっと丁寧に作る必要がありそう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away