You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ih...@apache.org on 2012/06/05 14:08:24 UTC

svn commit: r1346363 - in /logging/log4php/trunk/src: main/php/appenders/LoggerAppenderMongoDB.php test/php/appenders/LoggerAppenderMongoDBTest.php test/php/bootstrap.php

Author: ihabunek
Date: Tue Jun  5 12:08:24 2012
New Revision: 1346363

URL: http://svn.apache.org/viewvc?rev=1346363&view=rev
Log:
Improved error reporting for MongoDB appender, better docs.

Modified:
    logging/log4php/trunk/src/main/php/appenders/LoggerAppenderMongoDB.php
    logging/log4php/trunk/src/test/php/appenders/LoggerAppenderMongoDBTest.php
    logging/log4php/trunk/src/test/php/bootstrap.php

Modified: logging/log4php/trunk/src/main/php/appenders/LoggerAppenderMongoDB.php
URL: http://svn.apache.org/viewvc/logging/log4php/trunk/src/main/php/appenders/LoggerAppenderMongoDB.php?rev=1346363&r1=1346362&r2=1346363&view=diff
==============================================================================
--- logging/log4php/trunk/src/main/php/appenders/LoggerAppenderMongoDB.php (original)
+++ logging/log4php/trunk/src/main/php/appenders/LoggerAppenderMongoDB.php Tue Jun  5 12:08:24 2012
@@ -23,9 +23,13 @@
  * 
  * ## Configurable parameters: ##
  * 
- * 
- * @link http://github.com/log4mongo/log4mongo-php Vladimir Gorej's original submission.
- * @link http://www.mongodb.org/ MongoDB website.
+ * - **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).
  * 
  * @version $Revision$
  * @package log4php
@@ -33,6 +37,8 @@
  * @since 2.1
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  * @link http://logging.apache.org/log4php/docs/appenders/mongodb.html Appender documentation
+ * @link http://github.com/log4mongo/log4mongo-php Vladimir Gorej's original submission.
+ * @link http://www.mongodb.org/ MongoDB website.
  */
 class LoggerAppenderMongoDB extends LoggerAppender {
 	
@@ -99,15 +105,6 @@ class LoggerAppenderMongoDB extends Logg
 	 */
 	protected $collection;
 
-	/** 
-	 * Set to true if the appender can append. 
-	 * @todo Maybe we should use $closed here instead? 
-	 */
-	protected $canAppend = false;
-	
-	/** Appender does not require a layout. */
-	protected $requiresLayout = false;
-		
 	public function __construct($name = '') {
 		parent::__construct($name);
 		$this->host = self::DEFAULT_MONGO_URL_PREFIX . self::DEFAULT_MONGO_HOST;
@@ -115,18 +112,17 @@ class LoggerAppenderMongoDB extends Logg
 		$this->databaseName = self::DEFAULT_DB_NAME;
 		$this->collectionName = self::DEFAULT_COLLECTION_NAME;
 		$this->timeout = self::DEFAULT_TIMEOUT_VALUE;
+		$this->requiresLayout = false;
 	}
 	
 	/**
 	 * Setup db connection.
 	 * Based on defined options, this method connects to the database and 
 	 * creates a {@link $collection}. 
-	 *  
-	 * @throws Exception if the attempt to connect to the requested database fails.
 	 */
 	public function activateOptions() {
 		try {
-			$this->connection = new Mongo(sprintf('%s:%d', $this->host, $this->port), array("timeout" => $this->timeout));
+			$this->connection = new Mongo(sprintf('%s:%d', $this->host, $this->port), array('timeout' => $this->timeout));
 			$db	= $this->connection->selectDB($this->databaseName);
 			if ($this->userName !== null && $this->password !== null) {
 				$authResult = $db->authenticate($this->userName, $this->password);
@@ -134,25 +130,31 @@ class LoggerAppenderMongoDB extends Logg
 					throw new Exception($authResult['errmsg'], $authResult['ok']);
 				}
 			}
-			
-			$this->collection = $db->selectCollection($this->collectionName);												 
+			$this->collection = $db->selectCollection($this->collectionName);
+		} catch (MongoConnectionException $ex) {
+			$this->closed = true;
+			$this->warn(sprintf('Failed to connect to mongo deamon: %s', $ex->getMessage()));
+		} catch (InvalidArgumentException $ex) {
+			$this->closed = true;
+			$this->warn(sprintf('Error while selecting mongo database: %s', $ex->getMessage()));
 		} catch (Exception $ex) {
-			$this->canAppend = false;
-			throw new LoggerException($ex);
-		} 
-			
-		$this->canAppend = true;
-	}		 
-	
+			$this->closed = true;
+			$this->warn('Invalid credentials for mongo database authentication');
+		}
+	}
+
 	/**
 	 * Appends a new event to the mongo database.
-	 * 
-	 * @throws LoggerException If the pattern conversion or the INSERT statement fails.
+	 *
+	 * @param LoggerLoggingEvent $event
 	 */
 	public function append(LoggerLoggingEvent $event) {
-		if ($this->canAppend == true && $this->collection != null) {
-			$document = $this->format($event);
-			$this->collection->insert($document);			
+		try {
+			if ($this->collection != null) {
+				$this->collection->insert($this->format($event));
+			}
+		} catch (MongoCursorException $ex) {
+			$this->warn(sprintf('Error while writing to mongo collection: %s', $ex->getMessage()));
 		}
 	}
 	
@@ -163,23 +165,23 @@ class LoggerAppenderMongoDB extends Logg
 	 * @return array The array representation of the logging event.
 	 */
 	protected function format(LoggerLoggingEvent $event) {
-		$timestampSec  = (int) $event->getTimestamp();
+		$timestampSec = (int) $event->getTimestamp();
 		$timestampUsec = (int) (($event->getTimestamp() - $timestampSec) * 1000000);
 
 		$document = array(
-			'timestamp'  => new MongoDate($timestampSec, $timestampUsec),
-			'level'      => $event->getLevel()->toString(),
-			'thread'     => (int) $event->getThreadName(),
-			'message'    => $event->getMessage(),
+			'timestamp' => new MongoDate($timestampSec, $timestampUsec),
+			'level' => $event->getLevel()->toString(),
+			'thread' => (int) $event->getThreadName(),
+			'message' => $event->getMessage(),
 			'loggerName' => $event->getLoggerName() 
 		);	
 
 		$locationInfo = $event->getLocationInformation();
 		if ($locationInfo != null) {
-			$document['fileName']   = $locationInfo->getFileName();
-			$document['method']     = $locationInfo->getMethodName();
+			$document['fileName'] = $locationInfo->getFileName();
+			$document['method'] = $locationInfo->getMethodName();
 			$document['lineNumber'] = ($locationInfo->getLineNumber() == 'NA') ? 'NA' : (int) $locationInfo->getLineNumber();
-			$document['className']  = $locationInfo->getClassName();
+			$document['className'] = $locationInfo->getClassName();
 		}	
 
 		$throwableInfo = $event->getThrowableInformation();
@@ -200,15 +202,15 @@ class LoggerAppenderMongoDB extends Logg
 	 */
 	protected function formatThrowable(Exception $ex) {
 		$array = array(				
-			'message'    => $ex->getMessage(),
-			'code'       => $ex->getCode(),
+			'message' => $ex->getMessage(),
+			'code' => $ex->getCode(),
 			'stackTrace' => $ex->getTraceAsString(),
 		);
-                        
+        
 		if (method_exists($ex, 'getPrevious') && $ex->getPrevious() !== null) {
 			$array['innerException'] = $this->formatThrowable($ex->getPrevious());
 		}
-			
+		
 		return $array;
 	}
 		
@@ -220,13 +222,16 @@ class LoggerAppenderMongoDB extends Logg
 			$this->collection = null;
 			if ($this->connection !== null) {
 				$this->connection->close();
-				$this->connection = null;	
-			}					
+				$this->connection = null;
+			}
 			$this->closed = true;
 		}
 	}
 	
-	/** Sets the value of {@link $host} parameter. */
+	/** 
+	 * 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;
@@ -234,67 +239,106 @@ class LoggerAppenderMongoDB extends Logg
 		$this->host = $host;
 	}
 		
-	/** Returns the value of {@link $host} parameter. */
+	/** 
+	 * Returns the value of {@link $host} parameter.
+	 * @return string
+	 */
 	public function getHost() {
 		return $this->host;
 	}
-		
-	/** Sets the value of {@link $port} parameter. */
+
+	/** 
+	 * Sets the value of {@link $port} parameter.
+	 * @param int $port
+	 */
 	public function setPort($port) {
 		$this->setPositiveInteger('port', $port);
 	}
 		
-	/** Returns the value of {@link $port} parameter. */
+	/** 
+	 * Returns the value of {@link $port} parameter.
+	 * @return int
+	 */
 	public function getPort() {
 		return $this->port;
 	}
-		
-	/** Sets the value of {@link $databaseName} parameter. */
+
+	/** 
+	 * Sets the value of {@link $databaseName} parameter.
+	 * @param string $databaseName
+	 */
 	public function setDatabaseName($databaseName) {
 		$this->setString('databaseName', $databaseName);
 	}
 		
-	/** Returns the value of {@link $databaseName} parameter. */
+	/** 
+	 * Returns the value of {@link $databaseName} parameter.
+	 * @return string
+	 */
 	public function getDatabaseName() {
 		return $this->databaseName;
 	}
-	
-	/** Sets the value of {@link $collectionName} parameter. */
+
+	/** 
+	 * Sets the value of {@link $collectionName} parameter.
+	 * @param string $collectionName
+	 */
 	public function setCollectionName($collectionName) {
 		$this->setString('collectionName', $collectionName);
 	}
 		
-	/** Returns the value of {@link $collectionName} parameter. */
+	/** 
+	 * Returns the value of {@link $collectionName} parameter.
+	 * @return string
+	 */
 	public function getCollectionName() {
 		return $this->collectionName;
 	}
-		
-	/** Sets the value of {@link $userName} parameter. */
+
+	/** 
+	 * Sets the value of {@link $userName} parameter.
+	 * @param string $userName
+	 */
 	public function setUserName($userName) {
 		$this->setString('userName', $userName, true);
 	}
 	
-	/** Returns the value of {@link $userName} parameter. */
+	/** 
+	 * Returns the value of {@link $userName} parameter.
+	 * @return string
+	 */
 	public function getUserName() {
 		return $this->userName;
 	}
-		
-	/** Sets the value of {@link $password} parameter. */
+
+	/** 
+	 * Sets the value of {@link $password} parameter.
+	 * @param string $password
+	 */
 	public function setPassword($password) {
 		$this->setString('password', $password, true);
 	}
 		
-	/** Returns the value of {@link $password} parameter. */
+	/** 
+	 * Returns the value of {@link $password} parameter.
+	 * @return string 
+	 */
 	public function getPassword() {
 		return $this->password;
 	}
-	
-	/** Sets the value of {@link $timeout} parameter. */
+
+	/** 
+	 * Sets the value of {@link $timeout} parameter.
+	 * @param int $timeout
+	 */
 	public function setTimeout($timeout) {
 		$this->setPositiveInteger('timeout', $timeout);
 	}
 
-	/** Returns the value of {@link $timeout} parameter. */
+	/** 
+	 * Returns the value of {@link $timeout} parameter.
+	 * @return int
+	 */
 	public function getTimeout() {
 		return $this->timeout;
 	}

Modified: logging/log4php/trunk/src/test/php/appenders/LoggerAppenderMongoDBTest.php
URL: http://svn.apache.org/viewvc/logging/log4php/trunk/src/test/php/appenders/LoggerAppenderMongoDBTest.php?rev=1346363&r1=1346362&r2=1346363&view=diff
==============================================================================
--- logging/log4php/trunk/src/test/php/appenders/LoggerAppenderMongoDBTest.php (original)
+++ logging/log4php/trunk/src/test/php/appenders/LoggerAppenderMongoDBTest.php Tue Jun  5 12:08:24 2012
@@ -33,95 +33,107 @@
  */
 class LoggerAppenderMongoDBTest extends PHPUnit_Framework_TestCase {
 		
-	protected static $appender;
-	protected static $event;
-	
-	public static function setUpBeforeClass() {
-		self::$appender = new LoggerAppenderMongoDB('mongo_appender');
-		self::$event = new LoggerLoggingEvent("LoggerAppenderMongoDBTest", new Logger("test.Logger"), LoggerLevel::getLevelError(), "testmessage");
-	}
-	
-	public static function tearDownAfterClass() {
-		self::$appender->close();
-		self::$appender = null;
-		self::$event = null;
-	}
+	protected $appender;
+	protected $event;
 	
 	protected function setUp() {
 		if (!extension_loaded('mongo')) {
 			$this->markTestSkipped(
 				'The Mongo extension is not available.'
 			);
+		} else {
+			$this->appender = new LoggerAppenderMongoDB('mongo_appender');
+			$this->event = LoggerTestHelper::getErrorEvent('mongo logging event', 'test_mongo');
 		}
 	}
+
+	protected function tearDown() {
+		unset($this->appender);
+	}
 	
 	public function testHost() {
 		$expected = 'mongodb://localhost';
-		self::$appender->setHost($expected);
-		$result = self::$appender->getHost();
-		self::assertEquals($expected, $result);
+		$this->appender->setHost($expected);
+		$result = $this->appender->getHost();
+		$this->assertEquals($expected, $result);
 	}
 	
 	public function testPort() {
 		$expected = 27017;
-		self::$appender->setPort($expected);
-		$result = self::$appender->getPort();
-		self::assertEquals($expected, $result);
+		$this->appender->setPort($expected);
+		$result = $this->appender->getPort();
+		$this->assertEquals($expected, $result);
 	}
 
 	public function testDatabaseName() {
 		$expected = 'log4php_mongodb';
-		self::$appender->setDatabaseName($expected);
-		$result	= self::$appender->getDatabaseName();
-		self::assertEquals($expected, $result);
+		$this->appender->setDatabaseName($expected);
+		$result	= $this->appender->getDatabaseName();
+		$this->assertEquals($expected, $result);
 	}
 	
 	public function testCollectionName() {
 		$expected = 'logs';
-		self::$appender->setCollectionName($expected);
-		$result = self::$appender->getCollectionName();
-		self::assertEquals($expected, $result);
+		$this->appender->setCollectionName($expected);
+		$result = $this->appender->getCollectionName();
+		$this->assertEquals($expected, $result);
 	}
 	
 	public function testUserName() {
 		$expected = 'char0n';
-		self::$appender->setUserName($expected);
-		$result = self::$appender->getUserName();
-		self::assertEquals($expected, $result);
+		$this->appender->setUserName($expected);
+		$result = $this->appender->getUserName();
+		$this->assertEquals($expected, $result);
 	}
 	
 	public function testPassword() {
 		$expected = 'secret pass';
-		self::$appender->setPassword($expected);
-		$result	= self::$appender->getPassword();
-		self::assertEquals($expected, $result);
+		$this->appender->setPassword($expected);
+		$result	= $this->appender->getPassword();
+		$this->assertEquals($expected, $result);
 	}
-	
+
+	public function testTimeout() {
+		$expected = 4000;
+		$this->appender->setTimeout($expected);
+		$result	= $this->appender->getTimeout();
+		$this->assertEquals($expected, $result);
+	}
+
+	public function testActivateOptions() {
+		$this->appender->activateOptions();
+		$this->assertInstanceOf('Mongo', $this->appender->getConnection());
+		$this->assertInstanceOf('MongoCollection', $this->appender->getCollection());
+	}
+
 	public function testActivateOptionsNoCredentials() {
-		self::$appender->setUserName(null);
-		self::$appender->setPassword(null);
-		self::$appender->activateOptions();
-	}		
-	
+		$this->appender->setUserName(null);
+		$this->appender->setPassword(null);
+		$this->appender->activateOptions();
+		$this->assertInstanceOf('Mongo', $this->appender->getConnection());
+		$this->assertInstanceOf('MongoCollection', $this->appender->getCollection());
+	}
+
 	public function testFormat() {
-		$event = LoggerTestHelper::getErrorEvent("testmessage");
-		$record = $this->logOne($event);
+		$this->appender->activateOptions();
+		$record = $this->logOne($this->event);
 		
-		self::assertEquals('ERROR', $record['level']);
-		self::assertEquals('testmessage', $record['message']);
-		self::assertEquals('test', $record['loggerName']);
-		
-		self::assertEquals('NA', $record['fileName']);		
-		self::assertEquals('getLocationInformation', $record['method']);
-		self::assertEquals('NA', $record['lineNumber']);
-		self::assertEquals('LoggerLoggingEvent', $record['className']);
-		
-		self::assertTrue(is_int($record['thread']));
-		self::assertSame(getmypid(), $record['thread']);
-		self::assertTrue(is_int($record['lineNumber']) || $record['lineNumber'] == 'NA');
+		$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('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');
 	}
-	
+
 	public function testFormatThrowableInfo() {
+		$this->appender->activateOptions();
 		$event = new LoggerLoggingEvent(
 			'testFqcn',
 			new Logger('test.Logger'),
@@ -133,66 +145,63 @@ class LoggerAppenderMongoDBTest extends 
 		
 		$record = $this->logOne($event);
 		
-		self::assertArrayHasKey('exception', $record);
-		self::assertEquals(1, $record['exception']['code']);
-		self::assertEquals('test exception', $record['exception']['message']);
-		self::assertContains('[internal function]: LoggerAppenderMongoDBTest', $record['exception']['stackTrace']);
+		$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();
-		}
-		
-		$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);
 
-		self::assertArrayHasKey('exception', $record);
-		self::assertEquals(1, $record['exception']['code']);
-		self::assertEquals('test exception', $record['exception']['message']);
-		self::assertContains('[internal function]: LoggerAppenderMongoDBTest', $record['exception']['stackTrace']);
-		
-		self::assertTrue(array_key_exists('innerException', $record['exception']));
-		self::assertEquals(2, $record['exception']['innerException']['code']);
-		self::assertEquals('test exception inner', $record['exception']['innerException']['message']);
-	}
-	
-	public function testClose() {
-		self::$appender->close();
-	}
-	
-	/** Logs the event and returns the record from the database. */
+	 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());
+	 }
+
+	/**
+	 * Logs the event and returns the record from the database.
+	 * @param LoggerLoggingEvent $event
+	 * @return array
+	 */
 	private function logOne($event)
 	{
-		$appender = new LoggerAppenderMongoDB();
-		$appender->setHost('localhost');
-		$appender->activateOptions();
-		
-		$mongo = $appender->getConnection();
-		$collection = $mongo->log4php_mongodb->logs;
-		
-		$result = $collection->drop();
-		self::assertSame((float) 1, $result['ok'], "Could not clear the collection before logging.");
-		
-		$appender->append($event);
-		
+		$collection = $this->appender->getCollection();
+		$collection->drop();
+		$this->appender->append($event);
 		$record = $collection->findOne();
-		self::assertNotNull($record, "Could not read the record from the database.");
-		
-		$appender->close();
-		
+		$this->assertNotNull($record, 'Could not read the record from the database.');
 		return $record;
 	}
-	
 }
-?>
\ No newline at end of file

Modified: logging/log4php/trunk/src/test/php/bootstrap.php
URL: http://svn.apache.org/viewvc/logging/log4php/trunk/src/test/php/bootstrap.php?rev=1346363&r1=1346362&r2=1346363&view=diff
==============================================================================
--- logging/log4php/trunk/src/test/php/bootstrap.php (original)
+++ logging/log4php/trunk/src/test/php/bootstrap.php Tue Jun  5 12:08:24 2012
@@ -41,4 +41,5 @@ $confDir = dirname(__FILE__) . '/../reso
 define('PHPUNIT_CONFIG_DIR', realpath($confDir));
 
 require dirname(__FILE__) . '/../../main/php/Logger.php';
+require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'LoggerTestHelper.php';