LOG4PHP-207: Using class MongoClient instead of Mongo

 - additional connection options support
 - support for replica tests
 - support for multiple hosts via connection string

Signed-off-by: Vladimir Gorej <[email protected]>
Signed-off-by: Ivan Habunek <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/logging-log4php/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4php/commit/f6d602f4
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4php/tree/f6d602f4
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4php/diff/f6d602f4

Branch: refs/heads/develop
Commit: f6d602f465dfb78aef67b196ac5456ff6c2b945f
Parents: daf50b4
Author: Vladimir Gorej <[email protected]>
Authored: Sun Mar 17 16:13:50 2013 +0100
Committer: Ivan Habunek <[email protected]>
Committed: Mon Mar 18 08:09:41 2013 +0100

----------------------------------------------------------------------
 src/main/php/appenders/LoggerAppenderMongoDB.php   |  318 ++++++++++++---
 .../php/appenders/LoggerAppenderMongoDBTest.php    |   81 ++++-
 2 files changed, 338 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4php/blob/f6d602f4/src/main/php/appenders/LoggerAppenderMongoDB.php
----------------------------------------------------------------------
diff --git a/src/main/php/appenders/LoggerAppenderMongoDB.php 
b/src/main/php/appenders/LoggerAppenderMongoDB.php
index 4963035..8fb1db0 100644
--- a/src/main/php/appenders/LoggerAppenderMongoDB.php
+++ b/src/main/php/appenders/LoggerAppenderMongoDB.php
@@ -15,25 +15,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 /**
  * Appender for writing to MongoDB.
  * 
  * This class was originally contributed by Vladimir Gorej.
  * 
  * ## Configurable parameters: ##
- * 
+ *
+ * - **connectionString ** - Connection string, if used host and port 
properties are ignored. Allows defining multiple hosts.
  * - **host** - Server on which mongodb instance is located. 
  * - **port** - Port on which the instance is bound.
  * - **databaseName** - Name of the database to which to log.
  * - **collectionName** - Name of the target collection within the given 
database.
  * - **username** - Username used to connect to the database.
  * - **password** - Password used to connect to the database.
- * - **timeout** - For how long the driver should try to connect to the 
database (in milliseconds).
+ * - **timeout** - DEPRECATED; For how long the driver should try to connect 
to the database (in milliseconds).
+ * - **connectionTimeout** - How long a connection can take to be opened 
before timing out.
+ * - **socketTimeout** - How long a send or receive on a socket can take 
before timing out.
  * - **capped** - Whether the collection should be a fixed size.
  * - **cappedMax** - If the collection is fixed size, the maximum number of 
elements to store in the collection.
  * - **cappedSize** - If the collection is fixed size, its size in bytes.
- * 
+ * - **writeConcern** - Controls how many nodes must acknowledge the write 
instruction before the driver continues.
+ * - **writeConcernJournaled** - The write will be acknowledged by primary and 
the journal flushed to disk.
+ * - **writeConcernTimeout** -  Controls how many milliseconds the server 
waits for the write concern to be satisfied.
+ * - **replicaSet** - The name of the replica set to connect to. Primary will 
be automatically determined.
+ *
  * @package log4php
  * @subpackage appenders
  * @since 2.1
@@ -43,72 +50,92 @@
  * @link http://www.mongodb.org/ MongoDB website.
  */
 class LoggerAppenderMongoDB extends LoggerAppender {
-       
+
        // ******************************************
        // ** Constants                            **
        // ******************************************
-       
+
        /** Default prefix for the {@link $host}. */    
        const DEFAULT_MONGO_URL_PREFIX = 'mongodb://';
-       
+
        /** Default value for {@link $host}, without a prefix. */
        const DEFAULT_MONGO_HOST = 'localhost';
-       
+
        /** Default value for {@link $port} */
        const DEFAULT_MONGO_PORT = 27017;
-       
-       /** Default value for {@link $databaseName} */
+
+       /** Default value for {@link $databaseName}. */
        const DEFAULT_DB_NAME = 'log4php_mongodb';
-       
-       /** Default value for {@link $collectionName} */
+
+       /** Default value for {@link $collectionName}. */
        const DEFAULT_COLLECTION_NAME = 'logs';
-       
-       /** Default value for {@link $timeout} */
+
+       /** Default value for {@link $timeout}
+        * @deprecated
+        */
        const DEFAULT_TIMEOUT_VALUE = 3000;
 
-       /** Default value for {@link $capped} */
+       /** Default value for {@link $capped}. */
        const DEFAULT_CAPPED = false;
 
-       /** Default value for {@link $cappedMax} */
+       /** Default value for {@link $cappedMax}. */
        const DEFAULT_CAPPED_MAX = 1000;
 
-       /** Default value for {@link $cappedSize} */
+       /** Default value for {@link $cappedSize}. */
        const DEFAULT_CAPPED_SIZE = 1000000;
-       
+
+       /** Single/Primary server acknowledgement of write operation. {@link 
$writeConcern}. */
+       const WC_ACKNOWLEDGED = 1;
+
+       /** Default value for {@link $writeConcernTimeout}. */
+       const WC_TIMEOUT = 3000;
+
+       /**
+        * Default value for {@link $writeConcernJournaled}.
+        */
+       const WC_JOURNALED = false;
+
+
        // ******************************************
        // ** Configurable parameters              **
        // ******************************************
-       
+
+       /**
+        * Support for multiple hosts and additional connection options.
+        * @var string
+        */
+       protected $connectionString;
+
        /** Server on which mongodb instance is located.
         * @var string
         */
        protected $host;
-       
+
        /** Port on which the instance is bound.
         * @var int
         */
        protected $port;
-       
+
        /** Name of the database to which to log.
         * @var string
         */
        protected $databaseName;
-       
+
        /** Name of the collection within the given database.
         * @var string
         */
        protected $collectionName;
-                       
+
        /** Username used to connect to the database.
         * @var string
         */
        protected $userName;
-       
+
        /** Password used to connect to the database.
         * @var string
         */
        protected $password;
-       
+
        /** Timeout value used when connecting to the database (in 
milliseconds).
         * @var int
         */
@@ -128,7 +155,44 @@ class LoggerAppenderMongoDB extends LoggerAppender {
         * @var int
         */
        protected $cappedSize;
-       
+
+       /**
+        * How long the driver blocks when writing
+        * @var string
+        */
+       protected $writeConcern;
+
+       /**
+        * The write will be acknowledged by primary and the journal flushed to 
disk.
+        * @var bool
+        */
+       protected $writeConcernJournaled;
+
+       /**
+        * Write concern timeout in milliseconds.
+        * @var int
+        */
+       protected $writeConcernTimeout;
+
+       /**
+        * Connection timeout in milliseconds.
+        * @var int
+        */
+       protected $connectionTimeout;
+
+       /**
+        * Socket timeout in milliseconds.
+        * @var int
+        */
+       protected $socketTimeout;
+
+       /**
+        * Name of the replicaSet.
+        * @var string
+        */
+       protected $replicaSet;
+
+
        // ******************************************
        // ** Member variables                     **
        // ******************************************
@@ -138,16 +202,22 @@ class LoggerAppenderMongoDB extends LoggerAppender {
         * @var Mongo
         */
        protected $connection;
-       
+
        /** 
         * The collection to which log is written. 
         * @var MongoCollection
         */
        protected $collection;
 
+       /**
+        * Write options.
+        * @var array
+        */
+       protected $writeOptions;
+
        public function __construct($name = '') {
                parent::__construct($name);
-               $this->host = self::DEFAULT_MONGO_URL_PREFIX . 
self::DEFAULT_MONGO_HOST;
+               $this->host = self::DEFAULT_MONGO_HOST;
                $this->port = self::DEFAULT_MONGO_PORT;
                $this->databaseName = self::DEFAULT_DB_NAME;
                $this->collectionName = self::DEFAULT_COLLECTION_NAME;
@@ -156,16 +226,49 @@ class LoggerAppenderMongoDB extends LoggerAppender {
                $this->capped = self::DEFAULT_CAPPED;
                $this->cappedMax = self::DEFAULT_CAPPED_MAX;
                $this->cappedSize = self::DEFAULT_CAPPED_SIZE;
+               $this->writeConcern = self::WC_ACKNOWLEDGED;
+               $this->writeConcernJournaled = self::WC_JOURNALED;
+               $this->writeConcernTimeout = self::WC_TIMEOUT;
        }
-       
+
        /**
         * Setup db connection.
         * Based on defined options, this method connects to the database and 
         * creates a {@link $collection}. 
         */
        public function activateOptions() {
+               # Building connection options.
+               $options = array(
+                       'w' => (is_numeric($this->writeConcern)) ? (int) 
$this->writeConcern : $this->writeConcern,
+                       'timeout' => $this->timeout,
+                       'wTimeout' => $this->writeConcernTimeout
+               );
+               if ($this->replicaSet !== null) {
+                       $options['replicaSet'] = $this->replicaSet;
+               }
+               if ($this->socketTimeout !== null) {
+                       $options['socketTimeoutMS'] = $this->socketTimeout;
+               }
+               # Backwards compatibility with timeout parameter.
+               if ($this->connectionTimeout !== null) {
+                       $options['connectTimeoutMS'] = $options['timeout'] = 
$this->connectionTimeout;
+               }
+
+               # Building write options.
+               $this->writeOptions = array(
+                       'w' => (is_numeric($this->writeConcern)) ? (int) 
$this->writeConcern : $this->writeConcern,
+                       'j' => $this->writeConcernJournaled
+               );
+
                try {
-                       $this->connection = new Mongo(sprintf('%s:%d', 
$this->host, $this->port), array('timeout' => $this->timeout));
+                       $clientClass = class_exists('MongoClient') ? 
'MongoClient' : 'Mongo';
+                       # Connection string generation.
+                       if ($this->connectionString === null) {
+                               $connectionString = sprintf('%s%s:%d', 
self::DEFAULT_MONGO_URL_PREFIX, $this->host, $this->port);
+                       } else {
+                               $connectionString = $this->connectionString;
+                       }
+                       $this->connection = new $clientClass($connectionString, 
$options);
                        $db     = 
$this->connection->selectDB($this->databaseName);
                        if ($this->userName !== null && $this->password !== 
null) {
                                $authResult = 
$db->authenticate($this->userName, $this->password);
@@ -175,7 +278,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
                        }
                        if ($this->capped === true) {
                                $this->collection = 
$db->createCollection($this->collectionName, $this->capped, $this->cappedSize,
-                                                                             
$this->cappedMax);
+                                                                               
                                  $this->cappedMax);
                        } else {
                                $this->collection = 
$db->selectCollection($this->collectionName);
                        }
@@ -199,13 +302,13 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        public function append(LoggerLoggingEvent $event) {
                try {
                        if ($this->collection != null) {
-                               
$this->collection->insert($this->format($event));
+                               
$this->collection->insert($this->format($event), $this->writeOptions);
                        }
                } catch (MongoCursorException $ex) {
                        $this->warn(sprintf('Error while writing to mongo 
collection: %s', $ex->getMessage()));
                }
        }
-       
+
        /**
         * Converts the logging event into an array which can be logged to 
mongodb.
         * 
@@ -236,10 +339,10 @@ class LoggerAppenderMongoDB extends LoggerAppender {
                if ($throwableInfo != null) {
                        $document['exception'] = 
$this->formatThrowable($throwableInfo->getThrowable());
                }
-               
+
                return $document;
        }
-       
+
        /**
         * Converts an Exception into an array which can be logged to mongodb.
         * 
@@ -254,14 +357,14 @@ class LoggerAppenderMongoDB extends LoggerAppender {
                        'code' => $ex->getCode(),
                        'stackTrace' => $ex->getTraceAsString(),
                );
-        
+
                if (method_exists($ex, 'getPrevious') && $ex->getPrevious() !== 
null) {
                        $array['innerException'] = 
$this->formatThrowable($ex->getPrevious());
                }
-               
+
                return $array;
        }
-               
+
        /**
         * Closes the connection to the logging database
         */
@@ -275,18 +378,31 @@ class LoggerAppenderMongoDB extends LoggerAppender {
                        $this->closed = true;
                }
        }
-       
-       /** 
+
+       /**
+        * Sets the value of {@link $connectionString}.
+        * @param string $connectionString
+        */
+       public function setConnectionString($connectionString) {
+               $this->setString('connectionString', $connectionString);
+       }
+
+       /**
+        * Returns the value of {@link $connectionString}.
+        * @return string
+        */
+       public function getConnectionString() {
+               return $this->connectionString;
+       }
+
+       /**
         * Sets the value of {@link $host} parameter.
         * @param string $host
         */
        public function setHost($host) {
-               if (!preg_match('/^mongodb\:\/\//', $host)) {
-                       $host = self::DEFAULT_MONGO_URL_PREFIX . $host;
-               }
                $this->setString('host', $host);
        }
-               
+
        /** 
         * Returns the value of {@link $host} parameter.
         * @return string
@@ -302,7 +418,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        public function setPort($port) {
                $this->setPositiveInteger('port', $port);
        }
-               
+
        /** 
         * Returns the value of {@link $port} parameter.
         * @return int
@@ -318,7 +434,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        public function setDatabaseName($databaseName) {
                $this->setString('databaseName', $databaseName);
        }
-               
+
        /** 
         * Returns the value of {@link $databaseName} parameter.
         * @return string
@@ -334,7 +450,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        public function setCollectionName($collectionName) {
                $this->setString('collectionName', $collectionName);
        }
-               
+
        /** 
         * Returns the value of {@link $collectionName} parameter.
         * @return string
@@ -350,7 +466,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        public function setUserName($userName) {
                $this->setString('userName', $userName, true);
        }
-       
+
        /** 
         * Returns the value of {@link $userName} parameter.
         * @return string
@@ -366,7 +482,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        public function setPassword($password) {
                $this->setString('password', $password, true);
        }
-               
+
        /** 
         * Returns the value of {@link $password} parameter.
         * @return string 
@@ -375,8 +491,9 @@ class LoggerAppenderMongoDB extends LoggerAppender {
                return $this->password;
        }
 
-       /** 
+       /**
         * Sets the value of {@link $timeout} parameter.
+        * @deprecated Use {@link $connectionTimeout} and {@link 
$socketTimeout} instead.
         * @param int $timeout
         */
        public function setTimeout($timeout) {
@@ -385,6 +502,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
 
        /** 
         * Returns the value of {@link $timeout} parameter.
+        * @deprecated Use {@link $connectionTimeout} and {@link 
$socketTimeout} instead.
         * @return int
         */
        public function getTimeout() {
@@ -440,13 +558,109 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        }
 
        /**
+        * Sets the value of {@link $writeConcern} parameter.
+        * @param string $writeConcern
+        */
+       public function setWriteConcern($writeConcern) {
+               $this->setString('writeConcern', $writeConcern);
+       }
+
+       /**
+        * Returns the value of {@link $writeConcern} parameter.
+        * @return string
+        */
+       public function getWriteConcern() {
+               return $this->writeConcern;
+       }
+
+       /**
+        * Sets the value of {@link $writeConcernJournaled} parameter.
+        * @param bool $writeConcernJournaled
+        */
+       public function setWriteConcernJournaled($writeConcernJournaled) {
+               $this->setBoolean('writeConcernJournaled', 
$writeConcernJournaled);
+       }
+
+       /**
+        * Returns the value of {@link $writeConcernJournaled} parameter.
+        * @return bool
+        */
+       public function getWriteConcernJournaled() {
+               return $this->writeConcernJournaled;
+       }
+
+       /**
+        * Sets the value of {@link $writeConcernTimeout} parameter.
+        * @param int $writeConcernTimeout
+        */
+       public function setWriteConcernTimeout($writeConcernTimeout) {
+               $this->setPositiveInteger('writeConcernTimeout', 
$writeConcernTimeout);
+       }
+
+       /**
+        * Returns the value of {@link $writeConcernTimeout} parameter.
+        * @return int
+        */
+       public function getWriteConcernTimeout() {
+               return $this->writeConcernTimeout;
+       }
+
+       /**
+        * Sets the value of {@link $connectionTimeout} parameter.
+        * @param int $connectionTimeout
+        */
+       public function setConnectionTimeout($connectionTimeout) {
+               $this->setPositiveInteger('connectionTimeout', 
$connectionTimeout);
+       }
+
+       /**
+        * Returns the value of {@link $connectionTimeout} parameter.
+        * @return int
+        */
+       public function getConnectionTimeout() {
+               return $this->connectionTimeout;
+       }
+
+       /**
+        * Sets the value of {@link $socketTimeout} parameter.
+        * @param int $socketTimeout
+        */
+       public function setSocketTimeout($socketTimeout) {
+               $this->setPositiveInteger('socketTimeout', $socketTimeout);
+       }
+
+       /**
+        * Returns the value of {@link $socketTimeout} parameter.
+        * @return int
+        */
+       public function getSocketTimeout() {
+               return $this->socketTimeout;
+       }
+
+       /**
+        * Sets the value of {@link $replicaSet} parameter.
+        * @param string $replicaSet
+        */
+       public function setReplicaSet($replicaSet) {
+               $this->setString('replicaSet', $replicaSet);
+       }
+
+       /**
+        * Returns the value of {@link $replicaSet} parameter.
+        * @return string
+        */
+       public function getReplicaSet() {
+               return $this->replicaSet;
+       }
+
+       /**
         * Returns the mongodb connection.
         * @return Mongo
         */
        public function getConnection() {
                return $this->connection;
        }
-       
+
        /** 
         * Returns the active mongodb collection.
         * @return MongoCollection
@@ -454,4 +668,4 @@ class LoggerAppenderMongoDB extends LoggerAppender {
        public function getCollection() {
                return $this->collection;
        }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4php/blob/f6d602f4/src/test/php/appenders/LoggerAppenderMongoDBTest.php
----------------------------------------------------------------------
diff --git a/src/test/php/appenders/LoggerAppenderMongoDBTest.php 
b/src/test/php/appenders/LoggerAppenderMongoDBTest.php
index fe7a62c..3be6c9c 100644
--- a/src/test/php/appenders/LoggerAppenderMongoDBTest.php
+++ b/src/test/php/appenders/LoggerAppenderMongoDBTest.php
@@ -31,12 +31,12 @@
  * @group appenders
  */
 class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
-               
+
        protected $appender;
        protected $event;
-       
+
        protected function setUp() {
-               if (!extension_loaded('mongo')) {
+               if (!extension_loaded('Mongo')) {
                        $this->markTestSkipped(
                                'The Mongo extension is not available.'
                        );
@@ -54,7 +54,14 @@ class LoggerAppenderMongoDBTest extends 
PHPUnit_Framework_TestCase {
                }
                unset($this->appender);
        }
-       
+
+       public function testConnectionString() {
+               $expected = 'mongodb://localhost,localhost';
+               $this->appender->setConnectionString($expected);
+               $result = $this->appender->getConnectionString();
+               $this->assertEquals($expected, $result);
+       }
+
        public function testHost() {
                $expected = 'mongodb://localhost';
                $this->appender->setHost($expected);
@@ -125,9 +132,52 @@ class LoggerAppenderMongoDBTest extends 
PHPUnit_Framework_TestCase {
                $this->assertEquals($expected, $result);
        }
 
+       public function testWriteConcern() {
+               $expected = 7;
+               $this->appender->setWriteConcern($expected);
+               $result = $this->appender->getWriteConcern();
+               $this->assertEquals($expected, $result);
+       }
+
+       public function testWriteConcernJournaled() {
+               $expected = true;
+               $this->appender->setWriteConcernJournaled($expected);
+               $result = $this->appender->getWriteConcernJournaled();
+               $this->assertEquals($expected, $result);
+       }
+
+
+       public function testWriteConcernTimeout() {
+               $expected = 100;
+               $this->appender->setWriteConcernTimeout($expected);
+               $result = $this->appender->getWriteConcernTimeout();
+               $this->assertEquals($expected, $result);
+       }
+
+       public function testConnectionTimeout() {
+               $expected = 200;
+               $this->appender->setConnectionTimeout($expected);
+               $result = $this->appender->getConnectionTimeout();
+               $this->assertEquals($expected, $result);
+       }
+
+       public function testSocketTimeout() {
+               $expected = 300;
+               $this->appender->setSocketTimeout($expected);
+               $result = $this->appender->getSocketTimeout();
+               $this->assertEquals($expected, $result);
+       }
+
+       public function testReplicaSet() {
+               $expected = 'replica_set';
+               $this->appender->setReplicaSet($expected);
+               $result = $this->appender->getReplicaSet();
+               $this->assertEquals($expected, $result);
+       }
+
        public function testActivateOptions() {
                $this->appender->activateOptions();
-               $this->assertInstanceOf('Mongo', 
$this->appender->getConnection());
+               $this->assertInstanceOf('MongoClient', 
$this->appender->getConnection());
                $this->assertInstanceOf('MongoCollection', 
$this->appender->getCollection());
        }
 
@@ -135,7 +185,7 @@ class LoggerAppenderMongoDBTest extends 
PHPUnit_Framework_TestCase {
                $this->appender->setUserName(null);
                $this->appender->setPassword(null);
                $this->appender->activateOptions();
-               $this->assertInstanceOf('Mongo', 
$this->appender->getConnection());
+               $this->assertInstanceOf('MongoClient', 
$this->appender->getConnection());
                $this->assertInstanceOf('MongoCollection', 
$this->appender->getCollection());
        }
 
@@ -143,7 +193,7 @@ class LoggerAppenderMongoDBTest extends 
PHPUnit_Framework_TestCase {
                $this->appender->setCollectionName('logs_capped');
                $this->appender->setCapped(true);
                $this->appender->activateOptions();
-               $this->assertInstanceOf('Mongo', 
$this->appender->getConnection());
+               $this->assertInstanceOf('MongoClient', 
$this->appender->getConnection());
                $this->assertInstanceOf('MongoCollection', 
$this->appender->getCollection());
        }
 
@@ -227,9 +277,22 @@ class LoggerAppenderMongoDBTest extends 
PHPUnit_Framework_TestCase {
                $this->assertEquals($expected, 
$this->appender->getCollection()->count());
        }
 
+       /**
+        * @expectedException PHPUnit_Framework_Error
+        */
+       public function testReplicaSetOption() {
+               $this->appender->setReplicaSet('mongo_appender_replica_set1');
+               $this->appender->activateOptions();
+       }
+
+       public function testMultipleHostsConnection() {
+               
$this->appender->setConnectionString('mongodb://locahost:27017,localhost:27017');
+               $this->appender->activateOptions();
+       }
+
        public function testClose() {
                $this->appender->activateOptions();
-               $this->assertInstanceOf('Mongo', 
$this->appender->getConnection());
+               $this->assertInstanceOf('MongoClient', 
$this->appender->getConnection());
                $this->assertInstanceOf('MongoCollection', 
$this->appender->getCollection());
                $this->appender->close();
                $this->assertNull($this->appender->getConnection());
@@ -250,4 +313,4 @@ class LoggerAppenderMongoDBTest extends 
PHPUnit_Framework_TestCase {
                $this->assertNotNull($record, 'Could not read the record from 
the database.');
                return $record;
        }
-}
+}
\ No newline at end of file

Reply via email to