Logging events in php

PHP Monolog

PHP Monolog tutorial shows how to do logging in PHP with Monolog.

$ php -v php -v PHP 8.1.2 (cli) (built: Aug 8 2022 07:28:23) (NTS) .

Logging

is the process of writing information into log files. Log files contain information about various events that happened in operating system, software, or in communication.

Purpose of logging

  • Information gathering
  • Troubleshooting
  • Generating statistics
  • Auditing
  • Profiling

Logging is not limited to identifying errors in software development. It is also used in detecting security incidents, monitoring policy violations, providing information in case of problems, finding application bottlenecks, or generating usage data.

Events to log

Events that should be logged include input validation failures, authentication and authorization failures, application errors, configuration changes, and application start-ups and shut-downs.

Events not to log

Events that should not be logged include application source code, session identification values, access tokens, sensitive personal data, passwords, database connection strings, encryption keys, bank account and card holder data.

Logging best practices

  • Logging should be meaningful.
  • Logging should contain context.
  • Logging should be balanced; it should not include too little or too much information.
  • Logging messages should be understandable to humans and parseable by machines.
  • Logging should structured and done at different levels.
  • Logging should be adapted to development and to production.
  • Logging in more complex applications should be done into several log files.
Читайте также:  Inline classes in java

PHP Monolog

is a popular PHP logging library. It allows to send logs to files, sockets, inboxes, databases and various web services. It implements the PSR-3 interface.

$ composer req monolog/monolog

We install Monolog with composer.

Monolog structure

A Monolog logger instance has a channel (name) and a stack of handlers. The handlers are responsible for saving the message to the file, database, or sending it to a mail.

A logged message travels through the handler stack. The last handler acts first. The further propagation of a message is controlled with the bubble variable, which is by default set to true .

A processor is any PHP callable that can be used to process the log message. It can add some extra data to the record.

The context is array data which has additional information that does not fit well in the primary string. The context is a parameter to the logging methods (e.g. info or warn ).

Formatters are used to format message records.

Monolog log levels

  • DEBUG — detailed debug information
  • INFO — interesting events
  • NOTICE — normal but significant events
  • WARNING — exceptional occurrences that are not errors
  • ERROR — runtime errors that do not require immediate action
  • CRITICAL — critical conditions
  • ALERT — events for which action must be taken immediately
  • EMERGENCY — emergency events

Less severe logs are not processed by handlers with more severe logging levels. By setting the log level to ERROR we get messages with ERROR level and up.

Each handler is specified a log level; the default is DEBUG . To produce a message with a specific log level, we have methods including info , warn , error , and critical . Since Monolog predates PSR-3, it contains duplicate methods (e.g. addInfo or addWarning ).

Monolog simple example

In the first example, we use Streamhandler to log a message to a file.

pushHandler(new StreamHandler(__DIR__ . '/logs/app.log', Logger::DEBUG)); $logger->info('First message');

The example writes an info message to the logs/app.log file.

A new logger named main is created.

$logger->pushHandler(new StreamHandler(__DIR__ . '/logs/app.log', Logger::DEBUG));

We add a StreamHandler to the logger with pushHandler . The handler writes messages to the specified file with the DEBUG severity.

We log an info message with info method.

$ cat logs\app.log [2019-05-15 15:49:48] main.INFO: First message [] []

This is the written message. The log message starts with the current datetime. It is followed by the log channel name and level. Then comes the message record. The two pairs of square brackets is where we can specify context and extra data. We can customize this output with Monolog formatters.

Monolog console logging

We can write log messages to terminal.

pushHandler(new StreamHandler('php://stderr', Logger::WARNING)); $logger->warn('A warning message');

We write to console by specifying php://stderr to the StreamHandler .

Monolog context array

Monolog context array allows to add information to the message records at the userland level.

pushHandler(new StreamHandler('php://stderr')); $logger->info('Information message', ['user' => get_current_user()]);

The second parameter of the info method is the context array. We add the current user to the message.

$ php context_array.php [2019-05-15 15:37:56] main.INFO: Information message []

Monolog logger handler stack

We can add multiple handlers to the stack. The last added handler is executed first.

pushHandler(new StreamHandler(__DIR__ . '/logs/app.log')); $main->pushHandler(new StreamHandler('php://stdout', $level = Logger::DEBUG, $bubble = true)); $main->info('Information message');

In the example, we have two logger handlers: a file and a console handler. If we change the $bubble to false , the message will not be written to the logs/app.log file.

Monolog custom processor

A custom processor can be added with pushProcessor .

pushHandler(new StreamHandler('php://stderr')); $logger->pushProcessor(function ($record) < $record['extra']['user'] = get_current_user(); return $record; >); $logger->info('Information message');

In the example, we add some extra information to the message record in the processor. According to the documentation, the difference between context and extra data is that context is supplied in user land whereas extra is internal only and can be filled by processors.

$ php custom_processor.php [2019-05-15 17:24:48] main.INFO: Information message []

The extra information is added at the end of the output.

Monolog JsonFormatter

JsonFormatter writes records in JSON format.

setFormatter($formatter); $logger->pushHandler($stream); $logger->info('Information message', ['user' => get_current_user()]);

The example writes an info message to a file in JSON format using JsonFormatter .

$ cat logs\app-json.log ,"level":200,"level_name":"INFO", "channel":"main","datetime":,"extra":[]>

This is the logged message.

Monolog LineFormatter

LineFormatter formats a log record into a one-line string.

setFormatter($formatter); $logger = new Logger('main'); $logger->pushHandler($streamHandler); $logger->info('Information message from', ['user' => get_current_user()]);

In the example, we customize the message record with LineFormatter .

$output = "[%datetime%] %channel%.%level_name%: %message% %context.user%\n"; $formatter = new LineFormatter($output);

We create a custom record message. It contains datetime, channel name, level name, message and context data.

$streamHandler->setFormatter($formatter);

We add the formatter to the handler with setFormatter .

$ php line_format.php [2019-05-15 17:43:36] main.INFO: Information message from Jano

Monolog mail log message

Emails can be sent with SwiftMailerHandler

$ composer req swiftmailer/swiftmailer

For this example, we need to install swiftmailer/swiftmailer package.

Note: Gmail is not ideal for testing applications. We should use an online service such as Mailtrap or Mailgun, or use an SMTP server provided by a webhosting company.

In our example, we use Mailtrap service.

setUsername('3178491df14b6d'); $transporter->setPassword('7c1d6fa59a5v08'); $mailer = new Swift_Mailer($transporter); $message = new Swift_Message('Critical message'); $message->setFrom(['approot@example.com' => 'App root']); $message->setTo(['support@example.com' => 'Support']); $logger = new Logger('main'); $logger->pushHandler(new SwiftMailerHandler($mailer, $message, Logger::CRITICAL)); $logger->critical('Could not connect to the database');

In the example, we use the SwiftMailerHandler to send a message record to a mail inbox.

$transporter = new Swift_SmtpTransport('smtp.mailtrap.io', 2525, 'tls'); $transporter->setUsername('3178491df14b6d'); $transporter->setPassword('7c1d6fa59a5v08');

Using the Mailtrap connection details, we build the transporter.

$mailer = new Swift_Mailer($transporter);

A Swinf_Mailer is created.

$message = new Swift_Message('Critical message'); $message->setFrom(['approot@example.com' => 'App root']); $message->setTo(['support@example.com' => 'Support']);

A Swift_Message is created. It contains the from the to fields.

$logger = new Logger('main'); $logger->pushHandler(new SwiftMailerHandler($mailer, $message, Logger::CRITICAL)); $logger->critical('Could not connect to the database');

We add the SwiftMailerHandler to the logger and create a critical message with critical .

In this tutorial, we have used Monolog to do logging in PHP.

Источник

Оцените статью