From 0b1fa252b0535c2f5ad1c34ab82b59c2332c68d0 Mon Sep 17 00:00:00 2001
From: Vladimir Gorej <gorej@codescale.net>
Date: Mon, 31 Dec 2012 10:51:25 +0100
Subject: [PATCH 1/4] Set default behaviour, in case users don't have
 core.autocrlf set.

Signed-off-by: Vladimir Gorej <gorej@codescale.net>
---
 .gitattributes |    2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 .gitattributes

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..2f0cc2c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Set default behaviour, in case users don't have core.autocrlf set.
+text=auto
\ No newline at end of file
-- 
1.7.9.5


From e31835601be3a1655fc0ac6fd9bdfedb288e06e5 Mon Sep 17 00:00:00 2001
From: Vladimir Gorej <gorej@codescale.net>
Date: Mon, 31 Dec 2012 11:43:58 +0100
Subject: [PATCH 2/4] LOG4PHP-203; added support for capped collection in mongo
 appender

Capped collections are fixed-size collections that support high-throughput operations that insert,
retrieve, and delete documents based on insertion order. Capped collections work in a way similar
to circular buffers: once a collection fills its allocated space, it makes room for new documents
by overwriting the oldest documents in the collection.

Signed-off-by: Vladimir Gorej <gorej@codescale.net>
---
 src/main/php/appenders/LoggerAppenderMongoDB.php |  122 +++++++++++++++++++---
 1 file changed, 110 insertions(+), 12 deletions(-)

diff --git a/src/main/php/appenders/LoggerAppenderMongoDB.php b/src/main/php/appenders/LoggerAppenderMongoDB.php
index 43dabb8..2eccfcd 100644
--- a/src/main/php/appenders/LoggerAppenderMongoDB.php
+++ b/src/main/php/appenders/LoggerAppenderMongoDB.php
@@ -30,6 +30,9 @@
  * - **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).
+ * - **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.
  * 
  * @package log4php
  * @subpackage appenders
@@ -62,31 +65,69 @@ class LoggerAppenderMongoDB extends LoggerAppender {
 	
 	/** Default value for {@link $timeout} */
 	const DEFAULT_TIMEOUT_VALUE = 3000;
+
+	/** Default value for {@link $capped} */
+	const DEFAULT_CAPPED = false;
+
+	/** Default value for {@link $cappedMax} */
+	const DEFAULT_CAPPED_MAX = 1000;
+
+	/** Default value for {@link $cappedSize} */
+	const DEFAULT_CAPPED_SIZE = 1000000;
 	
 	// ******************************************
 	// ** Configurable parameters              **
 	// ******************************************
 	
-	/** Server on which mongodb instance is located. */
+	/** Server on which mongodb instance is located.
+	 * @var string
+	 */
 	protected $host;
 	
-	/** Port on which the instance is bound. */
+	/** Port on which the instance is bound.
+	 * @var int
+	 */
 	protected $port;
 	
-	/** Name of the database to which to log. */
+	/** Name of the database to which to log.
+	 * @var string
+	 */
 	protected $databaseName;
 	
-	/** Name of the collection within the given database. */
+	/** Name of the collection within the given database.
+	 * @var string
+	 */
 	protected $collectionName;
 			
-	/** Username used to connect to the database. */
+	/** Username used to connect to the database.
+	 * @var string
+	 */
 	protected $userName;
 	
-	/** Password used to connect to the database. */
+	/** Password used to connect to the database.
+	 * @var string
+	 */
 	protected $password;
 	
-	/** Timeout value used when connecting to the database (in milliseconds). */
+	/** Timeout value used when connecting to the database (in milliseconds).
+	 * @var int
+	 */
 	protected $timeout;
+
+	/** Whether the collection should be a fixed size.
+	 * @var bool
+	 */
+	protected $capped;
+
+	/** If the collection is fixed size, the maximum number of elements to store in the collection.
+	 * @var int
+	 */
+	protected $cappedMax;
+
+	/** If the collection is fixed size, its size in bytes.
+	 * @var int
+	 */
+	protected $cappedSize;
 	
 	// ******************************************
 	// ** Member variables                     **
@@ -112,6 +153,9 @@ class LoggerAppenderMongoDB extends LoggerAppender {
 		$this->collectionName = self::DEFAULT_COLLECTION_NAME;
 		$this->timeout = self::DEFAULT_TIMEOUT_VALUE;
 		$this->requiresLayout = false;
+		$this->capped = self::DEFAULT_CAPPED;
+		$this->cappedMax = self::DEFAULT_CAPPED_MAX;
+		$this->cappedSize = self::DEFAULT_CAPPED_SIZE;
 	}
 	
 	/**
@@ -129,10 +173,15 @@ class LoggerAppenderMongoDB extends LoggerAppender {
 					throw new Exception($authResult['errmsg'], $authResult['ok']);
 				}
 			}
-			$this->collection = $db->selectCollection($this->collectionName);
+			if ($this->capped === true) {
+				$this->collection = $db->createCollection($this->collectionName, $this->capped, $this->cappedSize,
+					                                      $this->cappedMax);
+			} else {
+				$this->collection = $db->selectCollection($this->collectionName);
+			}
 		} catch (MongoConnectionException $ex) {
 			$this->closed = true;
-			$this->warn(sprintf('Failed to connect to mongo deamon: %s', $ex->getMessage()));
+			$this->warn(sprintf('Failed to connect to mongo daemon: %s', $ex->getMessage()));
 		} catch (InvalidArgumentException $ex) {
 			$this->closed = true;
 			$this->warn(sprintf('Error while selecting mongo database: %s', $ex->getMessage()));
@@ -194,7 +243,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
 	/**
 	 * Converts an Exception into an array which can be logged to mongodb.
 	 * 
-	 * Supports innner exceptions (PHP >= 5.3)
+	 * Supports inner exceptions (PHP >= 5.3)
 	 * 
 	 * @param Exception $ex
 	 * @return array
@@ -235,7 +284,7 @@ class LoggerAppenderMongoDB extends LoggerAppender {
 		if (!preg_match('/^mongodb\:\/\//', $host)) {
 			$host = self::DEFAULT_MONGO_URL_PREFIX . $host;
 		}
-		$this->host = $host;
+		$this->setString('host', $host);
 	}
 		
 	/** 
@@ -341,7 +390,56 @@ class LoggerAppenderMongoDB extends LoggerAppender {
 	public function getTimeout() {
 		return $this->timeout;
 	}
-	/** 
+
+	/**
+	 * Sets the value of {@link $capped} parameter.
+	 * @param bool $capped
+	 */
+	public function setCapped($capped) {
+		$this->setBoolean('capped', $capped);
+	}
+
+	/**
+	 * Returns the value of {@link $capped} parameter.
+	 * @return bool
+	 */
+	public function getCapped() {
+		return $this->capped;
+	}
+
+	/**
+	 * Sets the value of {@link $cappedMax} parameter.
+	 * @param int $cappedMax
+	 */
+	public function setCappedMax($cappedMax) {
+		$this->setPositiveInteger('cappedMax', $cappedMax);
+	}
+
+	/**
+	 * Returns the value of {@link $cappedMax} parameter.
+	 * @return int
+	 */
+	public function getCappedMax() {
+		return $this->cappedMax;
+	}
+
+	/**
+	 * Sets the value of {@link $cappedSize} parameter.
+	 * @param int $cappedSize
+	 */
+	public function setCappedSize($cappedSize) {
+		$this->setPositiveInteger('cappedSize', $cappedSize);
+	}
+
+	/**
+	 * Returns the value of {@link $cappedSzie} parameter.
+	 * @return int
+	 */
+	public function getCappedSize() {
+		return $this->cappedSize;
+	}
+
+	/**
 	 * Returns the mongodb connection.
 	 * @return Mongo
 	 */
-- 
1.7.9.5


From 99f4f22f590da77f78dc1bdc23b1334c9ee87300 Mon Sep 17 00:00:00 2001
From: Vladimir Gorej <gorej@codescale.net>
Date: Mon, 31 Dec 2012 12:13:54 +0100
Subject: [PATCH 3/4] LOG4PHP-203; tests for capped collections in mongo
 appender.

Signed-off-by: Vladimir Gorej <gorej@codescale.net>
---
 .../php/appenders/LoggerAppenderMongoDBTest.php    |  138 +++++++++++++-------
 1 file changed, 90 insertions(+), 48 deletions(-)

diff --git a/src/test/php/appenders/LoggerAppenderMongoDBTest.php b/src/test/php/appenders/LoggerAppenderMongoDBTest.php
index b659a6f..b29d5b9 100644
--- a/src/test/php/appenders/LoggerAppenderMongoDBTest.php
+++ b/src/test/php/appenders/LoggerAppenderMongoDBTest.php
@@ -56,7 +56,7 @@ class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 		$result = $this->appender->getHost();
 		$this->assertEquals($expected, $result);
 	}
-	
+
 	public function testPort() {
 		$expected = 27017;
 		$this->appender->setPort($expected);
@@ -70,21 +70,21 @@ class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 		$result	= $this->appender->getDatabaseName();
 		$this->assertEquals($expected, $result);
 	}
-	
+
 	public function testCollectionName() {
 		$expected = 'logs';
 		$this->appender->setCollectionName($expected);
 		$result = $this->appender->getCollectionName();
 		$this->assertEquals($expected, $result);
 	}
-	
+
 	public function testUserName() {
 		$expected = 'char0n';
 		$this->appender->setUserName($expected);
 		$result = $this->appender->getUserName();
 		$this->assertEquals($expected, $result);
 	}
-	
+
 	public function testPassword() {
 		$expected = 'secret pass';
 		$this->appender->setPassword($expected);
@@ -99,6 +99,27 @@ class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 		$this->assertEquals($expected, $result);
 	}
 
+	public function testCapped() {
+		$expected = true;
+		$this->appender->setCapped($expected);
+		$result	= $this->appender->getCapped();
+		$this->assertEquals($expected, $result);
+	}
+
+	public function testCappedMax() {
+		$expected = 20;
+		$this->appender->setCappedMax($expected);
+		$result	= $this->appender->getCappedMax();
+		$this->assertEquals($expected, $result);
+	}
+
+	public function testCappedSize() {
+		$expected = 10000;
+		$this->appender->setCappedSize($expected);
+		$result	= $this->appender->getCappedSize();
+		$this->assertEquals($expected, $result);
+	}
+
 	public function testActivateOptions() {
 		$this->appender->activateOptions();
 		$this->assertInstanceOf('Mongo', $this->appender->getConnection());
@@ -113,19 +134,27 @@ class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 		$this->assertInstanceOf('MongoCollection', $this->appender->getCollection());
 	}
 
+	public function testActivateOptionsCappedCollection() {
+		$this->appender->setCollectionName('logs_capped');
+		$this->appender->setCapped(true);
+		$this->appender->activateOptions();
+		$this->assertInstanceOf('Mongo', $this->appender->getConnection());
+		$this->assertInstanceOf('MongoCollection', $this->appender->getCollection());
+	}
+
 	public function testFormat() {
 		$this->appender->activateOptions();
 		$record = $this->logOne($this->event);
-		
+
 		$this->assertEquals('ERROR', $record['level']);
 		$this->assertEquals('mongo logging event', $record['message']);
 		$this->assertEquals('test_mongo', $record['loggerName']);
-		
-		$this->assertEquals('NA', $record['fileName']);		
+
+		$this->assertEquals('NA', $record['fileName']);
 		$this->assertEquals('getLocationInformation', $record['method']);
 		$this->assertEquals('NA', $record['lineNumber']);
 		$this->assertEquals('LoggerLoggingEvent', $record['className']);
-		
+
 		$this->assertTrue(is_int($record['thread']));
 		$this->assertSame(getmypid(), $record['thread']);
 		$this->assertTrue(is_int($record['lineNumber']) || $record['lineNumber'] == 'NA');
@@ -141,53 +170,66 @@ class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 			microtime(true),
 			new Exception('test exception', 1)
 		);
-		
+
 		$record = $this->logOne($event);
-		
+
 		$this->assertArrayHasKey('exception', $record);
 		$this->assertEquals(1, $record['exception']['code']);
 		$this->assertEquals('test exception', $record['exception']['message']);
 		$this->assertContains('[internal function]: LoggerAppenderMongoDBTest', $record['exception']['stackTrace']);
 	}
 
-	 public function testFormatThrowableInfoWithInnerException() {
-
-		 // Skip test if PHP version is lower than 5.3.0 (no inner exception support)
-		 if (version_compare(PHP_VERSION, '5.3.0') < 0) {
-			 $this->markTestSkipped();
-		 }
-
-		 $this->appender->activateOptions();
-		 $event = new LoggerLoggingEvent(
-			 'testFqcn',
-			 new Logger('test.Logger'),
-			 LoggerLevel::getLevelWarn(),
-			 'test message',
-			 microtime(true),
-			 new Exception('test exception', 1, new Exception('test exception inner', 2))
-		 );
-
-		 $record = $this->logOne($event);
-
-		 $this->assertArrayHasKey('exception', $record);
-		 $this->assertEquals(1, $record['exception']['code']);
-		 $this->assertEquals('test exception', $record['exception']['message']);
-		 $this->assertContains('[internal function]: LoggerAppenderMongoDBTest', $record['exception']['stackTrace']);
-
-		 $this->assertArrayHasKey('innerException', $record['exception']);
-		 $this->assertEquals(2, $record['exception']['innerException']['code']);
-		 $this->assertEquals('test exception inner', $record['exception']['innerException']['message']);
-	 }
-
-
-	 public function testClose() {
-		 $this->appender->activateOptions();
-		 $this->assertInstanceOf('Mongo', $this->appender->getConnection());
-		 $this->assertInstanceOf('MongoCollection', $this->appender->getCollection());
-		 $this->appender->close();
-		 $this->assertNull($this->appender->getConnection());
-		 $this->assertNull($this->appender->getCollection());
-	 }
+	public function testFormatThrowableInfoWithInnerException() {
+		// Skip test if PHP version is lower than 5.3.0 (no inner exception support)
+		if (version_compare(PHP_VERSION, '5.3.0') < 0) {
+			$this->markTestSkipped();
+		}
+
+		$this->appender->activateOptions();
+		$event = new LoggerLoggingEvent(
+			'testFqcn',
+			new Logger('test.Logger'),
+			LoggerLevel::getLevelWarn(),
+			'test message',
+			microtime(true),
+			new Exception('test exception', 1, new Exception('test exception inner', 2))
+		);
+
+		$record = $this->logOne($event);
+
+		$this->assertArrayHasKey('exception', $record);
+		$this->assertEquals(1, $record['exception']['code']);
+		$this->assertEquals('test exception', $record['exception']['message']);
+		$this->assertContains('[internal function]: LoggerAppenderMongoDBTest', $record['exception']['stackTrace']);
+
+		$this->assertArrayHasKey('innerException', $record['exception']);
+		$this->assertEquals(2, $record['exception']['innerException']['code']);
+		$this->assertEquals('test exception inner', $record['exception']['innerException']['message']);
+	}
+
+	public function testCappedCollection() {
+		$expected = 2;
+		$this->appender->setCollectionName('logs_capped');
+		$this->appender->setCapped(true);
+		$this->appender->setCappedMax($expected);
+		$this->appender->activateOptions();
+
+		// Log 10 events into capped collection.
+		for ($i = 0; $i < 10; $i += 1) {
+			$this->appender->append($this->event);
+		}
+
+		$this->assertEquals($expected, $this->appender->getCollection()->count());
+	}
+
+	public function testClose() {
+		$this->appender->activateOptions();
+		$this->assertInstanceOf('Mongo', $this->appender->getConnection());
+		$this->assertInstanceOf('MongoCollection', $this->appender->getCollection());
+		$this->appender->close();
+		$this->assertNull($this->appender->getConnection());
+		$this->assertNull($this->appender->getCollection());
+	}
 
 	/**
 	 * Logs the event and returns the record from the database.
-- 
1.7.9.5


From 924e6bab95bd65ebbadd2a667502e330525ce6ec Mon Sep 17 00:00:00 2001
From: Vladimir Gorej <gorej@codescale.net>
Date: Mon, 31 Dec 2012 16:01:22 +0100
Subject: [PATCH 4/4] LOG4PHP-203; fixed tests for capped collections for
 mongo appender.


Signed-off-by: Vladimir Gorej <gorej@codescale.net>
---
 .../php/appenders/LoggerAppenderMongoDBTest.php    |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/test/php/appenders/LoggerAppenderMongoDBTest.php b/src/test/php/appenders/LoggerAppenderMongoDBTest.php
index b29d5b9..fe7a62c 100644
--- a/src/test/php/appenders/LoggerAppenderMongoDBTest.php
+++ b/src/test/php/appenders/LoggerAppenderMongoDBTest.php
@@ -42,11 +42,16 @@ class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 			);
 		} else {
 			$this->appender = new LoggerAppenderMongoDB('mongo_appender');
+			$this->appender->setCollectionName('log4php_mongodb_test');
 			$this->event = LoggerTestHelper::getErrorEvent('mongo logging event', 'test_mongo');
 		}
 	}
 
 	protected function tearDown() {
+		$collection = $this->appender->getCollection();
+		if ($collection !== null) {
+			$collection->drop();
+		}
 		unset($this->appender);
 	}
 	
@@ -65,7 +70,7 @@ class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 	}
 
 	public function testDatabaseName() {
-		$expected = 'log4php_mongodb';
+		$expected = 'log4php_mongodb_test';
 		$this->appender->setDatabaseName($expected);
 		$result	= $this->appender->getDatabaseName();
 		$this->assertEquals($expected, $result);
-- 
1.7.9.5

