2016-09-05 7 views
0

私はSymfony2プロジェクトを持っていて、別のファイルに美しくログを書きますが、ログをリモートデータベース(mongodb)に書きたいと思っています。データベース接続に何か問題が生じた場合に備えて、実際のログファイルをサーバにバックアップとして保存したいと考えています。Monologログをファイルとリモートデータベースに書き込む方法

質問1: 同じログを2つの異なる場所に同時に保存することはできますか?

質問2: ログをmongodbに保存するにはどうすればよいですか?私は必ずしも特定のmongodb-instructionを必要としませんが、monologgerを使用してリモートdbに書き込む方法に関するいくつかのガイドラインは必要ありません。利用可能であれば、mongodb固有の指示も歓迎されます。 ;)

質問3(オプション): ログに何らかのエラーが発生することはありますか。どこでMonologが実際に書くことができるデータの完全なリストと書き方を見つけることができますか?

答えて

0

いつも、モノログとドクトリンを使ってmysqlデータベースにログするための非常に良いBlogpostがありました。私はもうそれを見つけることができないので、私はちょうどここに必要なファイルを追加し、あなたはそれを調整することができます。 全体のロジックはDatabaseHandlerで行われますので、 mysqlの挿入からmongodbの処理に変更できます。 元の投稿を知っている人は誰でもコメントしてください。

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

サービスで行うことができます。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> 
そして最後に_ ** 設定であなたのモノローグの設定にハンドラを追加します。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"] 
の生産のための

希望があれば

+0

"BacktraceLoggerListener"は何をしていますか?これはconfig_prod.ymlやこの例では使用されていません。 – GotBatteries

+0

PS:サービスコンテナ全体を注入するのは悪い習慣と考えられます。私が間違っていると誰かが私を修正します。 – GotBatteries

+0

BacktraceLoggerListenerはservices.xmlのカーネル例外イベントに登録されています はい、それは悪い習慣とみなされますが、私は午前怠惰なことを言うことができます;) あなたは必要なものだけを注入することもできます。 –

0

私はあなたのためにいくつかアップすることを願って:

質問1:はい、その可能。例えば。あなたはsmtをすることができます。 like:

$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メソッドに渡すことができますか、またはあなたのサービスでそれを持っていたい場合は、MongoDBConfigurationを見てください。

質問3: これは役立つはず:Configure Monolog

希望に役立ちます。

関連する問題