Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge pull request #38 from prolic/mongodb_writer
Browse files Browse the repository at this point in the history
add mongodb writer to writer plugin manager
  • Loading branch information
weierophinney committed Jun 22, 2016
2 parents f06f166 + d77e884 commit 5449b7c
Show file tree
Hide file tree
Showing 10 changed files with 540 additions and 79 deletions.
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ env:
- GH_REF: github.com/zendframework/zend-log.git
- secure: "qA/Jf9N8LOyGch3Wbm/zPKfe+MLSDJuIDiuCklkTULey+gJ9e6RIo0vpmaPfs+de9667teTq0j9xvDlDG/E+/H/CnPHAfs+oZ8SJQiQoXTAZeJ383GORSrj46UScDrWrr+EHAKrj9CWcLLghYfC3Yg4g5j50o6if3bs5s/wLjiYQnTNpzql2f3l8zG/+41wCB+z16RE0Yp5HGlvGi27h0Gw/g5+dTmVqz6PnWBHrheKe5K52p1+8kcBjOO+s08idhgZ0ES2Byd80nfDeV8GCpmSNyf4fLRvgxYX0ikHPPygv9ri4d2v12rgsgTV+aNGH5v9XsaF//vO8OzEt8ZNes17OMj6Em3uZxkdv/Lk6SaqCNQy47zqrkTcfWEFn45bFGMdHaI4CJ1mMa/BAruKgrzU649wmruILZ0IC2FWsTvfnlYyXHYsCNY8LRksBRkBGq5xQxa+0VVXlUnalvL5Pf+FMToznLIoa1DlZx4K1x7/sjCHpiedTehWL+D8rcTJt16j7Pkgu6doXgBUA98qxb/o0fp1lf9bwe2d6cDAifNS8xmcA2apqM3OaGKbhKQ0tzHi4HwObPG7MBXjkITsQmpd/T8G981OCSTcH3w7bKMZ5cf5j7e8NVuyFiQ/EQti82D1ga/pz+Unwcb4uq1yEAozHbjshLYF+HGTg3GVZZwI="

services:
- mongodb

matrix:
fast_finish: true
include:
Expand Down Expand Up @@ -55,6 +58,9 @@ notifications:

before_install:
- if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi
- if [[ $TRAVIS_PHP_VERSION != "7" && $TRAVIS_PHP_VERSION != "hhvm" ]]; then echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; fi
- if [[ $TRAVIS_PHP_VERSION == "hhvm" ]]; then echo "extension = mongodb.so" >> /etc/hhvm/php.ini ; fi
- if [[ $TRAVIS_PHP_VERSION == "hhvm" ]]; then echo "extension = mongo.so" >> /etc/hhvm/php.ini ; fi
- composer self-update
- if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then composer require --dev --no-update satooshi/php-coveralls ; fi
- if [[ $SERVICE_MANAGER_VERSION != '' ]]; then composer require --dev --no-update "zendframework/zend-servicemanager:$SERVICE_MANAGER_VERSION" ; fi
Expand Down
14 changes: 14 additions & 0 deletions src/Exception/ExtensionNotLoadedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Log\Exception;

class ExtensionNotLoadedException extends RuntimeException
{
}
48 changes: 41 additions & 7 deletions src/LoggerAbstractServiceFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,53 @@ protected function processConfig(&$config, ContainerInterface $services)
}

foreach ($config['writers'] as $index => $writerConfig) {
if (!isset($writerConfig['options']['db'])
|| !is_string($writerConfig['options']['db'])
if (isset($writerConfig['name'])
&& ('db' === $writerConfig['name']
|| Writer\Db::class === $writerConfig['name']
|| 'zendlogwriterdb' === $writerConfig['name']
)
&& isset($writerConfig['options']['db'])
&& is_string($writerConfig['options']['db'])
&& $services->has($writerConfig['options']['db'])
) {
// Retrieve the DB service from the service locator, and
// inject it into the configuration.
$db = $services->get($writerConfig['options']['db']);
$config['writers'][$index]['options']['db'] = $db;
continue;
}
if (!$services->has($writerConfig['options']['db'])) {

if (isset($writerConfig['name'])
&& ('mongo' === $writerConfig['name']
|| Writer\Mongo::class === $writerConfig['name']
|| 'zendlogwritermongo' === $writerConfig['name']
)
&& isset($writerConfig['options']['mongo'])
&& is_string($writerConfig['options']['mongo'])
&& $services->has($writerConfig['options']['mongo'])
) {
// Retrieve the Mongo service from the service locator, and
// inject it into the configuration.
$mongoClient = $services->get($writerConfig['options']['mongo']);
$config['writers'][$index]['options']['mongo'] = $mongoClient;
continue;
}

// Retrieve the DB service from the service locator, and
// inject it into the configuration.
$db = $services->get($writerConfig['options']['db']);
$config['writers'][$index]['options']['db'] = $db;
if (isset($writerConfig['name'])
&& ('mongodb' === $writerConfig['name']
|| Writer\MongoDB::class === $writerConfig['name']
|| 'zendlogwritermongodb' === $writerConfig['name']
)
&& isset($writerConfig['options']['manager'])
&& is_string($writerConfig['options']['manager'])
&& $services->has($writerConfig['options']['manager'])
) {
// Retrieve the MongoDB Manager service from the service locator, and
// inject it into the configuration.
$manager = $services->get($writerConfig['options']['manager']);
$config['writers'][$index]['options']['manager'] = $manager;
continue;
}
}
}
}
119 changes: 119 additions & 0 deletions src/Writer/Mongo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php

/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Log\Writer;

use DateTimeInterface;
use Mongo as MongoC;
use MongoClient;
use MongoCollection;
use MongoDate;
use Traversable;
use Zend\Log\Exception;
use Zend\Log\Formatter\FormatterInterface;
use Zend\Stdlib\ArrayUtils;

/**
* Mongo log writer.
*/
class Mongo extends AbstractWriter
{
/**
* MongoCollection instance
*
* @var MongoCollection
*/
protected $mongoCollection;

/**
* Options used for MongoCollection::save()
*
* @var array
*/
protected $saveOptions;

/**
* Constructor
*
* @param MongoC|MongoClient|array|Traversable $mongo
* @param string $database
* @param string $collection
* @param array $saveOptions
* @throws Exception\InvalidArgumentException
* @throws Exception\ExtensionNotLoadedException
*/
public function __construct($mongo, $database = null, $collection = null, array $saveOptions = [])
{
if (!extension_loaded('mongo')) {
throw new Exception\ExtensionNotLoadedException('Missing ext/mongo');
}

if ($mongo instanceof Traversable) {
// Configuration may be multi-dimensional due to save options
$mongo = ArrayUtils::iteratorToArray($mongo);
}
if (is_array($mongo)) {
parent::__construct($mongo);
$saveOptions = isset($mongo['save_options']) ? $mongo['save_options'] : [];
$collection = isset($mongo['collection']) ? $mongo['collection'] : null;
$database = isset($mongo['database']) ? $mongo['database'] : null;
$mongo = isset($mongo['mongo']) ? $mongo['mongo'] : null;
}

if (null === $collection) {
throw new Exception\InvalidArgumentException('The collection parameter cannot be empty');
}

if (null === $database) {
throw new Exception\InvalidArgumentException('The database parameter cannot be empty');
}

if (!($mongo instanceof MongoClient || $mongo instanceof MongoC)) {
throw new Exception\InvalidArgumentException(sprintf(
'Parameter of type %s is invalid; must be MongoClient or Mongo',
(is_object($mongo) ? get_class($mongo) : gettype($mongo))
));
}

$this->mongoCollection = $mongo->selectCollection($database, $collection);
$this->saveOptions = $saveOptions;
}

/**
* This writer does not support formatting.
*
* @param string|FormatterInterface $formatter
* @return WriterInterface
*/
public function setFormatter($formatter)
{
return $this;
}

/**
* Write a message to the log.
*
* @param array $event Event data
* @return void
* @throws Exception\RuntimeException
*/
protected function doWrite(array $event)
{
if (null === $this->mongoCollection) {
throw new Exception\RuntimeException('MongoCollection must be defined');
}

if (isset($event['timestamp']) && $event['timestamp'] instanceof DateTimeInterface) {
$event['timestamp'] = new MongoDate($event['timestamp']->getTimestamp());
}

$this->mongoCollection->save($event, $this->saveOptions);
}
}
97 changes: 60 additions & 37 deletions src/Writer/MongoDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@

namespace Zend\Log\Writer;

use DateTime;
use Mongo;
use MongoClient;
use MongoDate;
use DateTimeInterface;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use MongoDB\Driver\WriteConcern;
use MongoDB\BSON\UTCDateTime;
use Traversable;
use Zend\Log\Exception;
use Zend\Log\Formatter\FormatterInterface;
Expand All @@ -24,59 +25,77 @@
class MongoDB extends AbstractWriter
{
/**
* MongoCollection instance
*
* @var MongoCollection
* @var Manager
*/
protected $mongoCollection;
protected $manager;

/**
* Options used for MongoCollection::save()
*
* @var array
* @var string
*/
protected $database;

/**
* @var WriteConcern
*/
protected $saveOptions;
protected $writeConcern;

/**
* Constructor
*
* @param Mongo|MongoClient|array|Traversable $mongo
* @param string|MongoDB $database
* @param Manager|array|Traversable $manager
* @param string $database
* @param string $collection
* @param array $saveOptions
* @param WriteConcern|array|Traversable $writeConcern
* @throws Exception\InvalidArgumentException
*/
public function __construct($mongo, $database = null, $collection = null, array $saveOptions = [])
public function __construct($manager, $database = null, $collection = null, $writeConcern = null)
{
if ($mongo instanceof Traversable) {
// Configuration may be multi-dimensional due to save options
$mongo = ArrayUtils::iteratorToArray($mongo);
if (!extension_loaded('mongodb')) {
throw new Exception\ExtensionNotLoadedException('Missing ext/mongodb');
}
if (is_array($mongo)) {
parent::__construct($mongo);
$saveOptions = isset($mongo['save_options']) ? $mongo['save_options'] : [];
$collection = isset($mongo['collection']) ? $mongo['collection'] : null;
$database = isset($mongo['database']) ? $mongo['database'] : null;
$mongo = isset($mongo['mongo']) ? $mongo['mongo'] : null;

if ($manager instanceof Traversable) {
// Configuration may be multi-dimensional due to save options
$manager = ArrayUtils::iteratorToArray($manager);
}

if (null === $collection) {
throw new Exception\InvalidArgumentException('The collection parameter cannot be empty');
if (is_array($manager)) {
parent::__construct($manager);
$writeConcern = isset($manager['write_concern']) ? $manager['write_concern'] : new WriteConcern(1);
$collection = isset($manager['collection']) ? $manager['collection'] : null;
$database = isset($manager['database']) ? $manager['database'] : null;
$manager = isset($manager['manager']) ? $manager['manager'] : null;
}

if (null === $database) {
throw new Exception\InvalidArgumentException('The database parameter cannot be empty');
}

if (!($mongo instanceof MongoClient || $mongo instanceof Mongo)) {
if (null !== $collection) {
$database = $database . '.' . $collection;
}

if (!$manager instanceof Manager) {
throw new Exception\InvalidArgumentException(sprintf(
'Parameter of type %s is invalid; must be MongoClient or Mongo',
(is_object($mongo) ? get_class($mongo) : gettype($mongo))
'Parameter of type %s is invalid; must be MongoDB\Driver\Manager',
(is_object($manager) ? get_class($manager) : gettype($manager))
));
}

$this->mongoCollection = $mongo->selectCollection($database, $collection);
$this->saveOptions = $saveOptions;
if ($writeConcern instanceof Traversable) {
$writeConcern = iterator_to_array($writeConcern);
}

if (is_array($writeConcern)) {
$wstring = isset($writeConcern['wstring']) ? $writeConcern['wstring'] : 1;
$wtimeout = isset($writeConcern['wtimeout']) ? $writeConcern['wtimeout'] : 0;
$journal = isset($writeConcern['journal']) ? $writeConcern['journal'] : false;
$writeConcern = new WriteConcern($wstring, $wtimeout, $journal);
}

$this->manager = $manager;
$this->database = $database;
$this->writeConcern = $writeConcern;
}

/**
Expand All @@ -99,14 +118,18 @@ public function setFormatter($formatter)
*/
protected function doWrite(array $event)
{
if (null === $this->mongoCollection) {
throw new Exception\RuntimeException('MongoCollection must be defined');
if (null === $this->manager) {
throw new Exception\RuntimeException('MongoDB\Driver\Manager must be defined');
}

if (isset($event['timestamp']) && $event['timestamp'] instanceof DateTime) {
$event['timestamp'] = new MongoDate($event['timestamp']->getTimestamp());
if (isset($event['timestamp']) && $event['timestamp'] instanceof DateTimeInterface) {
$millis = (int) floor((float) $event['timestamp']->format('U.u') * 1000);
$event['timestamp'] = new UTCDateTime($millis);
}

$this->mongoCollection->save($event, $this->saveOptions);
$bulkWrite = new BulkWrite();
$bulkWrite->insert($event);

$this->manager->executeBulkWrite($this->database, $bulkWrite, $this->writeConcern);
}
}
6 changes: 6 additions & 0 deletions src/WriterPluginManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class WriterPluginManager extends AbstractPluginManager
'firephp' => Writer\FirePhp::class,
'mail' => Writer\Mail::class,
'mock' => Writer\Mock::class,
'mongo' => Writer\Mongo::class,
'mongodb' => Writer\MongoDB::class,
'noop' => Writer\Noop::class,
'psr' => Writer\Psr::class,
'stream' => Writer\Stream::class,
Expand All @@ -45,6 +47,8 @@ class WriterPluginManager extends AbstractPluginManager
Writer\FirePhp::class => WriterFactory::class,
Writer\Mail::class => WriterFactory::class,
Writer\Mock::class => WriterFactory::class,
Writer\Mongo::class => WriterFactory::class,
Writer\MongoDB::class => WriterFactory::class,
Writer\Noop::class => WriterFactory::class,
Writer\Psr::class => WriterFactory::class,
Writer\Stream::class => WriterFactory::class,
Expand All @@ -59,6 +63,8 @@ class WriterPluginManager extends AbstractPluginManager
'zendlogwriterfirephp' => WriterFactory::class,
'zendlogwritermail' => WriterFactory::class,
'zendlogwritermock' => WriterFactory::class,
'zendlogwritermongo' => WriterFactory::class,
'zendlogwritermongodb' => WriterFactory::class,
'zendlogwriternoop' => WriterFactory::class,
'zendlogwriterpsr' => WriterFactory::class,
'zendlogwriterstream' => WriterFactory::class,
Expand Down
Loading

0 comments on commit 5449b7c

Please sign in to comment.