0
votes

I have created custom log handler in symfony. Creating it was not a problem, config: config/packages/dev/monolog.yaml

monolog:
    handlers:
     ....
        alerts:
            type: service
            id: App\Logger\AlertLogger
            channels: [app]
            level:  warning

And my service:

<?php

namespace App\Logger;
use Monolog\Handler\AbstractProcessingHandler;
class AlertLogger extends AbstractProcessingHandler
{
    protected function write(array $record)
    {
        // handle log
    }
}

But the problem is that I want to send this logs to RabbitMQ and do something in Consumer, but there is no way to call any other Service. I tried to pass it to construct, but I am getting errors like:

Argument 3 passed to App\Logger\AlertLogger::__construct() must implement interface OldSound\RabbitMqBundle\RabbitMq\ProducerInterface, string given, called in .....

Thats because there is a construct definition in AbstractProcessingHandler.

=============== EDIT: My tests:

Parents class constructor:

public function __construct($level = Logger::DEBUG, $bubble = true)
{
    $this->setLevel($level);
    $this->bubble = $bubble;
}

I tried to add log handler as a service to services.yaml:

services:
    .....
    App\Logger\AlertLogger:
        arguments:
            $producer: OldSound\RabbitMqBundle\RabbitMq\Producer

And my log handler:

...
class AlertLogger extends AbstractProcessingHandler
{
    /**
     * @var ProducerInterface
     */
    private $producer;
    public function __construct(ProducerInterface $producer)
    {
        $this->producer = $producer;
    }
  ......

But Im getting this error:

Argument 1 passed to App\Logger\AlertLogger::__construct() must implement interface OldSound\RabbitMqBundle\RabbitMq\ProducerInterface, string given, called in

When I try to set construct arguments:

....
class AlertLogger extends AbstractProcessingHandler
{
    /**
     * @var ProducerInterface
     */
    private $producer;
    public function __construct($level, $bubble, ProducerInterface $producer)
    {
        parent::__construct($level, $bubble);
        $this->producer = $producer;
    }
.....

I got error:

Cannot autowire service "App\Logger\AlertLogger": argument "$level" of method "__construct()" has no type-hint, you should configure its value explicitly.

1

1 Answers

0
votes

Lucas, in order to override your constructor arguments you should define custom constructor for it and configure service definition for (if not autowired). Unfortunately this leads to loss of predefined functionality (i.e level setting is useless here), so you have to re-define it by yourself.

If handler defined as a service it's really not processed in any way

https://github.com/symfony/monolog-bundle/blob/master/DependencyInjection/MonologExtension.php#L131-L135

You can try post you constructor and service definition to get more specific answers on their state. On first look I can suggest that you've created the service definition by hand and forgot the @ sign. Just a guess.

Edit:

should be

services:
    .....
    App\Logger\AlertLogger:
        arguments:
            $level: 'warning'
            $bubble: true
            $producer: "@OldSound\RabbitMqBundle\RabbitMq\Producer"

With constructor

/**
 * @var ProducerInterface
 */
private $producer;
public function __construct($level, $bubble, ProducerInterface $producer)
{
    parent::__construct($level, $bubble);
    $this->producer = $producer;
}