如何将 Monolog 日志写入文件和远程数据库

How to write Monolog logs into a file AND remote database

我有一个 Symfony2 项目,它可以将日志漂亮地写入不同的文件,但我希望它也可以将日志写入远程数据库 (mongodb)。我想在服务器中保留实际的日志文件作为备份,以防数据库连接出现问题。

问题 1: 甚至可以将相同的日志同时保存到两个不同的地方吗?

问题 2: 如何将日志保存到 mongodb?我不一定需要特定的 mongodb 说明,但需要一些关于如何使用 monologger 写入远程数据库的指南。如果可用,也欢迎 mongodb-特定说明。 ;)

问题 3(可选): 我能以某种方式将完整的错误堆栈写入日志吗?在哪里可以找到 Monolog 实际可以写入哪些数据以及如何写入的完整列表?

希望我能为您解决一些问题:

问题 1:有可能。例如。你可以做smt。喜欢:

    $this->logger->pushHandler(new StreamHandler('/path/to/logs/123_info.log',    Logger::INFO));
    $this->logger->pushHandler(new StreamHandler('/path/to/logs/456_warning.log',    Logger::INFO));

因此,如果 $this->logger->addInfo("testinfo"); 这将被记录在两个流中。

问题2:根据StreamHandler,有一个MongoDBHandler。您应该能够对其进行配置并将其传递给 pushHandler 方法,或者如果您想在服务中使用它,请查看 .

问题 3: 这应该有所帮助:Configure Monolog

希望对您有所帮助。

有一个非常好的博客post 曾经用独白和学说登录到 mysql 数据库。我找不到它了,所以我会在这里添加必要的文件,你可以调整它。 整个逻辑都在 DatabaseHandler 中完成,因此您只需更改 mysql 插入到 mongodb 的处理中。 这段代码不是我的,如果有人知道原文post请评论。

BacktraceLoggerListener.php

namespace UtilsBundle\EventListener;

use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;

class BacktraceLoggerListener{
private $_logger;

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

public function onKernelException(GetResponseForExceptionEvent $event)
{
    $this->_logger->addError($event->getException());
}
}

DatabaseHandler.php

namespace UtilsBundle\Logger;



use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;

/**
 * Stores to database
 *
 */
class DatabaseHandler extends AbstractProcessingHandler{
protected $_container;

/**
 * @param string $stream
 * @param integer $level The minimum logging level at which this handler will be triggered
 * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
 */
public function __construct($level = Logger::DEBUG, $bubble = true)
{
    parent::__construct($level, $bubble);
}

/**
 *
 * @param type $container
 */
public function setContainer($container)
{
    $this->_container = $container;
}

/**
 * {@inheritdoc}
 */
protected function write(array $record)
{

    // Ensure the doctrine channel is ignored (unless its greater than a warning error), otherwise you will create an infinite loop, as doctrine like to log.. a lot..
    if( 'doctrine' == $record['channel'] ) {

        if( (int)$record['level'] >= Logger::WARNING ) {
            error_log($record['message']);
        }

        return;
    }
    // Only log errors greater than a warning
    // TODO - you could ideally add this into configuration variable
    if( (int)$record['level'] >= Logger::NOTICE ) {

        try
        {
            // Logs are inserted as separate SQL statements, separate to the current transactions that may exist within the entity manager.
            $em = $this->_container->get('doctrine')->getManager();
            $conn = $em->getConnection();

            $created = date('Y-m-d H:i:s');

            $serverData = ""; //$record['extra']['server_data'];
            $referer = "";
            if (isset($_SERVER['HTTP_REFERER'])){
                $referer= $_SERVER['HTTP_REFERER'];
            }

            $stmt = $em->getConnection()->prepare('INSERT INTO system_log(log, level, server_data, modified, created)
                                    VALUES(' . $conn->quote($record['message']) . ', \'' . $record['level'] . '\', ' . $conn->quote($referer) . ', \'' . $created . '\', \'' . $created . '\');');
            $stmt->execute();

        } catch( \Exception $e ) {

            // Fallback to just writing to php error logs if something really bad happens
            error_log($record['message']);
            error_log($e->getMessage());
        }
    }
}
}

我们在这里使用了 xml 但这可以在 services.yml 也是

services.xml

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services     http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
    <service id="utils.database.logger" class="UtilsBundle\Logger\DatabaseHandler">
        <call method="setContainer">
            <argument type="service" id="service_container" />
        </call>
    </service>

    <service id="utils.backtrace.logger.listener" class="UtilsBundle\EventListener\BacktraceLoggerListener">
        <argument type="service" id="logger" />
        <tag name="monolog.logger" channel="backtrace" />
        <tag name="kernel.event_listener"  event="kernel.exception" method="onKernelException" />
    </service>
</services>

最后将处理程序添加到您的独白配置中 config_**.yml 所以这里用于生产例如

config_prod.yml

monolog:
handlers:
    main:
        type:         rotating_file
        action_level: error
        max_files: 10
        handler:      nested
    nested:
        type:  stream
        path:  "%kernel.logs_dir%/%kernel.environment%.log"
        level: debug
    console:
        type:  console
    database:
        type: service
        level: notice
        id: utils.database.logger
        channels: ["!translation"]

希望对您有所帮助