Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 979
Sdlion Avatar asked Feb 15 '16 01:02

Sdlion


People also ask

How do I change the PHP INI error log?

Enable Error Logging in php. If you want to enable PHP error logging in individual files, add this code at the top of the PHP file. ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); Now, you must enable only one statement to parse the log errors in the php.

How do I create an error log?

The ini_set(“log_errors”, TRUE) command can be added to the php script to enable error logging in php. The ini_set('error_log', $log_file) command can be added to the php script to set the error logging file. Further error_log($error_message) function call can be used to log error message to the given file.

Where does Error_log write to?

The location of the error log file itself can be set manually in the php. ini file. On a Windows server, in IIS, it may be something like "'error_log = C:\log_files\php_errors. log'" in Linux it may be a value of "'/var/log/php_errors.

What is Error_log file?

The error_log() function sends an error message to a log, to a file, or to a mail account.


2 Answers

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.


  • Read more about set_error_handler
  • Read more about trigger_error
  • Read more about error types
like image 167
fusion3k Avatar answered Sep 19 '22 15:09

fusion3k


(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
like image 44
scott8035 Avatar answered Sep 16 '22 15:09

scott8035