diff --git a/composer.json b/composer.json index 8c9e3b8a..060dd9cb 100644 --- a/composer.json +++ b/composer.json @@ -35,8 +35,8 @@ "ruflin/elastica": "Allow sending log messages to an Elastic Search server", "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", "rollbar/rollbar": "Allow sending log messages to Rollbar", "php-console/php-console": "Allow sending log messages to Google Chrome" diff --git a/src/Monolog/Handler/MongoDBHandler.php b/src/Monolog/Handler/MongoDBHandler.php index de40ef5d..15f6c882 100644 --- a/src/Monolog/Handler/MongoDBHandler.php +++ b/src/Monolog/Handler/MongoDBHandler.php @@ -11,55 +11,51 @@ namespace Monolog\Handler; -use Monolog\Logger; -use Monolog\Formatter\NormalizerFormatter; +use MongoDB\Driver\BulkWrite; use MongoDB\Driver\Manager; use MongoDB\Client; -//use Mongo; -use MongoClient; +use Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; /** * Logs to a MongoDB database. * - * usage example: + * Usage example: * - * $log = new Logger('application'); - * $mongodb = new MongoDBHandler(new \Mongo("mongodb://localhost:27017"), "logs", "prod"); + * $log = new \Monolog\Logger('application'); + * $client = new \MongoDB\Client('mongodb://localhost:27017'); + * $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod'); * $log->pushHandler($mongodb); * - * The above examples uses the MongoDB PHP library's client class; however, - * classes from ext-mongodb (MongoDB\Driver\Manager) and ext-mongo (Mongo and - * MongoClient) are also supported. - * - * @author Thomas Tourlourat + * The above examples uses the MongoDB PHP library's client class; however, the + * MongoDB\Driver\Manager class from ext-mongodb is also supported. */ class MongoDBHandler extends AbstractProcessingHandler { - private $mongoCollection; - private $namespace; + private $collection; private $manager; - + private $namespace; /** * Constructor. * - * @param Client|Manager|Mongo|MongoClient $mongo MongoDB driver or library instance - * @param string $database Database name - * @param string $collection Collection name - * @param int $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 + * @param Client|Manager $mongodb MongoDB library or driver client + * @param string $database Database name + * @param string $collection Collection name + * @param int $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($mongo, $database, $collection, $level = Logger::DEBUG, $bubble = true) + public function __construct($mongodb, $database, $collection, $level = Logger::DEBUG, $bubble = true) { - if (!($mongo instanceof MongoClient || $mongo instanceof \Mongo || $mongo instanceof MongoDB\Client || $mongo instanceof Manager)) { - throw new \InvalidArgumentException('MongoClient, Mongo or MongoDB\Client instance required'); + if (!($mongodb instanceof Client || $mongodb instanceof Manager)) { + throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required'); } - if ($mongo instanceof Manger) { - $this->manager = $mongo; - $this->namespace = $database . '.' . $collection; + if ($mongodb instanceof Client) { + $this->collection = $mongodb->selectCollection($database, $collection); } else { - $this->mongoCollection = $mongo->selectCollection($database, $collection); + $this->manager = $mongodb; + $this->namespace = $database . '.' . $collection; } parent::__construct($level, $bubble); @@ -67,23 +63,15 @@ class MongoDBHandler extends AbstractProcessingHandler protected function write(array $record) { - if ($this->mongoCollection instanceof Collection) { - $this->mongoCollection->insertOne($record["formatted"]); - - return; + if (isset($this->collection)) { + $this->collection->insertOne($record['formatted']); } - if ($this->mongoCollection instanceof MongoCollection) { - $this->mongoCollection->insert($record["formatted"]); - - return; + if (isset($this->manager, $this->namespace)) { + $bulk = new BulkWrite; + $bulk->insert($record["formatted"]); + $this->manager->executeBulkWrite($this->namespace, $bulk); } - - // $this->manager instanceof \MongoDB\Driver\Manager - $bulk = new BulkWrite(); - $bulk->insert($record["formatted"]); - $this->$manager->executeBulkWrite($this->namespace, $bulk); - } /** @@ -91,6 +79,6 @@ class MongoDBHandler extends AbstractProcessingHandler */ protected function getDefaultFormatter() { - return new NormalizerFormatter(); + return new NormalizerFormatter; } } diff --git a/tests/Monolog/Handler/MongoDBHandlerTest.php b/tests/Monolog/Handler/MongoDBHandlerTest.php index 5c05e901..5d6d59dc 100644 --- a/tests/Monolog/Handler/MongoDBHandlerTest.php +++ b/tests/Monolog/Handler/MongoDBHandlerTest.php @@ -11,8 +11,9 @@ namespace Monolog\Handler; +use MongoDB\Driver\Manager; use Monolog\TestCase; -use Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; class MongoDBHandlerTest extends TestCase { @@ -21,78 +22,57 @@ class MongoDBHandlerTest extends TestCase */ public function testConstructorShouldThrowExceptionForInvalidMongo() { - new MongoDBHandler(new \stdClass(), 'DB', 'Collection'); + new MongoDBHandler(new \stdClass, 'db', 'collection'); } - public function testHandle() + public function testHandleWithLibraryClient() { - $mongo = $this->getMock('Mongo', array('selectCollection'), array(), '', false); - $collection = $this->getMock('stdClass', array('insert')); + if (!(class_exists('MongoDB\Client'))) { + $this->markTestSkipped('mongodb/mongodb not installed'); + } - $mongo->expects($this->once()) + $mongodb = $this->getMockBuilder('MongoDB\Client') + ->disableOriginalConstructor() + ->getMock(); + + $collection = $this->getMockBuilder('MongoDB\Collection') + ->disableOriginalConstructor() + ->getMock(); + + $mongodb->expects($this->once()) ->method('selectCollection') - ->with('DB', 'Collection') + ->with('db', 'collection') ->will($this->returnValue($collection)); - $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); - - $expected = array( - 'message' => 'test', - 'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), - 'level' => Logger::WARNING, - 'level_name' => 'WARNING', - 'channel' => 'test', - 'datetime' => $record['datetime']->format('Y-m-d H:i:s'), - 'extra' => array(), - ); + $record = $this->getRecord(); + $expected = $record; + $expected['datetime'] = $record['datetime']->format(NormalizerFormatter::SIMPLE_DATE); $collection->expects($this->once()) - ->method('insert') + ->method('insertOne') ->with($expected); - $handler = new MongoDBHandler($mongo, 'DB', 'Collection'); + $handler = new MongoDBHandler($mongodb, 'db', 'collection'); $handler->handle($record); } - public function testHandleWithManager() { - if (!(class_exists('MongoDB\Driver\Manager'))) { - $this->markTestSkipped('mongo extension not installed'); - } - - $manager = $this->getMock('MongoDB\Driver\Manager', array('executeBulkWrite'), array(), '', false); - - - $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); - $expected = array( - 'message' => 'test', - 'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), - 'level' => Logger::WARNING, - 'level_name' => 'WARNING', - 'channel' => 'test', - 'datetime' => $record['datetime']->format('Y-m-d H:i:s'), - 'extra' => array(), - ); - - $bulk = new \MongoDB\Driver\BulkWrite(); - $bulk->insert($expected); - - $manager->expects($this->once()) - ->method('executeBulkWrite') - ->with('DB.Collection', $bulk); - - - $handler = new MongoDBHandler($manager, 'DB', 'Collection'); - $handler->handle($record); - - } - -} - -if (!class_exists('Mongo')) { - class Mongo + public function testHandleWithDriverManager() { - public function selectCollection() - { + if (!(class_exists('MongoDB\Driver\Manager'))) { + $this->markTestSkipped('ext-mongodb not installed'); + } + + /* This can become a unit test once ManagerInterface can be mocked. + * See: https://jira.mongodb.org/browse/PHPC-378 + */ + $mongodb = new Manager('mongodb://localhost:27017'); + $handler = new MongoDBHandler($mongodb, 'test', 'monolog'); + $record = $this->getRecord(); + + try { + $handler->handle($record); + } catch (\RuntimeException $e) { + $this->markTestSkipped('Could not connect to MongoDB server on mongodb://localhost:27017'); } } }