1

PHP IDS 系统暴露使用Monolog将日志存储到 MongoDB。以下是它存储日志的方式:

{
  "message": "Executing on data 4f2793132469524563fa9b46207b21ee",
  "context": [

  ],
  "level": NumberLong(200),
  "level_name": "INFO",
  "channel": "audit",
  "datetime": "1441721696",
  "extra": [

  ]
}

我想在 Mongo 中使用自动删除功能,我需要该datetime字段以 ISOdate 格式存储,如下所示:

"datetime":ISODate("2015-09-08T17:43:25.678Z")

我查看了里面的类Mongo\Expose\Log\Mongo();这是负责存储datetime以秒为单位的格式的部分

public function log($level, $message, array $context = array())
{
    $logger = new \Monolog\Logger('audit');
    try {
        $handler = new \Monolog\Handler\MongoDBHandler(
            new \MongoClient($this->getConnectString()),
            $this->getDbName(),
            $this->getDbCollection()
        );
    } catch (\MongoConnectionException $e) {
        throw new \Exception('Cannot connect to Mongo - please check your server');
    }
    $logger->pushHandler($handler);
    $logger->pushProcessor(function ($record) {
        $record['datetime'] = $record['datetime']->format('U');            

        return $record;
    });

    return $logger->$level($message, $context);
}

我已将 $record['datetime'] 更改为此

//$record['datetime'] = $record['datetime']->format('U');
$record['datetime'] =  new \MongoDate();;

但时间不存储为 ISOdate 而是这样:

"datetime": "[object] (MongoDate: 0.84500000 1441721683)"

谁能告诉我如何以datetimeISODate 格式存储?

4

2 回答 2

0

我在 Symfony2 配置上遇到了同样的问题。我通过设置一个基本上什么都不做的自定义格式化程序来解决。它在我的情况下工作得很好,因为我只存储标量的东西,唯一的例外是不需要格式化的MongoDate。因此,您可能需要在您身边进行一些调整。

这是自定义格式化程序:

<?php

namespace AppBundle\Service\Formatter;

use Monolog\Formatter\FormatterInterface;

/**
 * Class MongoLoggerFormatter
 *
 * @package AppBundle\Service
 * @author  Francesco Casula <fra.casula@gmail.com>
 */
class MongoLoggerFormatter implements FormatterInterface
{
    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        return $record;
    }

    /**
     * {@inheritdoc}
     */
    public function formatBatch(array $records)
    {
        return $records;
    }
}

这是我的异常监听器的摘录:

/**
 * @return \Symfony\Bridge\Monolog\Logger
 */
public function getLogger()
{
    return $this->logger;
}

/**
 * @return \Monolog\Handler\HandlerInterface|null
 */
private function getMongoHandler()
{
    foreach ($this->getLogger()->getHandlers() as $handler) {
        if ($handler instanceof MongoDBHandler) {
            return $handler;
        }
    }

    return null;
}

/**
 * @return \Monolog\Handler\HandlerInterface|null
 */
private function addDefaultMongoHandlerSettings()
{
    $mongoHandler = $this->getMongoHandler();

    if ($mongoHandler) {
        $mongoHandler->setFormatter(new MongoLoggerFormatter());
        $mongoHandler->pushProcessor(function (array $record) {
            $record['created_at'] = new \MongoDate(time());

            return $record;
        });
    }

    return $mongoHandler;
}
于 2016-03-21T13:34:52.240 回答
0

使用MongoDate生成日期时间对象是正确的。例如:

$date = new MongoDate(strtotime("2015-11-23 00:00:00"));

如果您回显此内容,您将获得您描述的格式,但在内部 Mongo 应该正确存储它。要检查,您可以测试:

echo date(DATE_ISO8601, ($date->sec);

它应该以 ISO 可读格式返回它。

然后,您可以编写自己的 PSR-3 兼容记录器,以这种方式存储数据。

$filters = new \Expose\FilterCollection();
$filters->load();
$logger = new \YourCustom\PSR3Logger();
$manager = new \Expose\Manager($filters, $logger);

在您的 Mongo 实例上,您将希望在您的字段上设置 TTL,如下所示:

db.log.ensureIndex( { "datetime": 1 }, { expireAfterSeconds: 3600 } )

有关 TTL 设置的更多信息,请参阅 Mongo 文档:通过设置 TTL 使集合中的数据过期

于 2015-11-24T01:38:17.923 回答