将 Monolog 存储在数据库中

Nar*_*aki 2 database symfony monolog

我一直在用 Symfony 4.2 创建一个应用程序,我想将所有日志保存在数据库中,我正在使用 MonologBu​​ndle。

Monolog.yml

monolog:
    handlers:
        main:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            level: debug
            channels: ["!event"]
        console:
            type: console
            process_psr_3_messages: false
            channels: ["!event", "!doctrine", "!console"]
Run Code Online (Sandbox Code Playgroud)

我想像这样将数据存储在数据库中 在此处输入图片说明

我怎样才能用 Symfony 做到这一点。

Ben*_*der 8

您可以通过创建一个自定义的 Monolog 通道(例如doctrine_channel)和处理程序(例如doctrine)来实现这一点。根据您的需要更新下面的示例。

Monolog 配置

monolog:
    channels: [doctrine_channel]
    handlers:
        main:
            ...
            channels: [... !doctrine_channel]
        console:
            ...
            channels: [... !doctrine_channel]
        doctrine:
            type: service
            channels: [doctrine_channel]
            id: app.logger.doctrine_handler
Run Code Online (Sandbox Code Playgroud)

服务配置

services:
    app.logger.doctrine_handler:
        class: App\Logger\DoctrineHandler
        arguments:
            - "@doctrine.orm.entity_manager"
Run Code Online (Sandbox Code Playgroud)

DoctrineHandler

namespace App\Logger;

use App\Entity\Log;
use Doctrine\ORM\EntityManagerInterface;
use Monolog\Handler\AbstractProcessingHandler;

class DoctrineHandler extends AbstractProcessingHandler
{
    private $initialized;
    private $entityManager;
    private $channel = 'doctrine_channel';

    public function __construct(EntityManagerInterface $entityManager)
    {
        parent::__construct();

        $this->entityManager = $entityManager;
    }

    protected function write(array $record)
    {
        if (!$this->initialized) {
            $this->initialize();
        }

        if ($this->channel != $record['channel']) {
            return;
        }

        $log = new Log();
        $log->setMessage($record['message']);
        $log->setLevel($record['level_name']);

        $this->entityManager->persist($log);
        $this->entityManager->flush();
    }

    private function initialize()
    {
        $this->initialized = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

结果

mysql> SELECT * FROM log;
+----+----------+-----------+---------------------+
| id | message  | level     | created_at          |
+----+----------+-----------+---------------------+
|  1 | Welcome! | INFO      | 2019-02-07 19:00:00 |
|  2 | Go back! | WARNING   | 2019-02-07 19:00:05 |
|  3 | Help!    | EMERGENCY | 2019-02-07 19:00:10 |
+----+----------+-----------+---------------------+
3 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

然后注入@monolog.logger.doctrine_channel(输入提示LoggerInterface)到您的服务或您想要记录某些内容的任何地方。这应该有效!现在,您可以根据需要重构/增强。

  • @NarutoUzumaki - 您要求“将日志存储在数据库中”,这个答案正是您想要/想要的。其余的都是您的责任,所以请务必继续进行特定于功能的修改以实现您需要的任何其他内容。`对于一个用户的一项操作,数据库中总是保存超过 5 行。我想要一个动作,一行将自动保存在数据库中。` - 这与您提出的问题和答案无关。这只是您自己的代码/特定功能实现中的“难闻的气味”。我希望我们现在处于同一页面! (4认同)
  • >>> `这应该有效!现在,您可以根据需要进行重构/增强。 (3认同)