📜 ⬆️ ⬇️

Lagger - error handling and debugging in PHP with eyes closed

image

This tool was first introduced to the general public in 2008 at the Highload.ru conference, after which it was thoroughly optimized and refined. About what kind of animal it is and how it is convenient to use read on.

Article format


At first there was a desire to write a detailed guide-specification on the entire functionality of the library. Then I realized that it would be much clearer and clearer to cite simple examples of its practical use, and then briefly list the main features. So…
')

On fingers examples


config.php - all constants are fictional, any coincidences are random. It is important to understand that these constants are given for example only. Ideally, you can prescribe everything without them at all (see further lagger_init.php ).

<?php

define( 'SKIPER_DIR' , LOGS_DIR . DIRECTORY_SEPARATOR . 'skip' );
define( 'SKIPER_EXPIRE' , 60 * 60 * 24);
define( 'SKIPER_HASH_TEMPLATE' , '{file}{line}' );

define( 'ERRORS_STDOUT' , true );
define( 'ERRORS_STDOUT_TAGS' , null );
define( 'ERRORS_STDOUT_TEMPLATE' , '<div><font color="red"><b>{type}:</b> {message}<br /><em>{file} [{line}]</em></font></div>' );

define( 'ERRORS_LOGING' , true );
define( 'ERRORS_LOGING_TAGS' , 'warning,fatal' );
define( 'ERRORS_LOGING_FILEPATH' , LOGS_DIR . DIRECTORY_SEPARATOR . 'errors_log.htm' );
define( 'ERRORS_LOGING_LIMIT_SIZE' , 500000);
define( 'ERRORS_LOGING_LIMIT_DAYS' , 180);
define( 'ERRORS_LOGING_TEMPLATE' , '{date} {time} <a href="http://{host}{uri}">http://{host}{uri}</a><br /><b>{type}</b>: {message|htmlentities}<br />{file} [{line}]<hr />' );

define( 'ERRORS_SMS' , false ); // TODO: check /library/SmsSender.php before enable it
define( 'ERRORS_SMS_TAGS' , 'warning,fatal' );
define( 'ERRORS_SMS_TO' , '79627271169,79218550471' );
define( 'ERRORS_SMS_FROM' , 'MyWebSite' );
define( 'ERRORS_SMS_MESSAGE' , 'Web site error, check log at {date} {time}' );

define( 'ERRORS_EMAIL' , true ); // TODO: must be TRUE on production server
define( 'ERRORS_EMAIL_TAGS' , 'warning,fatal' );
define( 'ERRORS_EMAIL_FROM' , 'Lagger <lagger@mywebsite.com>' );
define( 'ERRORS_EMAIL_TO' , 'Jack Johnson <jack_admin@gmail.com>, mike_developer@gmail.com' );
define( 'ERRORS_EMAIL_SUBJECT' , '{type} error in my website' );
define( 'ERRORS_EMAIL_MESSAGE' , "Date: {date} {time}\nURL: http://{host}{uri}\nError({type}): {message}\nSource: {file} [{line}]\n\nPOST:\n{post}\n\nSESSION:\n{session}" );

define( 'DEBUG_STDOUT' , true );
define( 'DEBUG_STDOUT_TAGS' , 'test,high' );
define( 'DEBUG_STDOUT_TEMPLATE' , '<div><font color="green">{message|htmlentities}</font></div>' );

define( 'DEBUG_LOGING' , true );
define( 'DEBUG_LOGING_TAGS' , 'sql' );
define( 'DEBUG_LOGING_FILEPATH' , LOGS_DIR . DIRECTORY_SEPARATOR . 'debug_sql_log.csv' );
define( 'DEBUG_LOGING_LIMIT_SIZE' , 500000);
define( 'DEBUG_LOGING_LIMIT_DAYS' , 7);
define( 'DEBUG_LOGING_TEMPLATE' , "{date} {time};{process_id|csv};{microtime|csv};{tags|csv};{message|trim|csv}\n" );

* This source code was highlighted with Source Code Highlighter .

lagger_init.php - direct configuration of Lagger handlers. In this case, from the constants of the config, although it is possible without them.
<?php

/**************************************************************
REGISTER EVENTSPACE VARS
**************************************************************/

$laggerES = new Lagger_Eventspace();
$laggerES->registerReference( 'host' , $_SERVER[ 'HTTP_HOST' ]);
$laggerES->registerReference( 'uri' , $_SERVER[ 'REQUEST_URI' ]);
$laggerES->registerReference( 'post' , $_POST);
$laggerES->registerReference( 'session' , $_SESSION); // Session must be already started!
$laggerES->registerCallback( 'date' , 'date' , array( 'Ym-d' ));
$laggerES->registerCallback( 'time' , 'date' , array( 'H:i:s' ));
$laggerES->registerCallback( 'microtime' , 'microtime' , array( true ));
$laggerES->registerVar( 'session_id' , session_id());
$laggerES->registerVar( 'process_id' , substr(md5(mt_rand()), 25));

/**************************************************************
REGISTER EVENTSPACE MODIFIERS
**************************************************************/

function varToStringLine($ value ) {
return str_replace(array( "\r\n" , "\r" , "\n" ), ' ' , is_scalar($ value ) ? $ value : var_export($ value , 1));
}
$laggerES->registerModifier( 'line' , 'varToStringLine' );

function quoteCSV($ string ) {
return varToStringLine(str_replace( ';' , '\\;' , $ string ));
}
$laggerES->registerModifier( 'csv' , 'quoteCSV' );

/**************************************************************
SKIPER
**************************************************************/

$daylySkiper = new Lagger_Skiper($laggerES, SKIPER_HASH_TEMPLATE, SKIPER_EXPIRE, new Lagger_ExpireList(SKIPER_DIR, '.dayly_skiper' ));

/**************************************************************
LAGGER INTERNAL ERRORS AND EXCEPTIONS HANDLING
**************************************************************/

$emailAction = new Lagger_Action_Mail(ERRORS_EMAIL_FROM, ERRORS_EMAIL_TO, ERRORS_EMAIL_SUBJECT, ERRORS_EMAIL_MESSAGE);
$emailAction->setSkiper($daylySkiper, 'errors_email' );

Lagger_Handler::addInternalErrorAction($emailAction);

/**************************************************************
DEBUG HANDLER
**************************************************************/

$debug = new Lagger_Handler_Debug($laggerES);

function toDebug($message, $tags = null ) {
if (isset($GLOBALS[ 'debug' ])) {
$GLOBALS[ 'debug' ]->handle($message, $tags);
}
}

if (DEBUG_STDOUT) {
// Allows to rewrite DEBUG_STDOUT_TAGS. Try $_GET['__debug'] = 'high' or $_GET['__debug'] = ''
$debugTagger = new Lagger_Tagger( '__debug' );

$debug->addAction( new Lagger_Action_Print(DEBUG_STDOUT_TEMPLATE), DEBUG_STDOUT_TAGS, $debugTagger);
$debug->addAction( new Lagger_Action_FirePhp( '{message}' , '{tags}' , FirePHP::INFO), DEBUG_STDOUT_TAGS, $debugTagger);
}
if (DEBUG_LOGING) {
$debug->addAction( new Lagger_Action_FileLog(DEBUG_LOGING_TEMPLATE, DEBUG_LOGING_FILEPATH, DEBUG_LOGING_LIMIT_SIZE, DEBUG_LOGING_LIMIT_DAYS), DEBUG_LOGING_TAGS);
}

// Just for fun in windows servers it will speak the text :)
if (stristr(PHP_OS, 'win' ) !== false ) {
$debug->addAction( new Lagger_Action_WinSpeak( '{message}' , 100), 'speak' );
}

/**************************************************************
ERRORS AND EXCEPTIONS HANDLERS
**************************************************************/

$errors = new Lagger_Handler_Errors($laggerES);
$exceptions = new Lagger_Handler_Exceptions($laggerES);

if (ERRORS_STDOUT) {
$printAction = new Lagger_Action_Print(ERRORS_STDOUT_TEMPLATE, false );
$errors->addAction($printAction);
$exceptions->addAction($printAction);

$errorsFirePhpAction = new Lagger_Action_FirePhp( '{message} {file} [{line}]' , '{type}' , FirePHP::ERROR);
$errors->addAction($errorsFirePhpAction);
$exceptions->addAction($errorsFirePhpAction);
}

if (ERRORS_LOGING) {
$logAction = new Lagger_Action_FileLog(ERRORS_LOGING_TEMPLATE, ERRORS_LOGING_FILEPATH, ERRORS_LOGING_LIMIT_SIZE, ERRORS_LOGING_LIMIT_DAYS);
$errors->addAction($logAction, ERRORS_LOGING_TAGS);
$exceptions->addAction($logAction, ERRORS_LOGING_TAGS);
}

if (ERRORS_SMS) {
$smsAction = new Lagger_Action_Sms(ERRORS_SMS_FROM, ERRORS_SMS_TO, ERRORS_SMS_MESSAGE, true );
$smsAction->setSkiper($daylySkiper, 'errors_sms' );
$errors->addAction($smsAction, ERRORS_SMS_TAGS);
$exceptions->addAction($smsAction, ERRORS_SMS_TAGS);
}

if (ERRORS_EMAIL) {
$errors->addAction($emailAction, ERRORS_EMAIL_TAGS);
$exceptions->addAction($emailAction, ERRORS_EMAIL_TAGS);
}



Those.


There are 3 classes of event handlers:
There are 7 classes of custom actions:
There are many other things:

100% Open Source


Download the latest version
Examples instead of documentation
SVN / trunk
Google Code Project Page

Anyone wishing to join the project - very happy :)
Thank you all for your constructive criticism and feedback!

Source: https://habr.com/ru/post/74162/


All Articles