如何将 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"]
希望对您有所帮助
我有一个 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"]
希望对您有所帮助