Sdlion
Sdlion

Reputation: 543

Edit prepended date format in error_log

PHP 5.6

There's some way to define the format of the date shown when error_log is used?

I'm using it to log messages and errors from a certain script. It seems that set_error_handler won't handle all error messages.

In some examples out there, people prepend the date with date directly on the arguments of error_log. Using that approach would led me to a repeated date string in my log file.

I want to output an ISO formatted local date time, but the date prepended on CLI (php -f script.php) and Apache that I get with

ini_set('log_errors', 1);
ini_set('error_log', 'file.log');
error_log('Test');

Is something like this:

[14-Feb-2016 18:07:31 America/Mexico_City] Test

Noting that in most code examples the date format usually don't include the timezone. And that if I run it from the console I don't get the date prepended:

$ php -r 'error_log("Test");'
Test

Timezone is not set in either runtime or php.ini, but is correctly represented. I get this behavior on a php5.6.18 package and a compiled from source php5.6.13. On the production server the script is being run through CLI, there's no apache installation.

Solution

It seems that the date that is shown with error_log is not customizable. Going forward with set_error_handler as suggested by @fusion3k I put together this error handler that will format the date, message and error levels with a more computer/human friendly format

// set_trigger_error only accepts E_USER_ constants values
define('ERROR', 256);   // Before E_USER_ERROR
define('INFO',  512);   // Before E_USER_WARNING
define('DEBUG', 1024);  // Before E_USER_NOTICE

function errorHandler ($errType, $errStr, $errFile, $errLine, $errContext) {
    $displayErrors = ini_get( 'display_errors' );
    $logErrors     = ini_get( 'log_errors' );
    $errorLog      = ini_get( 'error_log' );

    if( $displayErrors ) echo $errStr.PHP_EOL;

    if( $logErrors ) {
        $line = "";
        switch ($errType) {
            case DEBUG: 
                $type = 'DEBUG'; 
                break;
            case INFO: 
                $type = 'INFO'; 
                break;
            case ERROR: 
                $type = 'ERROR'; 
                $line = " (Line:".$errLine.")";
                break;
            default: 
                $type = 'WARN'; 
                $line = " (Line:".$errLine.")";
                break;
        }
        $message = date('Y-m-d H:i:sO').";".$type.";".$errStr.$line;
        file_put_contents($errorLog, $message.PHP_EOL, FILE_APPEND);
    }
}

set_error_handler('errorHandler');

error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', 'test.log');

trigger_error('Test', DEBUG);

Output

2016-02-15 14:20:05-0600;DEBUG;Test

Upvotes: 15

Views: 10240

Answers (2)

scott8035
scott8035

Reputation: 460

(I copied answer from @Sdlion into its own answer so we can vote on it)

It seems that the date that is shown with error_log is not customizable. Going forward with set_error_handler as suggested by @fusion3k I put together this error handler that will format the date, message and error levels with a more computer/human friendly format

// set_trigger_error only accepts E_USER_ constants values
define('ERROR', 256);   // Before E_USER_ERROR
define('INFO',  512);   // Before E_USER_WARNING
define('DEBUG', 1024);  // Before E_USER_NOTICE

function errorHandler ($errType, $errStr, $errFile, $errLine, $errContext) {
    $displayErrors = ini_get( 'display_errors' );
    $logErrors     = ini_get( 'log_errors' );
    $errorLog      = ini_get( 'error_log' );

    if( $displayErrors ) echo $errStr.PHP_EOL;

    if( $logErrors ) {
        $line = "";
        switch ($errType) {
            case DEBUG: 
                $type = 'DEBUG'; 
                break;
            case INFO: 
                $type = 'INFO'; 
                break;
            case ERROR: 
                $type = 'ERROR'; 
                $line = " (Line:".$errLine.")";
                break;
            default: 
                $type = 'WARN'; 
                $line = " (Line:".$errLine.")";
                break;
        }
        $message = date('Y-m-d H:i:sO').";".$type.";".$errStr.$line;
        file_put_contents($errorLog, $message.PHP_EOL, FILE_APPEND);
    }
}

set_error_handler('errorHandler');

error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', 'test.log');

trigger_error('Test', DEBUG);

Output

2016-02-15 14:20:05-0600;DEBUG;Test

Upvotes: 2

fusion3k
fusion3k

Reputation: 11689

If you use your custom error log file, you can simply prepend your preferred date format to log message.

If you use standard Apache log file, you can't modify log format through php.

You have instead to modify entire Apache error log format in httpd.conf through LogFormat keyword: replace existent format with your desired format.

Here you can found complete syntax guide for LogFormat.

Edit:

After your last comment, I have searched through internet and I have performed some tests, then I realize that my previous answer is not correct: there is no way to modify error_log() behavior in php. In my case (I have Apache installed), error_log() function outputs Apache log format even on custom log file (defined through ini_set('error_log')).

In your case, I think that php use the OS log format (Are you sure that you don't have Apache installed, even if you don't use it?).

Alternative: trigger_error()

You can set your completely customizable error log format using trigger_error() — in conjunction with set_error_handler() — instead of error_log():

function myErrorHandler( $errType, $errStr, $errFile, $errLine, $errContext )
{
    $displayErrors = ini_get( 'display_errors' );
    $logErrors     = ini_get( 'log_errors' );
    $errorLog      = ini_get( 'error_log' );

    if( $displayErrors ) echo $errStr.PHP_EOL;

    if( $logErrors )
    {
        $message = sprintf( '[%s] %s (%s, %s)', date('d-m H:i'), $errStr, $errFile, $errLine );
        file_put_contents( $errorLog, $message.PHP_EOL, FILE_APPEND );
    }
}

ini_set( 'log_errors', 1 );
ini_set( 'error_log', 'file.log' );

set_error_handler( 'myErrorHandler' );
trigger_error( 'Test' );

In the above example, trigger_error will append to file.log a line like this one:

[15-02 09:43] Test (Script/File/Path.php, 12)

Setting error_handler all system errors are processed by custom function. To simulate a system error, you have to use trigger_error() instead of error_log().

To maximize customization, you can pass to trigger_error additional parameter error_type:

trigger_error( 'Test', E_WARNING );

will produce a Warning level error; default error_type value is E_USER_NOTICE. The error type is the first parameter ($errType) in custom function, so inside the custom error handler function you can modify the behavior depending of error type.

In my above simple example, the custom function also process some ini directives, so you can use ini_set in conjunction with set_error_handler. Please note that you can change the variables names of custom function parameters, but not the order, because this is defined by internal php error system.

If you decide to use set_error_handler(), read careful the documentation to understand the behavior and exceptions.


Upvotes: 6

Related Questions