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

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

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

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

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

YAPC::Asia Tokyo 2015 LTMasahiro Nagano @kazeburo

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

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

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

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

Catch PHP Exception and send it to Slack

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

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

Log the PHP Exception

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

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');}

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

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

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

set_error_handler

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

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

Convert Error to Exeption

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

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

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

Can’t all Exception with these functions

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

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

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

Apache vhost ErrorLog

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

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

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

Apache ErrorLog

ErrorLog /var/log/httpd/error_log

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

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

ここまでまとめ

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

ここまでが長かった

弊社の環境では

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

STEP 2例外の集約から通知

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

構成

App

App

App SQLを投入

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

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

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追加

集約サーバへの送信

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

Norikra

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

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

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

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

表示例

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

まとめ• Norikra便利

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

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

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

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

He is an awesomePHP guy!!!

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

おわり