Изменить формат даты в начале в error_log

PHP 5.6

Есть ли способ определить формат даты, отображаемой при использовании error_log?

Я использую его для регистрации сообщений и ошибок из определенного скрипта. Похоже, что set_error_handler не будет обрабатывать все сообщения об ошибках.

В некоторых примерах люди добавляют дату с date непосредственно к аргументам error_log. Использование этого подхода привело бы меня к повторяющейся строке даты в моем файле журнала.

Я хочу вывести локальное время даты в формате ISO, но дата добавлена ​​​​в CLI (php -f script.php) и Apache, которые я получаю с помощью

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

Что-то вроде этого:

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

Обратите внимание, что в большинстве примеров кода формат даты обычно не включает часовой пояс. И что, если я запущу его с консоли, я не добавлю дату:

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

Часовой пояс не установлен ни во время выполнения, ни в php.ini, но представлен правильно. Я получаю такое поведение в пакете php5.6.18 и скомпилированном из исходного кода php5. 6.13. На рабочем сервере скрипт запускается через CLI, установка apache не предусмотрена.

Решение

Кажется, что дату, отображаемую с помощью error_log, нельзя настроить. В дальнейшем с set_error_handler, как было предложено @fusion3k, я собрал этот обработчик ошибок, который будет форматировать дату, сообщение и уровни ошибок в более удобном для компьютера/человека формате.

// 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);

Выход

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

person Sdlion    schedule 15.02.2016    source источник
comment
Примечание. LOG_INFO, LOG_DEBUG и другие подобные константы уже определены для функции syslog. php.net/manual/es/function.syslog.php   -  person Sdlion    schedule 15.02.2016


Ответы (2)


Если вы используете свой пользовательский файл журнала ошибок, вы можете просто добавить предпочитаемый формат даты к сообщению журнала.

Если вы используете стандартный файл журнала Apache, вы не можете изменить формат журнала через php.

Вместо этого вам нужно изменить весь формат журнала ошибок Apache в ключевом слове от httpd.conf до LogFormat: замените существующий формат желаемым форматом.

Здесь вы можете найти полное руководство по синтаксису для LogFormat.

Редактировать:

После вашего последнего комментария я провел поиск в Интернете и провел несколько тестов, а затем понял, что мой предыдущий ответ неверен: нет способа изменить поведение error_log() в php. В моем случае (у меня установлен Apache) функция error_log() выводит формат журнала Apache четный в пользовательский файл журнала (определенный с помощью ini_set('error_log')).

В вашем случае я думаю, что php использует формат журнала ОС (вы уверены, что у вас не установлен Apache, даже если вы его не используете?).

Альтернатива: trigger_error()

Вы можете установить свой полностью настраиваемый формат журнала ошибок, используя trigger_error() — в сочетании с set_error_handler() — вместо 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' );

В приведенном выше примере trigger_error добавит в file.log строку, подобную этой:

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

Настройка error_handler все системные ошибки обрабатываются пользовательской функцией. Чтобы имитировать системную ошибку, вы должны использовать trigger_error() вместо error_log().

Для максимальной настройки можно передать trigger_error дополнительный параметр error_type:

trigger_error( 'Test', E_WARNING );

выдаст ошибку Уровень предупреждения; значение по умолчанию error_type равно E_USER_NOTICE. Тип ошибки — это первый параметр ($errType) в пользовательской функции, поэтому внутри пользовательской функции обработчика ошибок вы можете изменить поведение в зависимости от типа ошибки.

В приведенном выше простом примере пользовательская функция также обрабатывает некоторые директивы ini, поэтому вы можете использовать ini_set в сочетании с set_error_handler. Обратите внимание, что вы можете изменить имена переменных параметров пользовательских функций, но не порядок, потому что это определяется внутренней системой ошибок php.

Если вы решите использовать set_error_handler(), внимательно прочитайте документацию, чтобы понять поведение и исключения.


person fusion3k    schedule 15.02.2016
comment
Сценарий запускается с php -f file.php на рабочем сервере. Там нет даже установки апача. Но что еще более важно, что вы подразумеваете под пользовательским файлом журнала ошибок? - person Sdlion; 15.02.2016
comment
Я почти уверен, что у меня нет установки Apache. В моей системе нет httpd.conf. И /etc/apache2/ имеет только один файл: conf.d/javascript-common.conf является символической ссылкой на /etc/javascript-common/javascript-common.conf. В /usr/share/wwwconfig-common/ есть несколько скриптов, связанных с apache. Я собираюсь использовать собственный дескриптор ошибок. Я просто не мог поверить, что error_log нельзя редактировать - person Sdlion; 15.02.2016
comment
@Sdlion Я забыл проверить файл php.ini: в моем php.ini много ошибок/конфигураций журнала, но ничего о формате журнала. Я говорю: «Вы уверены, что у вас не установлен Apache?», потому что ваш формат журнала дат похож на мой формат журнала ошибок Apache. - person fusion3k; 15.02.2016
comment
я думаю, что директива ErrorLog apache не будет следовать LogFormat, поскольку она (LogFormat) может использоваться директивой CustomLog - person kia nasirzadeh; 20.10.2019

(Я скопировал ответ @Sdlion в его собственный ответ, чтобы мы могли проголосовать за него)

Кажется, что дату, отображаемую с помощью error_log, нельзя настроить. Продолжая использовать set_error_handler, как было предложено @fusion3k, я собрал этот обработчик ошибок, который будет форматировать дату, сообщение и уровни ошибок в более удобном для компьютера/человека формате.

// 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);

Выход

2016-02-15 14:20:05-0600;DEBUG;Test
person scott8035    schedule 28.09.2018