1

The PHP IDS system expose uses Monolog to store logs into MongoDB. The following is how it stores a log:

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

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

  ]
}

I want to use the auto-delete function in Mongo, and I need the datetime field to store in ISOdate format, like this:

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

I look at the class Mongo in \Expose\Log\Mongo(); and this is the part responsible for storing the datetime in seconds format

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);
}

I have changed the $record['datetime'] into this

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

but the time isn't store as ISOdate but this:

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

Can anyone tell me how to store the datetime in ISODate format?

RedGiant
  • 4,444
  • 11
  • 59
  • 146

2 Answers2

0

You are correct to use MongoDate to generate the datetime object. eg:

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

If you echo this back you will get the format you describe, but internally Mongo should be storing it correctly. To check, you can test:

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

which should return it in a ISO readable format.

Then you can write your own PSR-3 compatible logger that stores data in that manner.

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

On your Mongo instance you will want to set the TTL on your field like such:

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

For more info on the TTL setting see the Mongo docs: Expire Data from Collections by Setting TTL

Awnage
  • 94
  • 5
0

I had the same issue on a Symfony2 configuration. I solved by setting a custom formatter that basically does nothing. It worked pretty well in my case since I was storing just scalar stuff, the only exception was the MongoDate that didn't have to be formatted. So it could be that you may need to do some tuning on your side.

Here's the custom formatter:

<?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;
    }
}

And here's an excerpt of my exception listener:

/**
 * @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;
}
Francesco Casula
  • 26,184
  • 15
  • 132
  • 131