PSR-3 logging in a PHP application - XLogger PHP PSR Logger package blog

Recommend this page to a friend!
  All package blogs All package blogs   XLogger PHP PSR Logger XLogger PHP PSR Logger   Blog XLogger PHP PSR Logger package blog   RSS 1.0 feed RSS 2.0 feed   Blog PSR-3 logging in a PH...  
  Post a comment Post a comment   See comments See comments (0)   Trackbacks (0)  

Author:

Updated on: 2020-08-08

Posted on: 2020-08-08

Viewers: 97 (August 2020 until December 2020)

Last month viewers: 32 (December 2020)

Package: XLogger PHP PSR Logger

Logging within an application or module is one of the overarching tasks that is usually required regardless of the purpose of the component. Be it to log error messages or certain events during the process runtime, or to record information during debugging.




Introduction

For the purpose of logging, appropriate code for logging is usually included in every PHP project, in most cases using an appropriate library that takes over this task.

Depending on the actual purpose of the respective logging and especially on the phase in which the current project is located, it makes sense to define the output target and format as well as the scope of the data to be logged differently.

For example, what is helpful for troubleshooting during the development phase can be superfluous or even undesirable in the delivered product (because this could result in the publication of internal technical information).

Why Use PSR-3?

The use of PSR-3 ensures the highest possible independence of the actual source code from the logging library ultimately used, since the interface is clearly defined. One advantage is that you can use a different library at any time without having to make any changes in your own source code. Just as important is the possibility that any external modules or components that implement PSR-3-compliant logging can be easily integrated into your own project and their logging is thus automatically integrated into the system's own logging. Conversely, a self-created component based on PSR-3 logging can be integrated into third-party projects much faster.

PSR-3 and the dependency inversion principle

However, using a PSR-3 compatible logging library alone does not guarantee the independence of your own source code. As a further important step, no instance of a logger should be created within its own classes, but each class should implement a property holding an instance of LoggerInterface and a method to set this property. The Logger should be passed from outside, so there is the posibility to choose any PSR-3 compliant logger and configure it for the current environment or situation. The easiest way to do this is to either implement your own classes using the LoggerAwareInterface, which is also included in the PSR-3 specification, or, if this is not possible (if the own class already extends any other class or implements any other interface), simply integrate the LoggerAwareTrait by an use statement.

Another common pattern is to initialize the internal logger property in the constructor of your own class with an instance of the NullLogger class also contained in the PSR-3 specification. This class implements the Logger interface, but actually does nothing at all. The purpose of this class is that the logger can be called inside the class without need to validate the internal logger each time.

If the loger property is not initialized with a NullLogger, the logger should be included as an argument in the class constructor to ensure that a valid logger is available.

The PSR-3 LoggerInterface

In order to log PSR3 compatible, it is necessary to examine the structure and methods of the logger interface more closely.

The interface provides 8 methods for creating log entries with the appropriate weighting. In addition, a general method is defined that receives the weighting of the entry to be created as the first parameter.

PSR3 defines the following levels based on RFC 5424 (defined in class LogLevel):

  • Emergency the system is unusable
  • Alert immediate action is required
  • Critical critical conditions
  • Error errors that do not require immediate attention but should be monitored
  • Warning unusual or undesirable occurrences that are not errors
  • Notice normal but significant events
  • Info interesting events
  • Debug detailed information for debugging purposes

All methods expect the message to be logged as the first argument. This must either be a string or an object that implements the __toString() method. In addition to plain text, the message can also contain placeholders in curly braces ({key}), which are replaced by the corresponding values from the context data, which can be passed as a second argument.

The context data in the second (optional) argument are passed as an associative array. Any additional information that is not necessarily available as a string can be transferred via this array. The presentation of this context data is in the responsibility of the implementation of the logger, whereby the context data should be treated by the logger as tolerantly as possible. The content of the context data will under no circumstances lead to any exception, error or warning.

Exceptions are a special case when transferring the context data. An exception can also be passed directly in the message argument (this is permitted since all exceptions implement the __toString() method), but it is better to provide this in the context array in the key 'exception'. The implementation of the logger have thus the option to include additional, more extensive information (such as the stack trace) in the log, provided the respective output medium allows it.

Example how to implement PSR-3 logging

Below you see an example, how to implement an own class using PSR-3 logging. It shows the use of the context argument for some data and how to set an exception.

use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;

/**
 * Testclass to demonstrate the integration of any PSR-3 logger into
* own classes. Either implement LoggerAwareInterface or integrate
* LoggerAwareTrait by use statement (like i do here).
 */

class TestClass
{
    use LoggerAwareTrait;

    /**
     * it makes sense to initialize the $logger property with an
     * instance of the PSR-3 NullLogger() so nowhere in the code have
     * to be tested, if any logger is set.
     */

    public function __construct()
    {
        $this->logger = new NullLogger();
    }
    public function doSomething()
    {
        $this->logger->info(
'Start {class}::doSomething()'
,
['class' => get_class($this)]
);
        for ($i = 1; $i < 10; $i++) {
            // run a loop
            $this->logger->debug('Run loop ({loop})', ['loop' => $i]);
        }
        $this->logger->info(
'{class}::doSomething() finished'
,
['class' => get_class($this)]
);
    }
    public function causeException()
    {
        try {
            $this->throwException();
        } catch (Exception $e) {
            $this->logger->error('Catch Exception', ['exception' => $e]);
        }
    }
    protected function throwException()
    {
        throw new Exception('this is an Exception');
    }
}

With such a design, we are now able to use the class and control the logging behavior without having to change the class itself. We can use any PSR-3 compliant logger depending on requirements or environment.

$oTest = new TestClass();
// just work without logging...
$oTest->doSomething();
// work with our own PSR-3 logger $myLogger = new MyPSR3Logger(LogLevel::WARNING);
$oTest->setLogger($myLogger);
$oTest->doSomething();
// ... or use i.e. a Monolog logger
$logger = new MonologLogger('Test');
$logger->pushHandler(new MonologHandlerStreamHandler('test.log'));
$oTest->setLogger($logger);
$oTest->doSomething();

Conclusion

This post shows how using PSR-3 can help us write code that is not dependent on a particular logging implementation. Support for PSR-3 is already included in many well-known PHP projects (Monolog, Zend framework, Symfony,  ...) or there are corresponding plug-ins (Wordpress, Drupal, ...).

The use of PSR-3 compliant logging considerably simplifies the integration of different modules and libraries and makes the abilities of logging much more flexible.




You need to be a registered user or login to post a comment

Login Immediately with your account on:

FacebookGmail
HotmailStackOverflow
GitHubYahoo


Comments:

No comments were submitted yet.



  Post a comment Post a comment   See comments See comments (0)   Trackbacks (0)  
  All package blogs All package blogs   XLogger PHP PSR Logger XLogger PHP PSR Logger   Blog XLogger PHP PSR Logger package blog   RSS 1.0 feed RSS 2.0 feed   Blog PSR-3 logging in a PH...  

For more information send a message to info at phpclasses dot org.