zIs
zIs

Reputation: 860

How can I get a collection of all monolog loggers in Symfony?

I have a factory class that creates different objects and I have a lot of loggers defined for each type of object. And I want to get all loggers collection in my factory. Before I just used a ContainerInterface in my factory constructor, but since Symfony 5.1 container autowiring is deprecated. Now I can not find a way to get a collection of loggers. I tried to use

!tagged_iterator { tag: 'monolog.logger' }

and also tried to set a tag for LoggerInterface and get a tagged_iterator for it, but it didn't work. I suggest that it is because loggers are not real classes.

Upvotes: 1

Views: 903

Answers (1)

Cerad
Cerad

Reputation: 48865

This might be overkill but as you say the logger services are a bit unusual. Seems like they should be tagged or be taggable by LoggerInterface but I ran some test and could not get it to work. Here is a brute force approach which relies on logger services having ids of monolog.logger.name:

# Start with a service locator class
namespace App\Service;

use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ServiceLocator;

class LoggerLocator extends ServiceLocator 
{
    // Just to specify the return type to keep IDEs happy
    public function get($id) : LoggerInterface
    {
        return parent::get($id);
    }
}
...

# now make the kernel into a compiler pass
# src/Kernel.php
class Kernel extends BaseKernel implements CompilerPassInterface
...
    public function process(ContainerBuilder $container)
    {
        $loggerServices = [];
        foreach($container->getServiceIds() as $id) {
            if (!strncmp($id,'monolog.logger.',15)) {
                //echo 'Logger ' . $id . "\n";
                $loggerServices[$id] = new Reference($id);
            }
        }
        $loggerLocator = $container->getDefinition(LoggerLocator::class);
        $loggerLocator->setArguments([$loggerServices]);
    }

# and now we can inject the locator where it is needed
class SomeController {
    public function index(Request $request, LoggerLocator $loggerLocator)
    {
        dump($loggerLocator);
        $logger = $loggerLocator->get('monolog.logger.' . $name);

Seems like there should be a way to do this just through configuring but a pass is easy enough I guess.

Upvotes: 1

Related Questions