| Code Coverage
| Classes and Traits | Functions and Methods | Lines
Total |  | 0.00% | 0 / 1 |  | 86.36% | 19 / 22 | CRAP |  | 84.21% | 80 / 95
LoggerAppenderMongoDB |  | 0.00% | 0 / 1 |  | 86.36% | 19 / 22 | 43.68 |  | 84.21% | 80 / 95
__construct($name = '') |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 8 / 8
activateOptions() |  | 0.00% | 0 / 1 | 21.52 |  | 33.33% | 6 / 18
append(LoggerLoggingEvent $event) |  | 0.00% | 0 / 1 | 3.04 |  | 83.33% | 5 / 6
format(LoggerLoggingEvent $event) |  | 100.00% | 1 / 1 | 4 |  | 100.00% | 20 / 20
formatThrowable(Exception $ex) |  | 100.00% | 1 / 1 | 3 |  | 100.00% | 8 / 8
close() |  | 100.00% | 1 / 1 | 3 |  | 100.00% | 9 / 9
setHost($host) |  | 0.00% | 0 / 1 | 2.26 |  | 60.00% | 3 / 5
getHost() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
setPort($port) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 2 / 2
getPort() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
setDatabaseName($databaseName) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 2 / 2
getDatabaseName() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
setCollectionName($collectionName) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 2 / 2
getCollectionName() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
setUserName($userName) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 2 / 2
getUserName() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
setPassword($password) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 2 / 2
getPassword() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
setTimeout($timeout) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 2 / 2
getTimeout() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
getConnection() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1
getCollection() |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1

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 | * Appender for writing to MongoDB.
21 | *
22 | * This class was originally contributed by Vladimir Gorej.
23 | *
24 | * ## Configurable parameters: ##
25 | *
26 | * - **host** - Server on which mongodb instance is located.
27 | * - **port** - Port on which the instance is bound.
28 | * - **databaseName** - Name of the database to which to log.
29 | * - **collectionName** - Name of the target collection within the given database.
30 | * - **username** - Username used to connect to the database.
31 | * - **password** - Password used to connect to the database.
32 | * - **timeout** - For how long the driver should try to connect to the database (in milliseconds).
33 | *
34 | * @version $Revision: 1346363 $
35 | * @package log4php
36 | * @subpackage appenders
37 | * @since 2.1
38 | * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
39 | * @link http://logging.apache.org/log4php/docs/appenders/mongodb.html Appender documentation
40 | * @link http://github.com/log4mongo/log4mongo-php Vladimir Gorej's original submission.
41 | * @link http://www.mongodb.org/ MongoDB website.
42 | */
43 | class LoggerAppenderMongoDB extends LoggerAppender {
44 |
45 | // ******************************************
46 | // ** Constants **
47 | // ******************************************
48 |
49 | /** Default prefix for the {@link $host}. */
50 | const DEFAULT_MONGO_URL_PREFIX = 'mongodb://';
51 |
52 | /** Default value for {@link $host}, without a prefix. */
53 | const DEFAULT_MONGO_HOST = 'localhost';
54 |
55 | /** Default value for {@link $port} */
56 | const DEFAULT_MONGO_PORT = 27017;
57 |
58 | /** Default value for {@link $databaseName} */
59 | const DEFAULT_DB_NAME = 'log4php_mongodb';
60 |
61 | /** Default value for {@link $collectionName} */
62 | const DEFAULT_COLLECTION_NAME = 'logs';
63 |
64 | /** Default value for {@link $timeout} */
65 | const DEFAULT_TIMEOUT_VALUE = 3000;
66 |
67 | // ******************************************
68 | // ** Configurable parameters **
69 | // ******************************************
70 |
71 | /** Server on which mongodb instance is located. */
72 | protected $host;
73 |
74 | /** Port on which the instance is bound. */
75 | protected $port;
76 |
77 | /** Name of the database to which to log. */
78 | protected $databaseName;
79 |
80 | /** Name of the collection within the given database. */
81 | protected $collectionName;
82 |
83 | /** Username used to connect to the database. */
84 | protected $userName;
85 |
86 | /** Password used to connect to the database. */
87 | protected $password;
88 |
89 | /** Timeout value used when connecting to the database (in milliseconds). */
90 | protected $timeout;
91 |
92 | // ******************************************
93 | // ** Member variables **
94 | // ******************************************
95 |
96 | /**
97 | * Connection to the MongoDB instance.
98 | * @var Mongo
99 | */
100 | protected $connection;
101 |
102 | /**
103 | * The collection to which log is written.
104 | * @var MongoCollection
105 | */
106 | protected $collection;
107 |
108 | public function __construct($name = '') {
109 | parent::__construct($name);
110 | $this->host = self::DEFAULT_MONGO_URL_PREFIX . self::DEFAULT_MONGO_HOST;
111 | $this->port = self::DEFAULT_MONGO_PORT;
112 | $this->databaseName = self::DEFAULT_DB_NAME;
113 | $this->collectionName = self::DEFAULT_COLLECTION_NAME;
114 | $this->timeout = self::DEFAULT_TIMEOUT_VALUE;
115 | $this->requiresLayout = false;
116 | }
117 |
118 | /**
119 | * Setup db connection.
120 | * Based on defined options, this method connects to the database and
121 | * creates a {@link $collection}.
122 | */
123 | public function activateOptions() {
124 | try {
125 | $this->connection = new Mongo(sprintf('%s:%d', $this->host, $this->port), array('timeout' => $this->timeout));
126 | $db = $this->connection->selectDB($this->databaseName);
127 | if ($this->userName !== null && $this->password !== null) {
128 | $authResult = $db->authenticate($this->userName, $this->password);
129 | if ($authResult['ok'] == floatval(0)) {
130 | throw new Exception($authResult['errmsg'], $authResult['ok']);
131 | }
132 | }
133 | $this->collection = $db->selectCollection($this->collectionName);
134 | } catch (MongoConnectionException $ex) {
135 | $this->closed = true;
136 | $this->warn(sprintf('Failed to connect to mongo deamon: %s', $ex->getMessage()));
137 | } catch (InvalidArgumentException $ex) {
138 | $this->closed = true;
139 | $this->warn(sprintf('Error while selecting mongo database: %s', $ex->getMessage()));
140 | } catch (Exception $ex) {
141 | $this->closed = true;
142 | $this->warn('Invalid credentials for mongo database authentication');
143 | }
144 | }
145 |
146 | /**
147 | * Appends a new event to the mongo database.
148 | *
149 | * @param LoggerLoggingEvent $event
150 | */
151 | public function append(LoggerLoggingEvent $event) {
152 | try {
153 | if ($this->collection != null) {
154 | $this->collection->insert($this->format($event));
155 | }
156 | } catch (MongoCursorException $ex) {
157 | $this->warn(sprintf('Error while writing to mongo collection: %s', $ex->getMessage()));
158 | }
159 | }
160 |
161 | /**
162 | * Converts the logging event into an array which can be logged to mongodb.
163 | *
164 | * @param LoggerLoggingEvent $event
165 | * @return array The array representation of the logging event.
166 | */
167 | protected function format(LoggerLoggingEvent $event) {
168 | $timestampSec = (int) $event->getTimestamp();
169 | $timestampUsec = (int) (($event->getTimestamp() - $timestampSec) * 1000000);
170 |
171 | $document = array(
172 | 'timestamp' => new MongoDate($timestampSec, $timestampUsec),
173 | 'level' => $event->getLevel()->toString(),
174 | 'thread' => (int) $event->getThreadName(),
175 | 'message' => $event->getMessage(),
176 | 'loggerName' => $event->getLoggerName()
177 | );
178 |
179 | $locationInfo = $event->getLocationInformation();
180 | if ($locationInfo != null) {
181 | $document['fileName'] = $locationInfo->getFileName();
182 | $document['method'] = $locationInfo->getMethodName();
183 | $document['lineNumber'] = ($locationInfo->getLineNumber() == 'NA') ? 'NA' : (int) $locationInfo->getLineNumber();
184 | $document['className'] = $locationInfo->getClassName();
185 | }
186 |
187 | $throwableInfo = $event->getThrowableInformation();
188 | if ($throwableInfo != null) {
189 | $document['exception'] = $this->formatThrowable($throwableInfo->getThrowable());
190 | }
191 |
192 | return $document;
193 | }
194 |
195 | /**
196 | * Converts an Exception into an array which can be logged to mongodb.
197 | *
198 | * Supports innner exceptions (PHP >= 5.3)
199 | *
200 | * @param Exception $ex
201 | * @return array
202 | */
203 | protected function formatThrowable(Exception $ex) {
204 | $array = array(
205 | 'message' => $ex->getMessage(),
206 | 'code' => $ex->getCode(),
207 | 'stackTrace' => $ex->getTraceAsString(),
208 | );
209 |
210 | if (method_exists($ex, 'getPrevious') && $ex->getPrevious() !== null) {
211 | $array['innerException'] = $this->formatThrowable($ex->getPrevious());
212 | }
213 |
214 | return $array;
215 | }
216 |
217 | /**
218 | * Closes the connection to the logging database
219 | */
220 | public function close() {
221 | if($this->closed != true) {
222 | $this->collection = null;
223 | if ($this->connection !== null) {
224 | $this->connection->close();
225 | $this->connection = null;
226 | }
227 | $this->closed = true;
228 | }
229 | }
230 |
231 | /**
232 | * Sets the value of {@link $host} parameter.
233 | * @param string $host
234 | */
235 | public function setHost($host) {
236 | if (!preg_match('/^mongodb\:\/\//', $host)) {
237 | $host = self::DEFAULT_MONGO_URL_PREFIX . $host;
238 | }
239 | $this->host = $host;
240 | }
241 |
242 | /**
243 | * Returns the value of {@link $host} parameter.
244 | * @return string
245 | */
246 | public function getHost() {
247 | return $this->host;
248 | }
249 |
250 | /**
251 | * Sets the value of {@link $port} parameter.
252 | * @param int $port
253 | */
254 | public function setPort($port) {
255 | $this->setPositiveInteger('port', $port);
256 | }
257 |
258 | /**
259 | * Returns the value of {@link $port} parameter.
260 | * @return int
261 | */
262 | public function getPort() {
263 | return $this->port;
264 | }
265 |
266 | /**
267 | * Sets the value of {@link $databaseName} parameter.
268 | * @param string $databaseName
269 | */
270 | public function setDatabaseName($databaseName) {
271 | $this->setString('databaseName', $databaseName);
272 | }
273 |
274 | /**
275 | * Returns the value of {@link $databaseName} parameter.
276 | * @return string
277 | */
278 | public function getDatabaseName() {
279 | return $this->databaseName;
280 | }
281 |
282 | /**
283 | * Sets the value of {@link $collectionName} parameter.
284 | * @param string $collectionName
285 | */
286 | public function setCollectionName($collectionName) {
287 | $this->setString('collectionName', $collectionName);
288 | }
289 |
290 | /**
291 | * Returns the value of {@link $collectionName} parameter.
292 | * @return string
293 | */
294 | public function getCollectionName() {
295 | return $this->collectionName;
296 | }
297 |
298 | /**
299 | * Sets the value of {@link $userName} parameter.
300 | * @param string $userName
301 | */
302 | public function setUserName($userName) {
303 | $this->setString('userName', $userName, true);
304 | }
305 |
306 | /**
307 | * Returns the value of {@link $userName} parameter.
308 | * @return string
309 | */
310 | public function getUserName() {
311 | return $this->userName;
312 | }
313 |
314 | /**
315 | * Sets the value of {@link $password} parameter.
316 | * @param string $password
317 | */
318 | public function setPassword($password) {
319 | $this->setString('password', $password, true);
320 | }
321 |
322 | /**
323 | * Returns the value of {@link $password} parameter.
324 | * @return string
325 | */
326 | public function getPassword() {
327 | return $this->password;
328 | }
329 |
330 | /**
331 | * Sets the value of {@link $timeout} parameter.
332 | * @param int $timeout
333 | */
334 | public function setTimeout($timeout) {
335 | $this->setPositiveInteger('timeout', $timeout);
336 | }
337 |
338 | /**
339 | * Returns the value of {@link $timeout} parameter.
340 | * @return int
341 | */
342 | public function getTimeout() {
343 | return $this->timeout;
344 | }
345 | /**
346 | * Returns the mongodb connection.
347 | * @return Mongo
348 | */
349 | public function getConnection() {
350 | return $this->connection;
351 | }
352 |
353 | /**
354 | * Returns the active mongodb collection.
355 | * @return MongoCollection
356 | */
357 | public function getCollection() {
358 | return $this->collection;
359 | }
360 | }