Log ошибок php

(PHP 4, PHP 5, PHP 7, PHP 8)

error_logОтправляет сообщение об ошибке заданному обработчику ошибок

Описание

error_log(
    string $message,
    int $message_type = 0,
    ?string $destination = null,
    ?string $additional_headers = null
): bool

Список параметров

message

Сообщение об ошибке, которое должно быть логировано.

message_type

Определяет куда отправлять ошибку.
Возможны следующие значения:

Типы журналов error_log()

0 Сообщение message отправляется в системный регистратор PHP, используя
механизм логирования операционной системы, или файл, в зависимости от значения директивы
error_log
в конфигурационном файле. Это значение по умолчанию.
1 Сообщение message отправляется электронной почтой на адрес, установленный в параметре
destination. Это единственный тип сообщения, где используется четвёртый параметр
additional_headers.
2 Больше не используется.
3 message применяется к указанному в
destination файлу. Перенос строки автоматически не добавляется в конец
message.
4 Сообщение message отправляется напрямую в обработчик
логера SAPI.
destination

Назначение. Устанавливается в зависимости от параметра
message_type.

additional_headers

Дополнительные заголовки. Используется, когда значение параметра message_type
1.
Данный тип сообщения использует ту же внутреннюю функцию, что и
mail().

Возвращаемые значения

Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Если message_type равен нулю, функция всегда возвращает true,
независимо от того, может ли ошибка логироваться или нет.

Список изменений

Версия Описание
8.0.0 Параметр destination и
additional_headers теперь допускают значение null.

Примеры

Пример #1 Примеры использования error_log()

<?php
// Отправляет уведомление посредством серверного лога, если мы не можем
// подключиться к базе данных.
if (!Ora_Logon($username, $password)) {
error_log("База данных Oracle недоступна!", 0);
}
// Уведомить администратора по электронной почте, если невозможно выделить ресурсы для FOO
if (!($foo = allocate_new_foo())) {
error_log("Большая проблема, мы выпали из FOO!", 1,
"operator@example.com");
}
// другой способ вызвать error_log():
error_log("Вы ошиблись!", 3, "/var/tmp/my-errors.log");
?>

Примечания

Внимание

error_log() не является бинарно-безопасной функцией. message обрезается по null-символу.

Подсказка

message не должен содержать null-символ. Учтите, что message может передаваться в файл, по почте, в syslog и т.д. Используйте подходящую преобразующую или экранирующую функцию, base64_encode(), rawurlencode() или addslashes() перед вызовом error_log().

kevindougans at gmail dot com

13 years ago

Advice to novices: This function works great along with "tail" which is a unix command to watch a log file live. There are versions of Tail for Windows too, like Tail for Win32 or Kiwi Log Viewer.

Using both error_log() and tail to view the php_error.log you can debug code without having to worry so much about printing debug messages to the screen and who they might be seen by.

Further Note: This works even better when you have two monitors setup. One for your browser and IDE and the other for viewing the log files update live as you go.

Sion

4 years ago

DO NOT try to output TOO LARGE texts in the error_log();

if you try to output massive amounts of texts it will either cut of the text at about 8ooo characters (for reasonable massive strings, < 32 K characters) or (for insanely massive strings, about 1.6 million characters) totally crash without even throwing an error or anything (I even put it in a try/catch without getting any result from the catch).

I had this problem when I tried to debug a response from a wp_remote_get(); all of my error_log() worked as they should, except for ONE of them... (-_-)
After about a day of debugging I finally found out why & that's why I type this.

Apparently the response contained a body with over 1.6 million chars (or bytes? (whatever strlen() returns)).

If you have a string of unknown length, use this:
$start_index = 0;
$end_index = 8000;
error_log( substr( $output_text , $start_index , $end_index ) );

frank at booksku dot com

16 years ago

Beware! If multiple scripts share the same log file, but run as different users, whichever script logs an error first owns the file, and calls to error_log() run as a different user will fail *silently*!

Nothing more frustrating than trying to figure out why all your error_log calls aren't actually writing, than to find it was due to a *silent* permission denied error!

i dot buttinoni at intandtel dot com

15 years ago

Be carefull. Unexpected PHP dies when 2GByte of file log reached (on systems having upper file size limit).
A work aorund is rotate logs :)

php at kennel17 dot NOSPAM dot co dot uk

18 years ago

It appears that the system log = stderr if you are running PHP from the command line, and that often stderr = stdout. This means that if you are using a custom error to both display the error and log it to syslog, then a command-line user will see the same error reported twice.

Matthew Swift

3 years ago

Relative paths are accepted as the destination of message_type 3, but beware that the root directory is determined by the context of the call to error_log(), which can change, so that one instance of error_log () in your code can lead to the creation of multiple log files in different locations.

In a WordPress context, the root directory will be the site's root in many cases, but it will be /wp-admin/ for AJAX calls, and a plugin's directory in other cases. If you want all your output to go to one file, use an absolute path.

russ at russtanner dot com

3 years ago

You can easily filter messages sent to error_log() using "tail" and "grep" on *nix systems. This makes monitoring debug messages easy to see during development.

Be sure to "tag" your error message with a unique string so you can filter it using "grep":

In your code:

error_log("DevSys1 - FirstName: $FirstName - LastName: $Lastname");

On your command line:

tail -f /var/log/httpd/error_log | grep DevSys1

In this example, we pipe apache log output to grep (STDIN) which filters it for you only showing messages that contain "DevSys1".

The "-f" option means "follow" which streams all new log entries to your terminal or to any piped command that follows, in this case "grep".

SJL

15 years ago

"It appears that the system log = stderr if you are running PHP from the command line"

Actually, it seems that PHP logs to stderr if it can't write to the log file. Command line PHP falls back to stderr because the log file is (usually) only writable by the webserver.

stepheneliotdewey at GmailDotCom

16 years ago

Note that since typical email is unencrypted, sending data about your errors over email using this function could be considered a security risk. How much of a risk it is depends on how much and what type of information you are sending, but the mere act of sending an email when something happens (even if it cannot be read) could itself imply to a sophisticated hacker observing your site over time that they have managed to cause an error.

Of course, security through obscurity is the weakest kind of security, as most open source supporters will agree. This is just something that you should keep in mind.

And of course, whatever you do, make sure that such emails don't contain sensitive user data.

Anonymous

20 years ago

when using error_log to send email, not all elements of an extra_headers string are handled the same way. "From: " and "Reply-To: " header values will replace the default header values. "Subject: " header values won't: they are *added* to the mail header but don't replace the default, leading to mail messages with two Subject fields.

<?php

error_log

("sometext", 1, "zigzag@my.domain",
"Subject: Foo\nFrom: Rizzlas@my.domain\n");?>

---------------%<-----------------------
To: zigzag@my.domain
Envelope-to: zigzag@my.domain
Date: Fri, 28 Mar 2003 13:29:02 -0500
From: Rizzlas@my.domain
Subject: PHP error_log message
Subject: Foo
Delivery-date: Fri, 28 Mar 2003 13:29:03 -0500

sometext
---------------%<---------------------

quoth the docs: "This message type uses the same internal function as mail() does."

mail() will also fail to set a Subject field based on extra_header data - instead it takes a seperate argument to specify a "Subject: " string.

php v.4.2.3, SunOS 5.8

paul dot chubb at abs dot gov dot au

15 years ago

When logging to apache on windows, both error_log and also trigger_error result in an apache status of error on the front of the message. This is bad if all you want to do is log information. However you can simply log to stderr however you will have to do all message assembly:

LogToApache($Message) {
$stderr = fopen('php://stderr', 'w');
fwrite($stderr,$Message);
fclose($stderr);
}

p dot lhonorey at nospam-laposte dot net

17 years ago

Hi !

Another trick to post "HTML" mail body. Just add "Content-Type: text/html; charset=ISO-8859-1" into extra_header string. Of course you can set charset according to your country or Env or content.

EG: Error_log("<html><h2>stuff</h2></html>",1,"eat@joe.com","subject :lunch\nContent-Type: text/html; charset=ISO-8859-1");

Enjoy !

franz at fholzinger dot com

18 years ago

In the case of missing your entries in the error_log file:
When you use error_log in a script that does not produce any output, which means that you cannot see anything during the execution of the script, and when you wonder why there are no error_log entries produced in your error_log file, the reasons can be:
- you did not configure error_log output in php.ini
- the script has a syntax error and did therefore not execute

eguvenc at gmail dot com

14 years ago

<?php

//Multiline error log class

// ersin güvenç 2008 eguvenc@gmail.com

//For break use "\n" instead '\n'
Class log {

//

const USER_ERROR_DIR = '/home/site/error_log/Site_User_errors.log';

const
GENERAL_ERROR_DIR = '/home/site/error_log/Site_General_errors.log';
/*

User Errors...

*/

public function user($msg,$username)

{

$date = date('d.m.Y h:i:s');

$log = $msg." | Date: ".$date." | User: ".$username."\n";

error_log($log, 3, self::USER_ERROR_DIR);

}

/*

General Errors...

*/

public function general($msg)

{

$date = date('d.m.Y h:i:s');

$log = $msg." | Date: ".$date."\n";

error_log($msg." | Tarih: ".$date, 3, self::GENERAL_ERROR_DIR);

}

}

$log = new log();

$log->user($msg,$username); //use for user errors

//$log->general($msg); //use for general errors

?>

daniel dot fukuda at gmail dot com

14 years ago

If you have a problem with log file permission *silently*
it's best to leave error_log directive unset so errors will be written in your Apache log file for current VirtualHost.

Anonymous

2 years ago

Depending on the error, you may also want to add an error 500 header, and a message for the user:

$message = 'Description of the error.';
error_log($message);
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
exit($message);

kazezb at nospam dot carleton dot edu

18 years ago

It appears that error_log() only logs the first line of multi-line log messages. To log a multi-line message, either log each line individually or write the message to another file.

Robert Chapin

4 years ago

When error_log() unexpectedly uses stdout, you should check if the php.ini value for error_log is empty in your CLI environment. Something as simple as this might restore expected behavior:

<?php ini_set('error_log', 'error_log'); ?>

Anonymous

14 years ago

After scouring the internet for getting event logging to
work in syslog on Windows 2003, I found the following
from this post and was able to successfully get Windows
Event Viewer to log PHP errors/notices:

http://forums.iis.net/p/1159662/1912015.aspx#1913338

1. Copy the PHP 5 binaries to "C:\php".
2. Right-click My Computer and select Properties to bring
up the Computer Properties dialog. Switch to the Advanced
tab and click Environment Variables. Find the system
environment variable PATH, edit it and add ";C:\php"
(without the quotes) to the end.
3. Make sure that the configuration file "php.ini" resides
in the directory "C:\php" and contains the correct path
settings.
4. DELETE any old "php.ini" files from "C:\WINDOWS"
and other directories.
5. Open REGEDIT, navigate to the key
"HKLM\SOFTWARE\PHP" and DELETE the string value
"IniFilePath" from there. It is outdated and no longer
necessary!
6. Modify NTFS security permissions of the directory
"C:\php" to give Read and Execute permissions to (1) the
IIS Guest Account and (2) the group IIS_WPG.
7. Modify NTFS security permissions of the directories
"C:\php\session" and "C:\php\upload" to give additional
Modify permissions to (1) the IIS Guest Account and (2)
the group IIS_WPG.
8. Navigate to the registry key
"HKLM\SYSTEM\CurrentControlSet\Services\Eventlog
\Application" and edit the value "CustomSD" there. Find
the substring "(D;;0xf0007;;;BG)" which Denies access to
the application event log for Builtin Guest accounts (like
the IIS Web User account) and replace this substring with
"(A;;0x3;;;BG)" which allows read and write access. Please
pay attention to leave the rest of the security string intact.
Damaging this value can have dangerous effects!
9. Create or update the registry key
"HKLM\SYSTEM\CurrentControlSet\Services\Eventlog\Application\
PHP-5.2.0" (adapt the last to your version part
if necessary) with the following values:

* "EventMessageFile" (REG_EXPAND_SZ) = "C:\php\php5ts.dll"

* "TypesSupported" (REG_DWORD) = 7

В этом руководстве мы расскажем о различных способах того, как в PHP включить вывод ошибок. Мы также обсудим, как записывать ошибки в журнал (лог).

Как быстро показать все ошибки PHP

Самый быстрый способ отобразить все ошибки и предупреждения php — добавить эти строки в файл PHP:

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

Что именно делают эти строки?

Функция ini_set попытается переопределить конфигурацию, найденную в вашем ini-файле PHP.

Display_errors и display_startup_errors — это только две из доступных директив. Директива display_errors определяет, будут ли ошибки отображаться для пользователя. Обычно директива dispay_errors не должна использоваться для “боевого” режима работы сайта, а должна использоваться только для разработки.

display_startup_errors — это отдельная директива, потому что display_errors не обрабатывает ошибки, которые будут встречаться во время запуска PHP. Список директив, которые могут быть переопределены функцией ini_set, находится в официальной документации .

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

Отображение ошибок PHP через настройки в php.ini

Если ошибки в браузере по-прежнему не отображаются, то добавьте директиву:

display_errors = on

Директиву display_errors следует добавить в ini-файл PHP. Она отобразит все ошибки, включая синтаксические ошибки, которые невозможно отобразить, просто вызвав функцию ini_set в коде PHP.

Актуальный INI-файл можно найти в выводе функции phpinfo (). Он помечен как “загруженный файл конфигурации” (“loaded configuration file”).

Отображать ошибки PHP через настройки в .htaccess

Включить или выключить отображение ошибок можно и с помощью файла .htaccess, расположенного в каталоге сайта.

php_flag display_startup_errors on
php_flag display_errors on

.htaccess также имеет директивы для display_startup_errors и display_errors.

Вы можете настроить display_errors в .htaccess или в вашем файле PHP.ini. Однако многие хостинг-провайдеры не разрешают вам изменять ваш файл PHP.ini для включения display_errors.

В файле .htaccess также можно включить настраиваемый журнал ошибок, если папка журнала или файл журнала доступны для записи. Файл журнала может быть относительным путем к месту расположения .htaccess или абсолютным путем, например /var/www/html/website/public/logs.

php_value error_log logs/all_errors.log

Включить подробные предупреждения и уведомления

Иногда предупреждения приводят к некоторым фатальным ошибкам в определенных условиях. Скрыть ошибки, но отображать только предупреждающие (warning) сообщения можно вот так:

error_reporting(E_WARNING);

Для отображения предупреждений и уведомлений укажите «E_WARNING | E_NOTICE».

Также можно указать E_ERROR, E_WARNING, E_PARSE и E_NOTICE в качестве аргументов. Чтобы сообщить обо всех ошибках, кроме уведомлений, укажите «E_ALL & ~ E_NOTICE», где E_ALL обозначает все возможные параметры функции error_reporting.

Более подробно о функции error_reporting ()

Функция сообщения об ошибках — это встроенная функция PHP, которая позволяет разработчикам контролировать, какие ошибки будут отображаться. Помните, что в PHP ini есть директива error_reporting, которая будет задана ​​этой функцией во время выполнения.

error_reporting(0);

Для удаления всех ошибок, предупреждений, сообщений и уведомлений передайте в функцию error_reporting ноль. Можно сразу отключить сообщения отчетов в ini-файле PHP или в .htaccess:

error_reporting(E_NOTICE);

PHP позволяет использовать переменные, даже если они не объявлены. Это не стандартная практика, поскольку необъявленные переменные будут вызывать проблемы для приложения, если они используются в циклах и условиях.

Иногда это также происходит потому, что объявленная переменная имеет другое написание, чем переменная, используемая для условий или циклов. Когда E_NOTICE передается в функцию error_reporting, эти необъявленные переменные будут отображаться.

error_reporting(E_ALL & ~E_NOTICE);

Функция сообщения об ошибках позволяет вам фильтровать, какие ошибки могут отображаться. Символ «~» означает «нет», поэтому параметр ~ E_NOTICE означает не показывать уведомления. Обратите внимание на символы «&» и «|» между возможными параметрами. Символ «&» означает «верно для всех», в то время как символ «|» представляет любой из них, если он истинен. Эти два символа имеют одинаковое значение в условиях PHP OR и AND.

error_reporting(E_ALL);
error_reporting(-1);
ini_set('error_reporting', E_ALL);

Эти три строки кода делают одно и то же, они будут отображать все ошибки PHP. Error_reporting(E_ALL) наиболее широко используется разработчиками для отображения ошибок, потому что он более читабелен и понятен.

Включить ошибки php в файл с помощью функции error_log ()

У сайта на хостинге сообщения об ошибках не должны показываться конечным пользователям, но эта информация все равно должна быть записана в журнал (лог).

Простой способ использовать файлы журналов — использовать функцию error_log, которая принимает четыре параметра. Единственный обязательный параметр — это первый параметр, который содержит подробную информацию об ошибке или о том, что нужно регистрировать. Тип, назначение и заголовок являются необязательными параметрами.

error_log("There is something wrong!", 0);

Параметр type, если он не определен, будет по умолчанию равен 0, что означает, что эта информация журнала будет добавлена ​​к любому файлу журнала, определенному на веб-сервере.

error_log("Email this error to someone!", 1, "someone@mydomain.com");

Параметр 1 отправит журнал ошибок на почтовый ящик, указанный в третьем параметре. Чтобы эта функция работала, PHP ini должен иметь правильную конфигурацию SMTP, чтобы иметь возможность отправлять электронные письма. Эти SMTP-директивы ini включают хост, тип шифрования, имя пользователя, пароль и порт. Этот вид отчетов рекомендуется использовать для самых критичных ошибок.

error_log("Write this error down to a file!", 3, "logs/my-errors.log");

Для записи сообщений в отдельный файл необходимо использовать тип 3. Третий параметр будет служить местоположением файла журнала и должен быть доступен для записи веб-сервером. Расположение файла журнала может быть относительным путем к тому, где этот код вызывается, или абсолютным путем.

Журнал ошибок PHP через конфигурацию веб-сервера

Лучший способ регистрировать ошибки — это определить их в файле конфигурации веб-сервера.

Однако в этом случае вам нужно попросить администратора сервера добавить следующие строки в конфигурацию.

Пример для Apache:

ErrorLog "/var/log/apache2/my-website-error.log"

В nginx директива называется error_log.

error_log /var/log/nginx/my-website-error.log;

Теперь вы знаете, как в PHP включить отображение ошибок. Надеемся, что эта информация была вам полезна.

error_log

(PHP 4, PHP 5, PHP 7)

error_logОтправляет сообщение об ошибке заданному обработчику ошибок

Описание

bool error_log
( string $message
[, int $message_type = 0
[, string $destination
[, string $extra_headers
]]] )

Отправляет сообщение об ошибке в лог web-сервера или в пользовательский файл.

Список параметров

message

Сообщение об ошибке которое должно быть логировано.

message_type

Определяет куда отправлять ошибку.
Возможны следующие значения:

error_log() log types

0 Сообщение message отправляется в системный регистратор PHP, используя
механизм логирования операционной системы, или файл, в зависимости от значения директивы
error_log
в конфигурационном файле. Это значение по умолчанию.
1 Сообщение message отправляется электронной почтой на адрес, установленный в параметре
destination. Это единственный тип сообщения, где используется четвертый параметр
extra_headers.
2 Больше не используется.
3 message применяется к указанному в
destination файлу. Перенос строки автоматически не добавляется в конец
message.
4 Сообщение message отправляется напрямую в обработчик
логера SAPI.
destination

Назначение. Устанавливается в зависимости от параметра
message_type.

extra_headers

Дополнительные заголовки. Используется, когда значение параметра message_type
1.
Данный тип сообщения использует ту же внутреннюю функцию, что и
mail().

Возвращаемые значения

Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Примечания

Внимание

error_log() не является бинарнобезопасным. message обрезается по null-символу.

Подсказка

message не должен содержать null-символ. Учтите, что message может передаваться в файл, по почте, в syslog, и т.д.. Используйте подходящую преобразующую или экранирующую функцию, base64_encode(), rawurlencode() или addslashes() перед вызовом error_log().

Примеры

Пример #1 Примеры использования error_log()


<?php
// Отправляет уведомление посредством серверного лога, если мы не можем 
// подключиться к базе данных.
if (!Ora_Logon($username$password)) {
    
error_log("Oracle database not available!"0);
}
// Уведомить администратора электронной почтой,  если невозможно выделить ресурсы для FOO
if (!($foo allocate_new_foo())) {
    
error_log("Big trouble, we're all out of FOOs!"1,
               
"operator@example.com");
}
// другой способ вызвать error_log():
error_log("You messed up!"3"/var/tmp/my-errors.log");
?>

Список изменений

Версия Описание
5.2.7 Добавлен 4-й тип значения в message_type.

Вернуться к: Функции обработки ошибок

here’s my log function:

You can edit the log rows by editing $maxLogs=5,
also the order to write your logs $logOrder='top'

<?php
lg('script start','start');

#Code......
lg('script end','End of code');

function lg($str,$mod='Your Log Category'){
    $ts = microtime(true);
    if(!defined('logTimer')){
        define('logTimer',microtime(true));
    }
    $diff=abs(round(($ts-logTimer)*1000,2));
    $maxLogs=5;
    $logOrder='top';#new Logs at top
    
    
    $filename = './log.txt';
    $log=[];
    if(!file_exists($filename)){
        if(!file_put_contents($filename,json_encode($log,128))){
            echo "Can’t open to write '$filename' Check Permissions";
            return;
        }
    }else{
        $c=file_get_contents($filename);
        if(trim($c)==''){$c='[]';}
        
        $log =@json_decode($c,true);
        if(!is_Array($log)){$log=[];}
    }
    $new=['mod'=>$mod,'date'=> date('Y-m-d H:i:s')." Scripttime: ".$diff."ms",'log'=>$str];
    if($logOrder=='top'){
        array_unshift($log , $new);
        $log=array_slice($log,0,$maxLogs);
        }else{
        $log[]=$new;
        $log=array_slice($log,0-$maxLogs,$maxLogs);
    }
    
    
    $logs=json_encode($log,128);
    if(!file_put_contents($filename,$logs) ){echo ("Can’t open to write '$filename' Check Permissions") ;return;}
    return $str;
}
?>

The Output looks like:

[
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:02 0.33ms",
        "log": "test 2"
    },
    {
        "mod": "start",
        "date": "2022-08-04 13:48:29 0ms",
        "log": "test"
    },
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:29 0.27ms",
        "log": "test 2"
    },
    {
        "mod": "start",
        "date": "2022-08-04 13:48:34 0ms",
        "log": "test"
    },
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:34 0.92ms",
        "log": "test 2"
    }
]

Logging is an essential and underutilized practice in software development. It’s
obvious value is for debugging, but it can also be a resource for deriving
various analytics and usage information. When you learn how to log properly, you
will be able to adequately track the inner workings of your application so that
troubleshooting becomes much more effortless.

In this article, we will discuss the basics of logging in PHP and explore all
the logging-related configurations you should know. We will begin by discussing
the native logging functions in the language before branching out to examine the
logging solutions developed by other PHP users. Here are some of the other
things you stand to learn by following through with this article:

  • What is logging and examples of what to log.
  • Understanding PHP logging configurations.
  • Using native logging functions like error_log().
  • Why you should opt for a logging framework
  • An introduction to the Monolog framework for logging.

Prerequisites

Ensure to have
the latest version of PHP installed
on your machine before proceeding with this article. The code snippets and
command output included in the sections below were all tested and confirmed to
be accurate as at PHP v8.x, but they should continue to work with later
versions.

🔭 Want to centralize and monitor your PHP application logs?

Head over to Logtail and start ingesting your logs in 5 minutes.

What should you log?

Before we discuss how logging works in PHP, let’s briefly examine what you
should consider logging when developing your application. Some typical
candidates for what to log include the following:

  • Errors and exceptions. Ensure to log every error and exception that occurs in
    your application so that you can find the root cause of an issue and fix them
    quickly.

  • Incoming requests. When a request is made to an endpoint in your application,
    you should log that event and include details such as a timestamp, user ID (if
    any), the endpoint and HTTP method, etc. It is also a good idea to generate a
    correlation ID at this point such that all other logging calls following from
    the request will include this ID, making it easier to trace the path of a
    specific client request in the application.

  • Any changes to your database, including inserting new data and updating and
    deleting existing data. You should record what data was changed, who changed
    it, and when it occurred.

  • Accessing sensitive information. Whenever sensitive or restricted information
    is being accessed on the system, a corresponding log entry should be recorded
    describing who accessed the resource and when.

Logging as much as possible does not mean you should record just anything as
irrelevant entries will create noise and make your logs much less helpful. You
should also take care never to log anything that would compromise user privacy
such as passwords, credit card information, home addresses, phone numbers, or
other Personally Identifiable Information (PII).

Understanding logging configurations in PHP

PHP saves all its configuration in a php.ini file whose location depends on
your operating system and how you installed PHP. Luckily, there is an easy way
to locate the configuration file. Open a new terminal window and run the
following command:

Configuration File (php.ini) Path: /opt/homebrew/etc/php/8.1

Loaded Configuration File: /opt/homebrew/etc/php/8.1/php.ini

Scan for additional .ini files in: /opt/homebrew/etc/php/8.1/conf.d Additional .ini files parsed: /opt/homebrew/etc/php/8.1/conf.d/ext-opcache.ini

The highlighted line above describes where to find the relevant php.ini file
you need to edit. Copy the path to the file and open it in your text editor:

code <path/to/your/php.ini>

This configuration file is enormous, but we only care about a small section.
Scroll down to the «Error handling and logging» section or use your text
editor’s search function.

. . .
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
. . .

Let’s look at some of the common directives in this section that you need to
note. You can find a complete list of all available directives in the
official documentation. Note that
you’ll need to restart your web server after making changes to your php.ini file
for the changes to take effect.

  • error_reporting: this directive configures
    the level of diagnostics that should be recorded, and its value should be an
    error level constant.
    For example, a value of E_ALL (the default) indicates that all diagnostic
    messages will be recorded regardless of their level, while a value of
    E_ALL & ~E_NOTICE means that all notice-level messages will be omitted.
  • display_errors: controls whether PHP should output errors to the screen as
    part of the program’s output or if they should be hidden from view. Keeping
    this value On is fine in development settings, but it should always be
    turned Off in production, or end users may see ugly stack traces on your
    website when an error occurs (see above screenshot).

  • display_startup_errors: determines whether PHP will output errors that occur
    during its startup sequence. These errors are hidden by default, but you can
    turn them on when debugging.

  • log_errors: this option configures PHP to log errors to the location
    specified by the error_log directive. Setting this to Off will disable
    such behavior, but we recommend keeping this option On.

  • log_errors_max_len: restricts the maximum length of each log record to the
    specified value in bytes. The default is 1024 bytes, but setting this option
    to 0 removes the restriction.

  • error_log: this defines the path to a file where script errors should be
    logged. If this file does not exist, it will be automatically created. You can
    also forward log records to the system log by setting its value to syslog.

Aside from configuring these options directly in the php.ini file, PHP also
offers a way override them at runtime. This can be useful in a serverless
environment where you don’t have access to the configuration file, or when you
are troubleshooting an issue.

You can retrieve the current configuration using the ini_get() function as
shown below:

<?php
echo 'log_errors = ' . ini_get('log_errors') . "\n";
?>

If you wish to override an existing configuration, you can provide a new value
using the ini_set() function:

<?php
ini_set('log_errors', 1); // enable error logging
ini_set('error_log', 'app-errors.log' // specify error log file path
?>

Error levels and constants in PHP

In this section, we’ll examine one of the more obtuse aspects of PHP logging:
error level constants. They are conceptually similar to log
levels and are used to distinguish the different types of
diagnostic messages produced when executing a program.

PHP has an unnecessarily complicated system when it comes to log levels. It uses
many different constants to indicate different log levels, and these constants
can be roughly classified into three families:

1. E_ for internal PHP errors

These include the following:

  • E_ERROR: a fatal error that causes script termination (e.g., calling a
    non-existent function, out of memory, etc.).
  • E_WARNING: a runtime warning that doesn’t terminate script execution (e.g.,
    using an undefined variable in an expression).
  • E_PARSE: compile-time parse errors, usually syntax errors.
  • E_NOTICE: runtime notices, meaning PHP encountered something that it thinks
    could be a mistake, but could also be intentional. For instance, using
    unassigned values in your code.

The constants above are used to indicate the severity of any event in your
application, and they are not user-customizable. When something happens, PHP
will automatically create a log record and decide if it is E_ERROR,
E_WARNING, or E_NOTICE. The only thing we can do with these constants is to
use them in the error_reporting directive to tell PHP whether or not to log
these errors.

2. E_USER for application-specific logs

  • E_USER_ERROR: something went seriously wrong with your project, causing
    services to stop working.
  • E_USER_WARNING: something abnormal happened, but it doesn’t affect the core
    functionalities of your applications, though the situation may need to be
    addressed soon to prevent it from escalating further.
  • E_USER_NOTICE: informative messages that describe the normal operation of
    the program.

3. LOG_ for system logs

The LOG_ family conforms to the standard
syslog severity levels:

  • LOG_EMERG: the entire application is unusable.
  • LOG_ALERT: something serious happened that needs to be addressed
    immediately.
  • LOG_CRIT — a critical function is no longer working.
  • LOG_ERR — an error occurred, but the application can continue working.
  • LOG_WARNING: abnormal situations that may later become an error if not
    addressed.
  • LOG_NOTICE: unusual events but not error conditions.
  • LOG_INFO — informative messages.
  • LOG_DEBUG: used to indicate messages helpful for debugging.

Exploring logging functions in PHP

Now that we’ve examined the PHP logging configuration and its error constants,
let’s get into the nitty-gritty of logging in a PHP project. Several logging
functions ship with PHP, and they all depend on the configurations discussed in
the earlier sections.

To guarantee that you get results consistent with what is described in the
sections below, ensure that your logging configuration matches the following
values:

. . .
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = On
log_errors = On
error_log = error.log
. . .

Go to your working directory and create a new logging.php file using the
command below. This is where we are going to explore PHP’s logging functions
throughout this tutorial.

The most basic form of logging involves sending messages to the console. In PHP,
we can easily print to the console using echo or print statements like this:

<?php
echo "This is a log message.\n";

print "This is also a log message.";
?>
This is a log message.

This is also a log message.

While echo and print statements are valuable ways to print some text to the
console, you shouldn’t use them for logging as there are much better facilities
for doing so. We will explore some of these functions in detail here.

The error_log() function

PHP’s error_log() function pushes a log message to the file path defined in
error_log config option. You can also specify a different file path directly
in the function, if you prefer. It can take up to four arguments but only the
first one is required:

error_log(
    string $message,
    int $message_type = 0,
    ?string $destination = null,
    ?string $additional_headers = null
): bool
  1. The $message argument is the log message you wish to record.
  2. The $message_type argument has a confusing name but it specifies where you
    want PHP to push the message. It has four possible values:

    • 0: the message is sent to the location specified in the error_log
      directive.
    • 1: the message is pushed through email, which is specified by the
      $destination parameter.
    • 3: the message is appended to the file specified by the $destination
      parameter.
    • 4: the message is sent directly to the Server API (SAPI) logging handler,
      which depends on your platform. For example,
      Apache’s error log
      will be used for LAMP (Linux Apache, MySQL, PHP) setups.
  3. The $destination parameter specifies where the log message should be sent,
    and it could be an email address or a local file, depending on the value of
    $message_type.
  4. The $additional_headers parameter is only used when $message_type is set
    to 1. It is the same as the $additional_headers used in PHP’s
    mail() function.

Let’s go ahead and use the error_log() function to create a log record like
this:

<?php
error_log("database not available!");
?>

Once you execute this script, you will notice an error.log file in the current
directory:

Examine the contents of the error.log file through the cat command as shown
below:

[27-Jul-2022 16:05:49 America/New_York] database not available!

As you can see, the error_log() function automatically includes a timestamp
which is one reason why using a dedicated logging function is better than echo
and print statements.

You can also record a log entry into a different file by changing the
$message_type and $destination parameters as shown below:

. . .
error_log("database not available!", 3, "my-errors.log");

Save the changes and execute the logging.php file again.

This time, the log entry will be sent to the my-errors.log file:

Notice that a timestamp is not included in the above entry! This is because the
method bypasses the operating system’s logging mechanism leading to less
detailed logs. A better way to log to a different file is by using the
ini_set() function discussed earlier:

<?php
. . .
ini_set("error_log", "my-errors.log");
error_log("database not available!");
?>

This example will produce the same result, but with the timestamp included:

[27-Jul-2022 17:38:04 America/New_York] database not available!

The trigger_error() function

The trigger_error() function is used to record application-specific errors,
warnings and notices. It takes two parameters: the first one is the log message,
and the second one defines its error level (one of E_USER_ERROR,
E_USER_WARNING, E_USER_NOTICE, or E_USER_DEPRECATED):

<?php
trigger_error("A user requested a resource.", E_USER_NOTICE);
trigger_error("The image failed to load!", E_USER_WARNING);
trigger_error("User requested a profile that doesn't exist!", E_USER_ERROR);
?>

When you execute the script above, you will observe the following console
output:

Notice:  A user requested a resource. in /home/eric/test/logging.php on line 2
Warning:  The image failed to load! in /home/eric/test/logging.php on line 3
Fatal error:  User requested a profile that doesn't exist! in /home/eric/test/logging.php on line 4

The above logs are also recorded to the error.log file in a slightly different
format:

[8-Jul-2022 22:11:43 America/New_York] PHP Notice:  A user requested a service. in /home/eric/test/logging.php on line 3
[8-Jul-2022 22:11:43 America/New_York] PHP Warning:  The image failed to load! in /home/eric/test/logging.php on line 4
[8-Jul-2022 22:11:43 America/New_York] PHP Fatal error:  User requested a profile that doesn't exist! in /home/eric/test/logging.php on line 5

Each log entry specifies the corresponding log level and the location of the log
message. If you don’t use a user-assigned error level constant (prefixed with
E_USER_), an error will be thrown.

<?php
trigger_error("A user requested a service.", E_ERROR);
?>
Fatal error: Uncaught ValueError: trigger_error(): Argument #2 ($error_level) must be one of E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, or E_USER_DEPRECATED in /home/ayo/dev/betterstack/betterstack-community/demo/logging-php/logging.php:2
Stack trace:
#0 /home/ayo/dev/betterstack/betterstack-community/demo/logging-php/logging.php(2): trigger_error()
#1 {main}
  thrown in /home/ayo/dev/betterstack/betterstack-community/demo/logging-php/logging.php on line 2

Logging to the system log

A third way to log messages in PHP is using the syslog() function. It sends
the log message to the default system log like this:

syslog(LOG_ERR, "Custom error message");

The first argument to syslog() is the appropriate log level constant, and the
second is the log message to be recorded. Notice that when specifying the log
level, the third group of constants (those prefixed with LOG_) are utilized.
These constants are unique to the syslog() function, and they are all listed
in its documentation.

Here are a few ways to view your system log:

  • On Linux, use one of the following commands to access the system log
    (depending on the specific OS):
tail -f /var/log/messages
  • On macOS, run tail -f /var/log/system.log in your terminal.
  • On Windows, use the
    Windows Event Viewer.

Here’s some sample output from the system log on a Linux-based OS after
executing the previous code snippet:

Jul 27 20:58:28 fedora php[485047]: Custom error message

You can customize the output above through the openlog() function. It opens a
connection to the system logger and takes up to three arguments: a string prefix
to be added to each message, the logging options, and the logging facility.
After calling openlog(), you should call closelog() to close the connection.

openlog("MyAppPrefix", LOG_PID | LOG_PERROR,LOG_USER);
syslog(LOG_ERR, "Custom error message");
closelog();

Here’s the output after executing the script above:

Jul 28 09:20:04 fedora MyAppPrefix[596277]: Custom error message

You can learn more about system logs on
Linux by reading our
detailed tutorial on the subject.

Why you should use a logging framework

Using PHP’s built-in logging functions is an easy way to get started with
logging in simple projects, but they are insufficient for creating a robust
logging strategy in serious applications due to their lack of features and
flexibility, such as customizing the formatting of your logs, or determining how
they are recorded. They also cannot capture a wide variety of data types since
everything fed into them must be a string, which means you have to do extra work
to capture contextual data in a log entry.

These limitations are why third-party logging frameworks
are prevalent in the PHP ecosystem. Here are some of the most popular logging
libraries for PHP that are worth exploring for production-grade applications:

  • Monolog: Monolog is the most popular PHP
    logging framework out there. It has dozens of handlers that can send your log
    records to files, emails, databases, Slack, etc. It is also packed with
    multiple formatters that allow you to customize your logs however you want.
  • Analog: Analog is a minimal logging
    library. It also has several handlers that can send your logs to different
    destinations. However, it does not have optional features such as formatters
    and processors.
  • KLogger: Unlike Analog, KLogger goes in
    a different direction. It can only push your logs to a file, but it has many
    different formatters that you can use to customize the timestamp, file name,
    file extension, context information, etc.

In the next section, we will briefly examine how to implement logging using the
Monolog library as it’s the most popular and satisfactorily meets all our
criteria for a good logging framework.

Getting started with Monolog

To use Monolog in your PHP application, you need to install the library through
PHP Composer:

composer require monolog/monolog
. . .
Package operations: 2 installs, 0 updates, 0 removals
  - Installing psr/log (3.0.0): Extracting archive

- Installing monolog/monolog (3.1.0): Extracting archive

11 package suggestions were added by new dependencies, use `composer suggest` to see details. Generating autoload files 1 package you are using is looking for funding. Use the `composer fund` command to find out more!

This command will install Monolog into the vendor directory, and you can
import the package into your project like this:

<?php

require __DIR__."/vendor/autoload.php"; // This tells PHP where to find the autoload file so that PHP can load the installed packages

use Monolog\Logger; // The Logger instance
use Monolog\Handler\StreamHandler; // The StreamHandler sends log messages to a file on your disk
use Monolog\Level; // Log levels
?>

The three classes we imported into the file above represent Monolog’s most
important concepts. First, logging in Monolog is channel-based, and the Logger
instance is used to initialize a new log channel which provides a mechanism for
grouping different logs. For example, you can have an errors channel that
records errors, a performance channel that logs performance-related messages,
and so on. You can organize this system however you like depending on what kind
of application you are building.

Each log channel can be assigned multiple handlers, and they are responsible for
sending log messages to various destinations. For example, the StreamHandler
above can push your messages to the console or a local file.

Finally, each handler needs to have a minimum log level, which defines the
minimum level a message must have to be logged by the handler. Monolog provides
a more standard way of dealing with log levels than PHP’s error level constants.
There are eight different levels available in Monolog, and they are modeled
after the
Syslog severity levels
discussed earlier:

  • EMERGENCY
  • ALERT
  • CRITICAL
  • ERROR
  • WARNING
  • NOTICE
  • INFO
  • DEBUG

Logging in PHP with Monolog

Let’s look at an example of how to log messages to the console with Monolog:

<?php
. . .
// New Logger instance. Create a new channel called "my_logger".
$logger = new Logger("my_logger");

// Create a new handler. In this case, it is the StreamHandler, which will send the log messages to the console.
$stream_handler = new StreamHandler("php://stdout", Level::Debug);

// Push the handler to the log channel
$logger->pushHandler($stream_handler);

// Log the message
$logger->debug("This is a debug message.");
$logger->info("This is an info message.");
$logger->error("This is an error message.");
$logger->critical("This is a critical message.");
?>

Execute the logging.php file, and observe the following output:

[2022-07-11T03:32:57.111007+02:00] my_logger.DEBUG: This is a debug message. [] []
[2022-07-11T03:32:57.111750+02:00] my_logger.INFO: This is an info message. [] []
[2022-07-11T03:32:57.111941+02:00] my_logger.ERROR: This is an error message. [] []
[2022-07-11T03:32:57.112127+02:00] my_logger.CRITICAL: This is a critical message. [] []

In this example, a new log channel called my_logger was initialized using the
Logger instance, and then a StreamHandler() instance was assigned to it.
This handler was setup to log debug-level messages or higher to the standard
output (represented by php://stdout).

Lastly, several log messages are recorded by using the debug(), info(),
error(), and critical() methods which give the message the corresponding log
level that is observed in the output. Notice that a timestamp is also included
with each entry.

Instead of logging to the terminal console, we can also push the log record to a
local file using the StreamHandler(). All we need to do is change the
destination parameter like this:

<?php
. . .

$logger = new Logger("my_logger");

$stream_handler = new StreamHandler(__DIR__ . "/log/debug.log", Level::Debug);

$logger->pushHandler($stream_handler); $logger->debug("This is a debug message."); ?>

This causes log messages using the $logger channel to be sent to a
/log/debug.log file. You can examine its contents with the following command:

[2022-07-10T01:53:24.848775+02:00] my_logger.DEBUG: This is a debug message. [] []

There are many other handlers other than the StreamHandler demonstrated above,
so ensure to read our detailed guide on
Monolog to learn more about them and how to
create a custom handler.

Formatting your logs

From the examples above, you will observe that all the log records follow a
predefined format. They all start with a timestamp, followed by the log level,
message, context and extra information. This format might not fit your needs
when creating a logging system, so Monolog provides several formatters that you
can use to customize the log records.

One of the useful formatters to look at is the LineFormatter. It takes a log
record as input, and subsequently outputs a formatted string of the record.
Let’s take a look at an example:

. . .
use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

use Monolog\Formatter\LineFormatter;

$logger = new Logger("my_logger"); $stream_handler = new StreamHandler("php://stdout", Level::Debug);

$output = "%level_name% | %datetime% > %message% | %context% %extra%\n";

$stream_handler->setFormatter(new LineFormatter($output));

$logger->pushHandler($stream_handler); $logger->debug("This file has been executed."); ?>

In this case, we are making Monolog return a log record that starts with the log
level, then the date, message, and context information.

DEBUG | 2022-07-10T21:33:51.345896+02:00 > This file has been executed. | [] []

Besides rearranging the different segments, it is also possible for us to
customize the timestamp output, since the default format isn’t very human
readable.

<?php
. . .

$dateFormat = "Y-n-j, g:i a";

$output = "%level_name% | %datetime% > %message% | %context% %extra%\n"; $stream_handler->setFormatter(new LineFormatter($output, $dateFormat)); . . . ?>
DEBUG | 2022-7-10, 10:24 pm > This file has been executed. | [] []

In a production environment, your application will probably generate tons of
logs, and in this case, it is best to use a structured logging
format
that is better suited to parsing by automated logging tools. Using Monolog’s
JsonFormatter, you are able to log in JSON format, making it easier for
machines to read.

<?php

require __DIR__ . "/vendor/autoload.php";

use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;

$logger = new Logger("daily");

$stream_handler = new StreamHandler("php://stdout", Level::Debug);
$logger->pushHandler($stream_handler);

$stream_handler->setFormatter(new JsonFormatter());

$logger->debug("This is a debug message.");
{"message":"This is a debug message.","context":{},"level":100,"level_name":"DEBUG","channel":"daily","datetime":"2022-07-29T21:43:30.910327+02:00","extra":{}}

Notice that the log message, the log level, the timestamp, and so on have all
been turned into JSON data.

You can learn more about formatters in Monolog and their available options by
reading their
documentation.

Final thoughts

We covered a lot of ground in this article, beginning with PHP’s native logging
functions and their quirks and features before briefly discussing logging
frameworks and why you need one. We also introduced Monolog, a logging library
for PHP application and demonstrated some of its basic features that help you
create a more useful logging system. There’s a lot more about Monolog that can’t
be covered here so we recommend diving into our detailed guide to logging with
Monolog to get a full picture of what you
can do with it.

Thanks for reading, and happy logging!

Author's avatar

Eric is a technical writer with a passion for writing and coding, mainly in Python and PHP. He loves transforming complex technical concepts into accessible content, solidifying understanding while sharing his own perspective. He wishes his content can be of assistance to as many people as possible.

Centralize all your logs into one place.

Analyze, correlate and filter logs with SQL.

Create actionable

dashboards.

Share and comment with built-in collaboration.

Got an article suggestion?
Let us know

Next article

How to Get Started with Monolog Logging in PHP

Monolog is among the most popular pieces of open source software, providing logging capabilities for PHP applications.

Licensed under CC-BY-NC-SA

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Понравилась статья? Поделить с друзьями:
  • Log ошибок linux
  • Lifan svs ошибка
  • Libreoffice ошибка 1406
  • Lof e1 ошибка
  • Lodctr r код ошибки 5