T
T
topuserman2020-03-10 23:36:06
PHP
topuserman, 2020-03-10 23:36:06

How to properly configure the logger and inject the dependency?

Hello!
I have many classes in my project that perform certain tasks.
There was a need to log.
Some classes should write logs to a file, others should send them using a specific protocol, or simultaneously to several sources.

To do this, I chose the Monolog library, which solves my problems with logging.

The problem arose architectural:

since. before using the logger class, it needs to be configured (set the error level for logging, file or other storage for logs, log format, etc.),
and all this takes about 20-50 lines of code.

Options I wanted to implement:

1. Initially, I thought to add a method to each class - * createLogger *, where I would configure the logger and return an object. It is very simple to implement, but it is a violation of the SRP principle.
Because each time you will need to climb into the class and change the method if you need to change the log format, or add a new storage for the log.

2. Create a factory that will create these loggers.
But in this case, the factory must have a bunch of settings so that different loggers can be configured.
This option also disappears, because. as a result, there will be another class, which also needs to be configured from a dozen lines of code.

3. Inject the logger dependency through the constructor, and before using the class, configure the logger and pass it through the constructor.
Seems like a normal option. But almost all project classes should have logging. Is it really necessary for all classes by default to have a constructor filled with arguments for a dependency-logger?

4. What are the options? How it is correct to implement it from the point of view of architecture?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
dmitriy, 2020-03-11
@topuserman

5. implement a logger depending on the interface. In DI it is possible to call the setLogger method depending on the interface.
For example, you create interfaces:

FileLoggerAware extends LoggerAwareInterface 
MysqlLoggerAware extends LoggerAwareInterface

now configures DI
$container->share(FileLogger::class,function(){
       return new NullLogger;//тут реализация file логера
});
$container->share(MysqlLogger::class,function(){
      return new NullLogger;//тут реализация Mysql логера
});
$container
    ->inflector(FileLoggerAware::class)
    ->invokeMethod('setLogger', [FileLogger::class]) 
;
$container
    ->inflector(MysqlLoggerAware::class)
    ->invokeMethod('setLogger', [MysqlLogger::class]) 
;

and you do everything in the right class (but all classes must work through awaring di, arrive automatically through the constructor)
class MyClass implements FileLoggerAware
{

use LoggerAwareTrait;

}

links:
https://github.com/php-fig/log/blob/master/Psr/Log...
https://container.thephppleague.com/3.x/inflectors/

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question