Система PHP IDS разоблачать использования Монолог хранить логи в 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)"
Может кто-нибудь сказать мне, как хранить datetime
в формате ISODate?
Вы правильно используете MongoDate генерировать объект datetime. например:
$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
У меня была такая же проблема в конфигурации Symfony2. Я решил, установив пользовательский форматер, который в принципе ничего не делает. В моем случае это работало довольно хорошо, так как я хранил только скалярные данные, единственным исключением было MongoDate это не должно быть отформатировано. Так что может быть, что вам нужно сделать некоторые настройки на вашей стороне.
Вот пользовательский форматтер:
<?php
namespace AppBundle\Service\Formatter;
use Monolog\Formatter\FormatterInterface;
/**
* Class MongoLoggerFormatter
*
* @package AppBundle\Service
* @author Francesco Casula <[email protected]>
*/
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;
}