You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4php-dev@logging.apache.org by gr...@apache.org on 2009/05/07 08:29:31 UTC

svn commit: r772512 - in /incubator/log4php/trunk/src: main/php/LoggerManager.php main/php/appenders/LoggerAppenderPDO.php test/php/appenders/LoggerAppenderPDOTest.php

Author: grobmeier
Date: Thu May  7 06:29:28 2009
New Revision: 772512

URL: http://svn.apache.org/viewvc?rev=772512&view=rev
Log:
#LOG4PHP-30: Added new appender which uses the the PDO extension (plus test)

Added:
    incubator/log4php/trunk/src/main/php/appenders/LoggerAppenderPDO.php
    incubator/log4php/trunk/src/test/php/appenders/LoggerAppenderPDOTest.php
Modified:
    incubator/log4php/trunk/src/main/php/LoggerManager.php

Modified: incubator/log4php/trunk/src/main/php/LoggerManager.php
URL: http://svn.apache.org/viewvc/incubator/log4php/trunk/src/main/php/LoggerManager.php?rev=772512&r1=772511&r2=772512&view=diff
==============================================================================
--- incubator/log4php/trunk/src/main/php/LoggerManager.php (original)
+++ incubator/log4php/trunk/src/main/php/LoggerManager.php Thu May  7 06:29:28 2009
@@ -61,6 +61,7 @@
 		'LoggerRoot' => '/LoggerRoot.php',
 		'LoggerAppender' => '/LoggerAppender.php',
 		'LoggerAppenderAdodb' => '/appenders/LoggerAppenderAdodb.php',
+		'LoggerAppenderPDO' => '/appenders/LoggerAppenderPDO.php',
 		'LoggerAppenderConsole' => '/appenders/LoggerAppenderConsole.php',
 		'LoggerAppenderDailyFile' => '/appenders/LoggerAppenderDailyFile.php',
 		'LoggerAppenderDb' => '/appenders/LoggerAppenderDb.php',

Added: incubator/log4php/trunk/src/main/php/appenders/LoggerAppenderPDO.php
URL: http://svn.apache.org/viewvc/incubator/log4php/trunk/src/main/php/appenders/LoggerAppenderPDO.php?rev=772512&view=auto
==============================================================================
--- incubator/log4php/trunk/src/main/php/appenders/LoggerAppenderPDO.php (added)
+++ incubator/log4php/trunk/src/main/php/appenders/LoggerAppenderPDO.php Thu May  7 06:29:28 2009
@@ -0,0 +1,206 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Appends log events to a db table using PDO
+ *
+ * <p>This appender uses a table in a database to log events.</p>
+ * <p>Parameters are {@link $host}, {@link $user}, {@link $password},
+ * {@link $database}, {@link $createTable}, {@link $table} and {@link $sql}.</p>
+ *
+ * @package log4php
+ * @subpackage appenders
+ * @since 2.0
+ */
+class LoggerAppenderPDO extends LoggerAppender {
+    /** Create the log table if it does not exists (optional). */
+	private $createTable = true;
+    
+    /** Database user name */
+    private $user = '';
+    
+    /** Database password */
+    private $password = '';
+    
+    /** Name of the database to connect to */
+    private $database;
+	
+	/** DSN string for enabling a connection */    
+    private $dsn;
+    
+    /** A {@link LoggerPatternLayout} string used to format a valid insert query (mandatory) */
+    private $sql;
+    
+    /** Table name to write events. Used only if {@link $createTable} is true. */    
+    private $table = 'log4php_log';
+    
+    /** The instance */
+    private $db = null;
+    
+    /** boolean used to check if all conditions to append are true */
+    private $canAppend = true;
+    
+    /**
+     * Constructor.
+     * This apender doesn't require a layout.
+     * @param string $name appender name
+     */
+    function __construct($name) {
+        parent::__construct($name);
+        $this->requiresLayout = false;
+    }
+
+    /**
+     * Setup db connection.
+     * Based on defined options, this method connects to db defined in {@link $dsn}
+     * and creates a {@link $table} table if {@link $createTable} is true.
+     * @return boolean true if all ok.
+     */
+    public function activateOptions() {
+    	$this->db = new PDO($this->dsn,$this->password,$this->password);
+		
+		if($this->db == null) {
+			$this->db = null;
+			$this->closed = true;
+			$this->canAppend = false;
+			return;
+			// TODO throw exception instead?
+		}
+		
+        // test if log table exists
+        $result = $this->db->query('select * from ' . $this->table . ' where 1 = 0');
+        if ($result == false and $this->createTable) {
+        	// TODO mysql syntax?
+            $query = "CREATE TABLE {$this->table} (	 timestamp varchar(32)," .
+            										"logger varchar(32)," .
+            										"level varchar(32)," .
+            										"message varchar(64)," .
+            										"thread varchar(32)," .
+            										"file varchar(64)," .
+            										"line varchar(4) );";
+
+            $result = $this->db->query($query);
+            if (!$result) {
+                $this->canAppend = false;
+                return;
+                // TODO throw exception?
+            }
+        }
+        
+        if($this->sql == '' || $this->sql == null) {
+            $this->sql = "INSERT INTO $this->table ( timestamp, " .
+            										"logger, " .
+            										"level, " .
+            										"message, " .
+            										"thread, " .
+            										"file, " .
+            										"line" .
+						 ") VALUES ('%d','%c','%p','%m','%t','%F','%L')";
+        }
+        
+		$this->layout = LoggerLayout::factory('LoggerPatternLayout');
+        $this->layout->setConversionPattern($this->sql);
+        $this->canAppend = true;
+        return true;
+    }
+    
+    /**
+     * Appends a new event to the database using the sql format.
+     */
+    public function append($event) {
+        if ($this->canAppend) {
+            $query = $this->layout->format($event);
+            $this->db->exec($query);
+        }
+    }
+    
+    /**
+     * Closes the connection to the logging database
+     */
+    public function close() {
+        if ($this->db !== null) {
+            $db = null;
+        }
+        $this->closed = true;
+    }
+    
+    /**
+     * Indicator if the logging table should be created on startup,
+     * if its not existing.
+     */
+    public function setCreateTable($flag) {
+        $this->createTable = LoggerOptionConverter::toBoolean($flag, true);
+    }
+   
+   	/**
+     * Sets the username for this connection. 
+     * Defaults to ''
+     */
+    function setUser($newUser) {
+        $this->user = $newUser;
+    }
+    
+    /**
+     * Sets the password for this connection. 
+     * Defaults to ''
+     */
+    public function setPassword($newPassword) {
+        $this->password = $newPassword;
+    }
+    
+    /**
+     * Sets the SQL string into which the event should be transformed.
+     * Defaults to:
+     * 
+     * INSERT INTO $this->table 
+     * ( timestamp, logger, level, message, thread, file, line) 
+     * VALUES 
+     * ('%d','%c','%p','%m','%t','%F','%L')
+     * 
+     * It's not necessary to change this except you have customized logging'
+     */
+    public function setSql($sql) {
+        $this->sql = $sql;    
+    }
+    
+    /**
+     * Sets the tablename to which this appender should log.
+     * Defaults to log4php_log
+     */
+    public function setTable($table) {
+        $this->table = $table;
+    }
+    
+    /**
+     * Sets the DSN string for this connection. In case of
+     * SQLite it could look like this: 'sqlite:appenders/pdotest.sqlite'
+     */
+    public function setDSN($dsn) {
+        $this->dsn = $dsn;
+    }
+    
+    /**
+     * Sometimes databases allow only one connection to themselves in one thread.
+     * SQLite has this behaviour. In that case this handle is needed if the database
+     * must be checked for events
+     */
+    public function getDatabaseHandle() {
+        return $this->db;
+    }
+}
+

Added: incubator/log4php/trunk/src/test/php/appenders/LoggerAppenderPDOTest.php
URL: http://svn.apache.org/viewvc/incubator/log4php/trunk/src/test/php/appenders/LoggerAppenderPDOTest.php?rev=772512&view=auto
==============================================================================
--- incubator/log4php/trunk/src/test/php/appenders/LoggerAppenderPDOTest.php (added)
+++ incubator/log4php/trunk/src/test/php/appenders/LoggerAppenderPDOTest.php Thu May  7 06:29:28 2009
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @category   tests   
+ * @package    log4php
+ * @subpackage appenders
+ * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
+ * @version    SVN: $Id$
+ * @link       http://logging.apache.org/log4php
+ */
+
+class LoggerAppenderPDOTest extends PHPUnit_Framework_TestCase {
+        
+	public function testSimpleLogging() {
+		$event = new LoggerLoggingEvent("LoggerAppenderPDOTest", new Logger("TEST"), LoggerLevel::getLevelError(), "testmessage");
+
+		$dbname = 'appenders/pdotest.sqlite';
+		try {
+			$database = new SQLiteDatabase($dbname);
+			$database = null;
+			
+			$appender = new LoggerAppenderPDO("myname");
+			$appender->setDSN('sqlite:'.$dbname);
+			$appender->setCreateTable(true);
+			$appender->activateOptions();
+			$appender->append($event);
+			
+			
+			$db = $appender->getDatabaseHandle();
+			$q = "select * from log4php_log";	
+			$error = "";
+			if($result = $db->query($q, SQLITE_BOTH, $error)) {
+				while($row = $result->fetch()) {
+	    			self::assertEquals($row['1'], 'TEST');
+	    			self::assertEquals($row['2'], 'ERROR');
+	    			self::assertEquals($row['3'], 'testmessage');
+	  			}
+			} else {
+				// todo propagate exception to phpunit
+			   self::assertTrue(false);
+			}
+			$appender->close();
+		} catch(Exception $e) {
+			// todo propagate exception to phpunit
+			self::assertTrue(false);
+		}
+		unlink($dbname);
+    }
+    
+}



Re: svn commit: r772512 - in /incubator/log4php/trunk/src: main/php/LoggerManager.php main/php/appenders/LoggerAppenderPDO.php test/php/appenders/LoggerAppenderPDOTest.php

Posted by Christian Hammers <ch...@lathspell.de>.
On Tue, 19 May 2009 06:51:05 +0200
Christian Grobmeier <gr...@gmail.com> wrote:

> Hi Christian,
> 
> > I've not read the code completely but shouldn't there be a quote() or
> > something around the insert statement? Although this is just the
> > template, the single quote indicate at least that $sth->quote() is
> > not used.
> 
> i am not sure what you mean with the above?

I fear that if I log a message that contains a single quote the SQL
query you build will produce an SQL syntax error.

The quote() function (http://de2.php.net/manual/en/pdo.quote.php)
puts backslashes before every quote and then a pair of single quotes
around the result so you would have the diff:
  -	VALUES ('%d','%c','%p','%m','%t','%F','%L')";
  +	VALUES (%d,%c,%p,%m,%t,%F,%L)";

> > BTW, as you're aiming for speed, did you consider a PDO Prepared
> > Statement?
> 
> you are right, a PS would fit better in most cases. If you have some
> cycles, I would apply all patches you bring in :-)

Hm.. I try to find time but don't be too optimistic :)

bye,

-christian-



 
> Cheers,
> Christian
> 
> >
> > bye,
> >
> > -christian-
> >
> >
> > Am Thu, 07 May 2009 06:29:31 -0000
> > schrieb grobmeier@apache.org:
> >
> >> Author: grobmeier
> >> Date: Thu May  7 06:29:28 2009
> >> New Revision: 772512
> > ...
> >> +    public function activateOptions() {
> > ...
> >> +
> >> +        if($this->sql == '' || $this->sql == null) {
> >> +            $this->sql = "INSERT INTO $this->table ( timestamp, " .
> >> +
> >>                                                                               "logger,
> >> " .
> >> +
> >>                                                                               "level,
> >> " .
> >> +
> >>                                                                               "message,
> >> " .
> >> +
> >>                                                                               "thread,
> >> " .
> >> +
> >>                                                                               "file,
> >> " .
> >> +
> >>                                                                               "line" .
> >> +                                              ") VALUES
> >> ('%d','%c','%p','%m','%t','%F','%L')";
> >> +        }
> >> +
> >

Re: svn commit: r772512 - in /incubator/log4php/trunk/src: main/php/LoggerManager.php main/php/appenders/LoggerAppenderPDO.php test/php/appenders/LoggerAppenderPDOTest.php

Posted by Christian Grobmeier <gr...@gmail.com>.
Hi Christian,

> I've not read the code completely but shouldn't there be a quote() or
> something around the insert statement? Although this is just the
> template, the single quote indicate at least that $sth->quote() is
> not used.

i am not sure what you mean with the above?

> BTW, as you're aiming for speed, did you consider a PDO Prepared
> Statement?

you are right, a PS would fit better in most cases. If you have some
cycles, I would apply all patches you bring in :-)

Cheers,
Christian

>
> bye,
>
> -christian-
>
>
> Am Thu, 07 May 2009 06:29:31 -0000
> schrieb grobmeier@apache.org:
>
>> Author: grobmeier
>> Date: Thu May  7 06:29:28 2009
>> New Revision: 772512
> ...
>> +    public function activateOptions() {
> ...
>> +
>> +        if($this->sql == '' || $this->sql == null) {
>> +            $this->sql = "INSERT INTO $this->table ( timestamp, " .
>> +
>>                                                                               "logger,
>> " .
>> +
>>                                                                               "level,
>> " .
>> +
>>                                                                               "message,
>> " .
>> +
>>                                                                               "thread,
>> " .
>> +
>>                                                                               "file,
>> " .
>> +
>>                                                                               "line" .
>> +                                              ") VALUES
>> ('%d','%c','%p','%m','%t','%F','%L')";
>> +        }
>> +
>

Re: svn commit: r772512 - in /incubator/log4php/trunk/src: main/php/LoggerManager.php main/php/appenders/LoggerAppenderPDO.php test/php/appenders/LoggerAppenderPDOTest.php

Posted by Christian Hammers <ch...@lathspell.de>.
Hello

I've not read the code completely but shouldn't there be a quote() or
something around the insert statement? Although this is just the
template, the single quote indicate at least that $sth->quote() is
not used.  

BTW, as you're aiming for speed, did you consider a PDO Prepared
Statement?

bye,

-christian-


Am Thu, 07 May 2009 06:29:31 -0000
schrieb grobmeier@apache.org:

> Author: grobmeier
> Date: Thu May  7 06:29:28 2009
> New Revision: 772512
...
> +    public function activateOptions() {
...
> +        
> +        if($this->sql == '' || $this->sql == null) {
> +            $this->sql = "INSERT INTO $this->table ( timestamp, " .
> +
> 										"logger,
> " .
> +
> 										"level,
> " .
> +
> 										"message,
> " .
> +
> 										"thread,
> " .
> +
> 										"file,
> " .
> +
> 										"line" .
> +						 ") VALUES
> ('%d','%c','%p','%m','%t','%F','%L')";
> +        }
> +