Overview

Packages

  • log4php
    • appenders
    • configurators
    • filters
    • helpers
    • layouts
    • pattern
    • renderers

Classes

  • LoggerAppenderConsole
  • LoggerAppenderDailyFile
  • LoggerAppenderEcho
  • LoggerAppenderFile
  • LoggerAppenderFirePHP
  • LoggerAppenderMail
  • LoggerAppenderMailEvent
  • LoggerAppenderMongoDB
  • LoggerAppenderNull
  • LoggerAppenderPDO
  • LoggerAppenderPhp
  • LoggerAppenderRollingFile
  • LoggerAppenderSocket
  • LoggerAppenderSyslog
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Licensed to the Apache Software Foundation (ASF) under one or more
  4:  * contributor license agreements.  See the NOTICE file distributed with
  5:  * this work for additional information regarding copyright ownership.
  6:  * The ASF licenses this file to You under the Apache License, Version 2.0
  7:  * (the "License"); you may not use this file except in compliance with
  8:  * the License.  You may obtain a copy of the License at
  9:  *
 10:  *     http://www.apache.org/licenses/LICENSE-2.0
 11:  *
 12:  * Unless required by applicable law or agreed to in writing, software
 13:  * distributed under the License is distributed on an "AS IS" BASIS,
 14:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15:  * See the License for the specific language governing permissions and
 16:  * limitations under the License.
 17:  */
 18: 
 19: /**
 20:  * LoggerAppenderPDO appender logs to a database using the PHP's PDO extension.
 21:  *
 22:  * ## Configurable parameters: ##
 23:  *
 24:  * - dsn             - The Data Source Name (DSN) used to connect to the database.
 25:  * - user            - Username used to connect to the database.
 26:  * - password        - Password used to connect to the database.
 27:  * - table           - Name of the table to which log entries are be inserted.
 28:  * - insertSQL       - Sets the insert statement for a logging event. Defaults
 29:  *                     to the correct one - change only if you are sure what you are doing.
 30:  * - insertPattern   - The conversion pattern to use in conjuction with insert 
 31:  *                     SQL. Must contain the same number of comma separated 
 32:  *                     conversion patterns as there are question marks in the 
 33:  *                     insertSQL.
 34:  *
 35:  * @version $Revision: 1374546 $
 36:  * @package log4php
 37:  * @subpackage appenders
 38:  * @since 2.0
 39:  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 40:  * @link http://logging.apache.org/log4php/docs/appenders/pdo.html Appender documentation
 41:  */
 42: class LoggerAppenderPDO extends LoggerAppender {
 43: 
 44:     // ******************************************
 45:     // *** Configurable parameters            ***
 46:     // ******************************************
 47:     
 48:     /** 
 49:      * DSN string used to connect to the database.
 50:      * @see http://www.php.net/manual/en/pdo.construct.php
 51:      */
 52:     protected $dsn;
 53: 
 54:     /** Database user name. */
 55:     protected $user;
 56:     
 57:     /** Database password. */
 58:     protected $password;
 59:     
 60:     /** 
 61:      * The insert query.
 62:      * 
 63:      * The __TABLE__ placeholder will be replaced by the table name from 
 64:      * {@link $table}.
 65:      *  
 66:      * The questionmarks are part of the prepared statement, and they must 
 67:      * match the number of conversion specifiers in {@link insertPattern}.
 68:      */
 69:     protected $insertSQL = "INSERT INTO __TABLE__ (timestamp, logger, level, message, thread, file, line) VALUES (?, ?, ?, ?, ?, ?, ?)";
 70: 
 71:     /** 
 72:      * A comma separated list of {@link LoggerPatternLayout} format strings 
 73:      * which replace the "?" in {@link $insertSQL}.
 74:      * 
 75:      * Must contain the same number of comma separated conversion patterns as 
 76:      * there are question marks in {@link insertSQL}.
 77:      * 
 78:      * @see LoggerPatternLayout For conversion patterns.
 79:      */
 80:     protected $insertPattern = "%date{Y-m-d H:i:s},%logger,%level,%message,%pid,%file,%line";
 81: 
 82:     /** Name of the table to which to append log events. */
 83:     protected $table = 'log4php_log';
 84:     
 85:     /** The number of recconect attempts to make on failed append. */
 86:     protected $reconnectAttempts = 3;
 87:     
 88:     
 89:     // ******************************************
 90:     // *** Private memebers                   ***
 91:     // ******************************************
 92:     
 93:     /** 
 94:      * The PDO instance.
 95:      * @var PDO 
 96:      */
 97:     protected $db;
 98:     
 99:     /** 
100:      * Prepared statement for the insert query.
101:      * @var PDOStatement 
102:      */
103:     protected $preparedInsert;
104:     
105:     /** This appender does not require a layout. */
106:     protected $requiresLayout = false;
107: 
108: 
109:     // ******************************************
110:     // *** Appender methods                   ***
111:     // ******************************************
112:     
113:     /**
114:      * Acquires a database connection based on parameters.
115:      * Parses the insert pattern to create a chain of converters which will be
116:      * used in forming query parameters from logging events.
117:      */
118:     public function activateOptions() {
119:         try {
120:             $this->establishConnection();
121:         } catch (PDOException $e) {
122:             $this->warn("Failed connecting to database. Closing appender. Error: " . $e->getMessage());
123:             $this->close();
124:             return;
125:         }
126: 
127:         // Parse the insert patterns; pattern parts are comma delimited
128:         $pieces = explode(',', $this->insertPattern);
129:         $converterMap = LoggerLayoutPattern::getDefaultConverterMap();
130:         foreach($pieces as $pattern) {
131:             $parser = new LoggerPatternParser($pattern, $converterMap);
132:             $this->converters[] = $parser->parse(); 
133:         }
134:         
135:         $this->closed = false;
136:     }
137:     
138:     /** 
139:      * Connects to the database, and prepares the insert query.
140:      * @throws PDOException If connect or prepare fails.  
141:      */
142:     protected function establishConnection() {
143:         // Acquire database connection
144:         $this->db = new PDO($this->dsn, $this->user, $this->password);
145:         $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
146:         
147:         // Prepare the insert statement
148:         $insertSQL = str_replace('__TABLE__', $this->table, $this->insertSQL);
149:         $this->preparedInsert = $this->db->prepare($insertSQL);
150:     }
151:     
152:     /**
153:      * Appends a new event to the database.
154:      * 
155:      * If writing to database fails, it will retry by re-establishing the 
156:      * connection up to $reconnectAttempts times. If writing still fails, 
157:      * the appender will close.
158:      */
159:     public function append(LoggerLoggingEvent $event) {
160: 
161:         for ($attempt = 1; $attempt <= $this->reconnectAttempts + 1; $attempt++) {
162:             try {
163:                 // Attempt to write to database
164:                 $this->preparedInsert->execute($this->format($event));
165:                 $this->preparedInsert->closeCursor();
166:                 break;
167:             } catch (PDOException $e) {
168:                 $this->warn("Failed writing to database: ". $e->getMessage());
169:                 
170:                 // Close the appender if it's the last attempt
171:                 if ($attempt > $this->reconnectAttempts) {
172:                     $this->warn("Failed writing to database after {$this->reconnectAttempts} reconnect attempts. Closing appender.");
173:                     $this->close();
174:                 // Otherwise reconnect and try to write again
175:                 } else {
176:                     $this->warn("Attempting a reconnect (attempt $attempt of {$this->reconnectAttempts}).");
177:                     $this->establishConnection();
178:                 }
179:             }
180:         }
181:     }
182:     
183:     /**
184:      * Converts the logging event to a series of database parameters by using 
185:      * the converter chain which was set up on activation. 
186:      */
187:     protected function format(LoggerLoggingEvent $event) {
188:         $params = array();
189:         foreach($this->converters as $converter) {
190:             $buffer = '';
191:             while ($converter !== null) {
192:                 $converter->format($buffer, $event);
193:                 $converter = $converter->next;
194:             }
195:             $params[] = $buffer;
196:         }
197:         return $params;
198:     }
199:     
200:     /**
201:      * Closes the connection to the logging database
202:      */
203:     public function close() {
204:         // Close the connection (if any)
205:         $this->db = null;
206:         
207:         // Close the appender
208:         $this->closed = true;
209:     }
210:     
211:     // ******************************************
212:     // *** Accessor methods                   ***
213:     // ******************************************
214:     
215:     /**
216:      * Returns the active database handle or null if not established.
217:      * @return PDO
218:      */
219:     public function getDatabaseHandle() {
220:         return $this->db;
221:     }
222:     
223:     /** Sets the username. */
224:     public function setUser($user) {
225:         $this->setString('user', $user);
226:     }
227:     
228:     /** Returns the username. */
229:     public function getUser($user) {
230:         return $this->user;
231:     }
232:     
233:     /** Sets the password. */
234:     public function setPassword($password) {
235:         $this->setString('password', $password);
236:     }
237:     
238:     /** Returns the password. */
239:     public function getPassword($password) {
240:         return $this->password;
241:     }
242:     
243:     /** Sets the insert SQL. */
244:     public function setInsertSQL($sql) {
245:         $this->setString('insertSQL', $sql);
246:     }
247:     
248:     /** Returns the insert SQL. */
249:     public function getInsertSQL($sql) {
250:         return $this->insertSQL;
251:     }
252: 
253:     /** Sets the insert pattern. */
254:     public function setInsertPattern($pattern) {
255:         $this->setString('insertPattern', $pattern);
256:     }
257:     
258:     /** Returns the insert pattern. */
259:     public function getInsertPattern($pattern) {
260:         return $this->insertPattern;
261:     }
262: 
263:     /** Sets the table name. */
264:     public function setTable($table) {
265:         $this->setString('table', $table);
266:     }
267:     
268:     /** Returns the table name. */
269:     public function getTable($table) {
270:         return $this->table;
271:     }
272:     
273:     /** Sets the DSN string. */
274:     public function setDSN($dsn) {
275:         $this->setString('dsn', $dsn);
276:     }
277:     
278:     /** Returns the DSN string. */
279:     public function getDSN($dsn) {
280:         return $this->setString('dsn', $dsn);
281:     }   
282: }
283: 
Apache log4php API documentation generated by ApiGen 2.8.0