Symfony 3.4-基于“上下文”的差异记录器

时间:2018-09-10 15:28:11

标签: php symfony monolog

我希望能够根据Symfony命令或应用程序服务器调用服务来区分Monolog使用的通道。

例如:

class A {
    private $logger;

    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }
}

class B {
    private $logger;

    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }
}

class SomeCommand extends Symfony\Component\Console\Command\Command {
    private $logger;

    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }

    protected function configure() {
        $this->setName('my-app:command');
    }

    protected function execute(InputInterface $input, OutputInterface $output) {
        // execute something from class A
        // execute something from class B
    }
}

如果我运行php bin\console my-app:command,我希望Symfony将所有内容写入commands通道(文件命令-{environment} .log),而如果请求使用了类A和B,从控制器,他们将所有内容都写入另一个通道。

目前我的配置是:

monolog:
    channels: ['commands']
    handlers:
        main:
            type: rotating_file
            path: '%kernel.logs_dir%/%kernel.environment%.log'
            level: debug
            channels: [!commands]
        commands_only:
            type: rotating_file
            path: '%kernel.logs_dir%/commands-%kernel.environment%.log'
            level: debug
            channels: [commands]

仅将记录器注入Command服务并不能得到我想要的结果:仅将Command类中的日志写到文件command- {environment} .log中,而其他类仍将日志记录到文件{envinronment} .log。

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您可以为此使用tagged Strategy Patternhere

独白

假设您创建了两个自定义的独白处理程序。 handler_xhandler_y

配置

service:
    # CONSUMER
    App\Service\StrategyService:
        arguments: [!tagged mytag]

    App\Service\ServiceA:
            - @monolog.logger.handler_x
        tags:
            - { name: mytag }

    App\Service\ServiceB:
        arguments:
            - @monolog.logger.handler_y
        tags:
            - { name: mytag }

StrategyService

declare(strict_types=1);

namespace App\Service;

use Traversable;

class StrategyService
{
    private $services;

    public function __construct(Traversable $services)
    {
        $this->services = $services;
    }

    public function process(string $name, string $message): bool
    {
        /** @var ServiceInterface $service */
        foreach ($this->services as $service) {
            if ($service->canProcess($name)) {
                $service->process($message);

                break;
            }
        }
    }
}

ServiceInterface

declare(strict_types=1);

namespace App\Service;

interface ServiceInterface
{
    public function canProcess(string $name): bool;

    public function process(string $message): void;
}

服务A

declare(strict_types=1);

namespace App\Service;

use Psr\Log\LoggerInterface;

class ServiceA implements ServiceInterface
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function canProcess(string $name): bool
    {
        return $name === 'handler_x';
    }

    public function process(string $message): void
    {
        // Do something with your service

        $this->logger->error($message);
    }
}

服务B

declare(strict_types=1);

namespace App\Service;

use Psr\Log\LoggerInterface;

class ServiceB implements ServiceInterface
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function canProcess(string $name): bool
    {
        return $name === 'handler_y';
    }

    public function process(string $message): void
    {
        // Do something with your service

        $this->logger->error($message);
    }
}

现在您要做的就是注入StrategyService来命令并调用process方法。

$this->strategyService->process('handler_x', 'This goes to ServiceA logger.');
$this->strategyService->process('handler_y', 'This goes to ServiceB logger.');