Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
38.89% |
7 / 18 |
CRAP | |
64.06% |
41 / 64 |
LoggerAppenderPDO | |
0.00% |
0 / 1 |
|
38.89% |
7 / 18 |
54.01 | |
64.06% |
41 / 64 |
activateOptions() | |
0.00% |
0 / 1 |
3.03 | |
84.62% |
11 / 13 |
|||
establishConnection() | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
append(LoggerLoggingEvent $event) | |
0.00% |
0 / 1 |
8.25 | |
35.71% |
5 / 14 |
|||
format(LoggerLoggingEvent $event) | |
100.00% |
1 / 1 |
3 | |
100.00% |
10 / 10 |
|||
close() | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
getDatabaseHandle() | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
setUser($user) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getUser($user) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
setPassword($password) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getPassword($password) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
setInsertSQL($sql) | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
getInsertSQL($sql) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
setInsertPattern($pattern) | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
getInsertPattern($pattern) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
setTable($table) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getTable($table) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
setDSN($dsn) | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
getDSN($dsn) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
<?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. | |
*/ | |
/** | |
* LoggerAppenderPDO appender logs to a database using the PHP's PDO extension. | |
* | |
* ## Configurable parameters: ## | |
* | |
* - dsn - The Data Source Name (DSN) used to connect to the database. | |
* - user - Username used to connect to the database. | |
* - password - Password used to connect to the database. | |
* - table - Name of the table to which log entries are be inserted. | |
* - insertSQL - Sets the insert statement for a logging event. Defaults | |
* to the correct one - change only if you are sure what you are doing. | |
* - insertPattern - The conversion pattern to use in conjuction with insert | |
* SQL. Must contain the same number of comma separated | |
* conversion patterns as there are question marks in the | |
* insertSQL. | |
* | |
* @version $Revision: 1374546 $ | |
* @package log4php | |
* @subpackage appenders | |
* @since 2.0 | |
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 | |
* @link http://logging.apache.org/log4php/docs/appenders/pdo.html Appender documentation | |
*/ | |
class LoggerAppenderPDO extends LoggerAppender { | |
// ****************************************** | |
// *** Configurable parameters *** | |
// ****************************************** | |
/** | |
* DSN string used to connect to the database. | |
* @see http://www.php.net/manual/en/pdo.construct.php | |
*/ | |
protected $dsn; | |
/** Database user name. */ | |
protected $user; | |
/** Database password. */ | |
protected $password; | |
/** | |
* The insert query. | |
* | |
* The __TABLE__ placeholder will be replaced by the table name from | |
* {@link $table}. | |
* | |
* The questionmarks are part of the prepared statement, and they must | |
* match the number of conversion specifiers in {@link insertPattern}. | |
*/ | |
protected $insertSQL = "INSERT INTO __TABLE__ (timestamp, logger, level, message, thread, file, line) VALUES (?, ?, ?, ?, ?, ?, ?)"; | |
/** | |
* A comma separated list of {@link LoggerPatternLayout} format strings | |
* which replace the "?" in {@link $insertSQL}. | |
* | |
* Must contain the same number of comma separated conversion patterns as | |
* there are question marks in {@link insertSQL}. | |
* | |
* @see LoggerPatternLayout For conversion patterns. | |
*/ | |
protected $insertPattern = "%date{Y-m-d H:i:s},%logger,%level,%message,%pid,%file,%line"; | |
/** Name of the table to which to append log events. */ | |
protected $table = 'log4php_log'; | |
/** The number of recconect attempts to make on failed append. */ | |
protected $reconnectAttempts = 3; | |
// ****************************************** | |
// *** Private memebers *** | |
// ****************************************** | |
/** | |
* The PDO instance. | |
* @var PDO | |
*/ | |
protected $db; | |
/** | |
* Prepared statement for the insert query. | |
* @var PDOStatement | |
*/ | |
protected $preparedInsert; | |
/** This appender does not require a layout. */ | |
protected $requiresLayout = false; | |
// ****************************************** | |
// *** Appender methods *** | |
// ****************************************** | |
/** | |
* Acquires a database connection based on parameters. | |
* Parses the insert pattern to create a chain of converters which will be | |
* used in forming query parameters from logging events. | |
*/ | |
public function activateOptions() { | |
try { | |
$this->establishConnection(); | |
} catch (PDOException $e) { | |
$this->warn("Failed connecting to database. Closing appender. Error: " . $e->getMessage()); | |
$this->close(); | |
return; | |
} | |
// Parse the insert patterns; pattern parts are comma delimited | |
$pieces = explode(',', $this->insertPattern); | |
$converterMap = LoggerLayoutPattern::getDefaultConverterMap(); | |
foreach($pieces as $pattern) { | |
$parser = new LoggerPatternParser($pattern, $converterMap); | |
$this->converters[] = $parser->parse(); | |
} | |
$this->closed = false; | |
} | |
/** | |
* Connects to the database, and prepares the insert query. | |
* @throws PDOException If connect or prepare fails. | |
*/ | |
protected function establishConnection() { | |
// Acquire database connection | |
$this->db = new PDO($this->dsn, $this->user, $this->password); | |
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
// Prepare the insert statement | |
$insertSQL = str_replace('__TABLE__', $this->table, $this->insertSQL); | |
$this->preparedInsert = $this->db->prepare($insertSQL); | |
} | |
/** | |
* Appends a new event to the database. | |
* | |
* If writing to database fails, it will retry by re-establishing the | |
* connection up to $reconnectAttempts times. If writing still fails, | |
* the appender will close. | |
*/ | |
public function append(LoggerLoggingEvent $event) { | |
for ($attempt = 1; $attempt <= $this->reconnectAttempts + 1; $attempt++) { | |
try { | |
// Attempt to write to database | |
$this->preparedInsert->execute($this->format($event)); | |
$this->preparedInsert->closeCursor(); | |
break; | |
} catch (PDOException $e) { | |
$this->warn("Failed writing to database: ". $e->getMessage()); | |
// Close the appender if it's the last attempt | |
if ($attempt > $this->reconnectAttempts) { | |
$this->warn("Failed writing to database after {$this->reconnectAttempts} reconnect attempts. Closing appender."); | |
$this->close(); | |
// Otherwise reconnect and try to write again | |
} else { | |
$this->warn("Attempting a reconnect (attempt $attempt of {$this->reconnectAttempts})."); | |
$this->establishConnection(); | |
} | |
} | |
} | |
} | |
/** | |
* Converts the logging event to a series of database parameters by using | |
* the converter chain which was set up on activation. | |
*/ | |
protected function format(LoggerLoggingEvent $event) { | |
$params = array(); | |
foreach($this->converters as $converter) { | |
$buffer = ''; | |
while ($converter !== null) { | |
$converter->format($buffer, $event); | |
$converter = $converter->next; | |
} | |
$params[] = $buffer; | |
} | |
return $params; | |
} | |
/** | |
* Closes the connection to the logging database | |
*/ | |
public function close() { | |
// Close the connection (if any) | |
$this->db = null; | |
// Close the appender | |
$this->closed = true; | |
} | |
// ****************************************** | |
// *** Accessor methods *** | |
// ****************************************** | |
/** | |
* Returns the active database handle or null if not established. | |
* @return PDO | |
*/ | |
public function getDatabaseHandle() { | |
return $this->db; | |
} | |
/** Sets the username. */ | |
public function setUser($user) { | |
$this->setString('user', $user); | |
} | |
/** Returns the username. */ | |
public function getUser($user) { | |
return $this->user; | |
} | |
/** Sets the password. */ | |
public function setPassword($password) { | |
$this->setString('password', $password); | |
} | |
/** Returns the password. */ | |
public function getPassword($password) { | |
return $this->password; | |
} | |
/** Sets the insert SQL. */ | |
public function setInsertSQL($sql) { | |
$this->setString('insertSQL', $sql); | |
} | |
/** Returns the insert SQL. */ | |
public function getInsertSQL($sql) { | |
return $this->insertSQL; | |
} | |
/** Sets the insert pattern. */ | |
public function setInsertPattern($pattern) { | |
$this->setString('insertPattern', $pattern); | |
} | |
/** Returns the insert pattern. */ | |
public function getInsertPattern($pattern) { | |
return $this->insertPattern; | |
} | |
/** Sets the table name. */ | |
public function setTable($table) { | |
$this->setString('table', $table); | |
} | |
/** Returns the table name. */ | |
public function getTable($table) { | |
return $this->table; | |
} | |
/** Sets the DSN string. */ | |
public function setDSN($dsn) { | |
$this->setString('dsn', $dsn); | |
} | |
/** Returns the DSN string. */ | |
public function getDSN($dsn) { | |
return $this->setString('dsn', $dsn); | |
} | |
} |