Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT

Post on 16-Apr-2017

19.962 views 1 download

Transcript of Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT

Norikraで作るPHPの例外検知システム

YAPC::Asia Tokyo 2015 LTMasahiro Nagano @kazeburo

PHPはじめました 長年Perlをやってきましたが

PHPの例外を検出し通知するシステム

Catch PHP Exception and send it to Slack

STEP 1例外をログに記録する

Log the PHP Exception

Try-Catchtry { throw new MyAppException('Boofy');} catch (\Exception $e ) { $msg = json_encode(array( 'message' => $e->getMessage(), '_exception' => array( 'class' => get_class($e), 'message' => $e->getMessage(), 'trace' => .. ), )). "\n"; error_log($msg, 3, '/path/to/app_error_log');}

set_exception_handler

set_exception_handler(function($e) { $msg = decorate_exception($e); error_log($msg, 3, '/path/to/app_error_log');});

throw new MyAppException('Boofy');

try-catch外で発生した例外を補足

Catch the PHP Exception outside Try-Catch

set_error_handler

set_error_handler( function($severity, $msg, $file, $line){ throw new ErrorException( $msg, 0, $$severity, $file, $line ); });

PHPではエラーと例外は別物エラーを例外に変換

Convert Error to Exeption

これらの機能を使っても補足できない例外がある

(例)syntax error、存在しないメソッドの呼び出し

Can’t all Exception with these functions

error_reporting & error_log

error_reporting(E_ALL | E_STRICT);ini_set('error_log', '/path/to/php_log');

致命的エラーをログに記録php.ini でも書ける

Log Fatal Errors to the log file

Apache vhost ErrorLog

<VirtualHost *:80> ServerName api.example.com ErrorLog /path/to/error_log</VirtualHost>

php.ini にerror_logの設定がなくini_set 前にエラーが発生した場合

Apache ErrorLog

ErrorLog /var/log/httpd/error_log

Segmentation fault などApacheのworkerプロセスの不正終了

ここまでまとめ

PHP(mod_php)のエラーログは全部で4つのファイルに記録される

ここまでが長かった

弊社の環境では

STEP 2例外の集約から通知

構成

App

App

App SQLを投入

エラーログをfluentdでNorikraに送りリアルタイムに集計してSlackに通知

fluentd<source> type tail format json path /path/to/app_error_log tag nohostname.error_app_log</source>

<source> type tail format /^\[(?<time>[^\]]*)\] (?<message>.*)$/ time_format %d-%b-%Y %H:%M:%S path /path/to/php_log tag nohostname.apache_error</source>

<source> type tail format /^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])? \[client (?<client>[^\]]*)\] (?<message>.*?)(?:, referer: (?<referer>.*))?$/ path /path/to/error_log tag nohostname.apache_error</source>

<source> type tail format /^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])? \[client (?<client>[^\]]*)\] (?<message>.*?)(?:, referer: (?<referer>.*))?$/ path /var/log/httpd/error_log tag nohostname.apache_error</source>

<match nohostname.**> type record_reformer tag ${tag_suffix[1]} hostname ${hostname}</match>

<match {error_app_log,apache_error}> type forward <server> name cep host cep </server></match>

in_tail x 4

hostname追加

集約サーバへの送信

Norikra

•Norikra とはリアルタイムイベントストリームに対して SQL ライクな言語で処理できる super cool なプロダクト

Norikra QuerySELECT "alert-channel" as channel, "[..][" || hostname || "] Detect *" || CAST(COUNT(*), string) || "* PDOException in this 1min: ```" || message || "``` action: `" || COALESCE(NULLABLE(action),"-") || "`" AS msgFROM error_app_log.win:time_batch(1 min)WHERE exception.class = "PDOException" OR ( _exception.class = "ErrorException" AND _exception.message LIKE "PDOStatement%" )GROUP BY hostname, message, actionHAVING COUNT(*) > 0

表示例

まとめ• Norikra便利

• PHPのエラーログはつらい

• 扱いづらいPHPのエラー処理を適当にいなす - uzullaがブログ

• http://uzulla.hateblo.jp/entry/2013/12/20/041619

He is an awesomePHP guy!!!

おわり