Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
12345 anikendra 1
<?php
2
/**
3
 * Logging.
4
 *
5
 * Log messages to text files.
6
 *
7
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
9
 *
10
 * Licensed under The MIT License
11
 * For full copyright and license information, please see the LICENSE.txt
12
 * Redistributions of files must retain the above copyright notice.
13
 *
14
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
15
 * @link          http://cakephp.org CakePHP(tm) Project
16
 * @package       Cake.Log
17
 * @since         CakePHP(tm) v 0.2.9
18
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
19
 */
20
 
21
App::uses('LogEngineCollection', 'Log');
22
 
23
/**
24
 * Logs messages to configured Log adapters. One or more adapters
25
 * can be configured using CakeLogs's methods. If you don't
26
 * configure any adapters, and write to the logs a default
27
 * FileLog will be autoconfigured for you.
28
 *
29
 * ### Configuring Log adapters
30
 *
31
 * You can configure log adapters in your applications `bootstrap.php` file.
32
 * A sample configuration would look like:
33
 *
34
 * {{{
35
 * CakeLog::config('my_log', array('engine' => 'File'));
36
 * }}}
37
 *
38
 * See the documentation on CakeLog::config() for more detail.
39
 *
40
 * ### Writing to the log
41
 *
42
 * You write to the logs using CakeLog::write(). See its documentation for more
43
 * information.
44
 *
45
 * ### Logging Levels
46
 *
47
 * By default CakeLog supports all the log levels defined in
48
 * RFC 5424. When logging messages you can either use the named methods,
49
 * or the correct constants with `write()`:
50
 *
51
 * {{{
52
 * CakeLog::error('Something horrible happened');
53
 * CakeLog::write(LOG_ERR, 'Something horrible happened');
54
 * }}}
55
 *
56
 * If you require custom logging levels, you can use CakeLog::levels() to
57
 * append additional logging levels.
58
 *
59
 * ### Logging scopes
60
 *
61
 * When logging messages and configuring log adapters, you can specify
62
 * 'scopes' that the logger will handle. You can think of scopes as subsystems
63
 * in your application that may require different logging setups. For
64
 * example in an e-commerce application you may want to handle logged errors
65
 * in the cart and ordering subsystems differently than the rest of the
66
 * application. By using scopes you can control logging for each part
67
 * of your application and still keep standard log levels.
68
 *
69
 * See CakeLog::config() and CakeLog::write() for more information
70
 * on scopes
71
 *
72
 * @package       Cake.Log
73
 */
74
class CakeLog {
75
 
76
/**
77
 * LogEngineCollection class
78
 *
79
 * @var LogEngineCollection
80
 */
81
	protected static $_Collection;
82
 
83
/**
84
 * Default log levels as detailed in RFC 5424
85
 * http://tools.ietf.org/html/rfc5424
86
 *
87
 * @var array
88
 */
89
	protected static $_defaultLevels = array(
90
		'emergency' => LOG_EMERG,
91
		'alert' => LOG_ALERT,
92
		'critical' => LOG_CRIT,
93
		'error' => LOG_ERR,
94
		'warning' => LOG_WARNING,
95
		'notice' => LOG_NOTICE,
96
		'info' => LOG_INFO,
97
		'debug' => LOG_DEBUG,
98
	);
99
 
100
/**
101
 * Active log levels for this instance.
102
 *
103
 * @var array
104
 */
105
	protected static $_levels;
106
 
107
/**
108
 * Mapped log levels
109
 *
110
 * @var array
111
 */
112
	protected static $_levelMap;
113
 
114
/**
115
 * initialize ObjectCollection
116
 *
117
 * @return void
118
 */
119
	protected static function _init() {
120
		self::$_levels = self::defaultLevels();
121
		self::$_Collection = new LogEngineCollection();
122
	}
123
 
124
/**
125
 * Configure and add a new logging stream to CakeLog
126
 * You can use add loggers from app/Log/Engine use app.loggername, or any
127
 * plugin/Log/Engine using plugin.loggername.
128
 *
129
 * ### Usage:
130
 *
131
 * {{{
132
 * CakeLog::config('second_file', array(
133
 *     'engine' => 'File',
134
 *     'path' => '/var/logs/my_app/'
135
 * ));
136
 * }}}
137
 *
138
 * Will configure a FileLog instance to use the specified path.
139
 * All options that are not `engine` are passed onto the logging adapter,
140
 * and handled there. Any class can be configured as a logging
141
 * adapter as long as it implements the methods in CakeLogInterface.
142
 *
143
 * ### Logging levels
144
 *
145
 * When configuring loggers, you can set which levels a logger will handle.
146
 * This allows you to disable debug messages in production for example:
147
 *
148
 * {{{
149
 * CakeLog::config('default', array(
150
 *     'engine' => 'File',
151
 *     'path' => LOGS,
152
 *     'levels' => array('error', 'critical', 'alert', 'emergency')
153
 * ));
154
 * }}}
155
 *
156
 * The above logger would only log error messages or higher. Any
157
 * other log messages would be discarded.
158
 *
159
 * ### Logging scopes
160
 *
161
 * When configuring loggers you can define the active scopes the logger
162
 * is for. If defined only the listed scopes will be handled by the
163
 * logger. If you don't define any scopes an adapter will catch
164
 * all scopes that match the handled levels.
165
 *
166
 * {{{
167
 * CakeLog::config('payments', array(
168
 *     'engine' => 'File',
169
 *     'types' => array('info', 'error', 'warning'),
170
 *     'scopes' => array('payment', 'order')
171
 * ));
172
 * }}}
173
 *
174
 * The above logger will only capture log entries made in the
175
 * `payment` and `order` scopes. All other scopes including the
176
 * undefined scope will be ignored. Its important to remember that
177
 * when using scopes you must also define the `types` of log messages
178
 * that a logger will handle. Failing to do so will result in the logger
179
 * catching all log messages even if the scope is incorrect.
180
 *
181
 * @param string $key The keyname for this logger, used to remove the
182
 *    logger later.
183
 * @param array $config Array of configuration information for the logger
184
 * @return bool success of configuration.
185
 * @throws CakeLogException
186
 */
187
	public static function config($key, $config) {
188
		if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $key)) {
189
			throw new CakeLogException(__d('cake_dev', 'Invalid key name'));
190
		}
191
		if (empty($config['engine'])) {
192
			throw new CakeLogException(__d('cake_dev', 'Missing logger class name'));
193
		}
194
		if (empty(self::$_Collection)) {
195
			self::_init();
196
		}
197
		self::$_Collection->load($key, $config);
198
		return true;
199
	}
200
 
201
/**
202
 * Returns the keynames of the currently active streams
203
 *
204
 * @return array Array of configured log streams.
205
 */
206
	public static function configured() {
207
		if (empty(self::$_Collection)) {
208
			self::_init();
209
		}
210
		return self::$_Collection->loaded();
211
	}
212
 
213
/**
214
 * Gets/sets log levels
215
 *
216
 * Call this method without arguments, eg: `CakeLog::levels()` to obtain current
217
 * level configuration.
218
 *
219
 * To append additional level 'user0' and 'user1' to to default log levels:
220
 *
221
 * {{{
222
 * CakeLog::levels(array('user0, 'user1'));
223
 * // or
224
 * CakeLog::levels(array('user0, 'user1'), true);
225
 * }}}
226
 *
227
 * will result in:
228
 *
229
 * {{{
230
 * array(
231
 *     0 => 'emergency',
232
 *     1 => 'alert',
233
 *     ...
234
 *     8 => 'user0',
235
 *     9 => 'user1',
236
 * );
237
 * }}}
238
 *
239
 * To set/replace existing configuration, pass an array with the second argument
240
 * set to false.
241
 *
242
 * {{{
243
 * CakeLog::levels(array('user0, 'user1'), false);
244
 * }}}
245
 *
246
 * will result in:
247
 *
248
 * {{{
249
 * array(
250
 *      0 => 'user0',
251
 *      1 => 'user1',
252
 * );
253
 * }}}
254
 *
255
 * @param array $levels array
256
 * @param bool $append true to append, false to replace
257
 * @return array Active log levels
258
 */
259
	public static function levels($levels = array(), $append = true) {
260
		if (empty(self::$_Collection)) {
261
			self::_init();
262
		}
263
		if (empty($levels)) {
264
			return self::$_levels;
265
		}
266
		$levels = array_values($levels);
267
		if ($append) {
268
			self::$_levels = array_merge(self::$_levels, $levels);
269
		} else {
270
			self::$_levels = $levels;
271
		}
272
		self::$_levelMap = array_flip(self::$_levels);
273
		return self::$_levels;
274
	}
275
 
276
/**
277
 * Reset log levels to the original value
278
 *
279
 * @return array Default log levels
280
 */
281
	public static function defaultLevels() {
282
		self::$_levelMap = self::$_defaultLevels;
283
		self::$_levels = array_flip(self::$_levelMap);
284
		return self::$_levels;
285
	}
286
 
287
/**
288
 * Removes a stream from the active streams. Once a stream has been removed
289
 * it will no longer have messages sent to it.
290
 *
291
 * @param string $streamName Key name of a configured stream to remove.
292
 * @return void
293
 */
294
	public static function drop($streamName) {
295
		if (empty(self::$_Collection)) {
296
			self::_init();
297
		}
298
		self::$_Collection->unload($streamName);
299
	}
300
 
301
/**
302
 * Checks whether $streamName is enabled
303
 *
304
 * @param string $streamName to check
305
 * @return bool
306
 * @throws CakeLogException
307
 */
308
	public static function enabled($streamName) {
309
		if (empty(self::$_Collection)) {
310
			self::_init();
311
		}
312
		if (!isset(self::$_Collection->{$streamName})) {
313
			throw new CakeLogException(__d('cake_dev', 'Stream %s not found', $streamName));
314
		}
315
		return self::$_Collection->enabled($streamName);
316
	}
317
 
318
/**
319
 * Enable stream. Streams that were previously disabled
320
 * can be re-enabled with this method.
321
 *
322
 * @param string $streamName to enable
323
 * @return void
324
 * @throws CakeLogException
325
 */
326
	public static function enable($streamName) {
327
		if (empty(self::$_Collection)) {
328
			self::_init();
329
		}
330
		if (!isset(self::$_Collection->{$streamName})) {
331
			throw new CakeLogException(__d('cake_dev', 'Stream %s not found', $streamName));
332
		}
333
		self::$_Collection->enable($streamName);
334
	}
335
 
336
/**
337
 * Disable stream. Disabling a stream will
338
 * prevent that log stream from receiving any messages until
339
 * its re-enabled.
340
 *
341
 * @param string $streamName to disable
342
 * @return void
343
 * @throws CakeLogException
344
 */
345
	public static function disable($streamName) {
346
		if (empty(self::$_Collection)) {
347
			self::_init();
348
		}
349
		if (!isset(self::$_Collection->{$streamName})) {
350
			throw new CakeLogException(__d('cake_dev', 'Stream %s not found', $streamName));
351
		}
352
		self::$_Collection->disable($streamName);
353
	}
354
 
355
/**
356
 * Gets the logging engine from the active streams.
357
 *
358
 * @param string $streamName Key name of a configured stream to get.
359
 * @return mixed instance of BaseLog or false if not found
360
 * @see BaseLog
361
 */
362
	public static function stream($streamName) {
363
		if (empty(self::$_Collection)) {
364
			self::_init();
365
		}
366
		if (!empty(self::$_Collection->{$streamName})) {
367
			return self::$_Collection->{$streamName};
368
		}
369
		return false;
370
	}
371
 
372
/**
373
 * Writes the given message and type to all of the configured log adapters.
374
 * Configured adapters are passed both the $type and $message variables. $type
375
 * is one of the following strings/values.
376
 *
377
 * ### Types:
378
 *
379
 * -  LOG_EMERG => 'emergency',
380
 * -  LOG_ALERT => 'alert',
381
 * -  LOG_CRIT => 'critical',
382
 * - `LOG_ERR` => 'error',
383
 * - `LOG_WARNING` => 'warning',
384
 * - `LOG_NOTICE` => 'notice',
385
 * - `LOG_INFO` => 'info',
386
 * - `LOG_DEBUG` => 'debug',
387
 *
388
 * ### Usage:
389
 *
390
 * Write a message to the 'warning' log:
391
 *
392
 * `CakeLog::write('warning', 'Stuff is broken here');`
393
 *
394
 * @param int|string $type Type of message being written. When value is an integer
395
 *    or a string matching the recognized levels, then it will
396
 *    be treated log levels. Otherwise it's treated as scope.
397
 * @param string $message Message content to log
398
 * @param string|array $scope The scope(s) a log message is being created in.
399
 *    See CakeLog::config() for more information on logging scopes.
400
 * @return bool Success
401
 */
402
	public static function write($type, $message, $scope = array()) {
403
		if (empty(self::$_Collection)) {
404
			self::_init();
405
		}
406
 
407
		if (is_int($type) && isset(self::$_levels[$type])) {
408
			$type = self::$_levels[$type];
409
		}
410
		if (is_string($type) && empty($scope) && !in_array($type, self::$_levels)) {
411
			$scope = $type;
412
		}
413
		$logged = false;
414
		foreach (self::$_Collection->enabled() as $streamName) {
415
			$logger = self::$_Collection->{$streamName};
416
			$types = $scopes = $config = array();
417
			if (method_exists($logger, 'config')) {
418
				$config = $logger->config();
419
			}
420
			if (isset($config['types'])) {
421
				$types = $config['types'];
422
			}
423
			if (isset($config['scopes'])) {
424
				$scopes = $config['scopes'];
425
			}
426
			$inScope = (count(array_intersect((array)$scope, $scopes)) > 0);
427
			$correctLevel = in_array($type, $types);
428
 
429
			if (
430
				// No config is a catch all (bc mode)
431
				(empty($types) && empty($scopes)) ||
432
				// BC layer for mixing scope & level
433
				(in_array($type, $scopes)) ||
434
				// no scopes, but has level
435
				(empty($scopes) && $correctLevel) ||
436
				// exact scope + level
437
				($correctLevel && $inScope)
438
			) {
439
				$logger->write($type, $message);
440
				$logged = true;
441
			}
442
		}
443
		return $logged;
444
	}
445
 
446
/**
447
 * Convenience method to log emergency messages
448
 *
449
 * @param string $message log message
450
 * @param string|array $scope The scope(s) a log message is being created in.
451
 *    See CakeLog::config() for more information on logging scopes.
452
 * @return bool Success
453
 */
454
	public static function emergency($message, $scope = array()) {
455
		return self::write(self::$_levelMap['emergency'], $message, $scope);
456
	}
457
 
458
/**
459
 * Convenience method to log alert messages
460
 *
461
 * @param string $message log message
462
 * @param string|array $scope The scope(s) a log message is being created in.
463
 *    See CakeLog::config() for more information on logging scopes.
464
 * @return bool Success
465
 */
466
	public static function alert($message, $scope = array()) {
467
		return self::write(self::$_levelMap['alert'], $message, $scope);
468
	}
469
 
470
/**
471
 * Convenience method to log critical messages
472
 *
473
 * @param string $message log message
474
 * @param string|array $scope The scope(s) a log message is being created in.
475
 *    See CakeLog::config() for more information on logging scopes.
476
 * @return bool Success
477
 */
478
	public static function critical($message, $scope = array()) {
479
		return self::write(self::$_levelMap['critical'], $message, $scope);
480
	}
481
 
482
/**
483
 * Convenience method to log error messages
484
 *
485
 * @param string $message log message
486
 * @param string|array $scope The scope(s) a log message is being created in.
487
 *    See CakeLog::config() for more information on logging scopes.
488
 * @return bool Success
489
 */
490
	public static function error($message, $scope = array()) {
491
		return self::write(self::$_levelMap['error'], $message, $scope);
492
	}
493
 
494
/**
495
 * Convenience method to log warning messages
496
 *
497
 * @param string $message log message
498
 * @param string|array $scope The scope(s) a log message is being created in.
499
 *    See CakeLog::config() for more information on logging scopes.
500
 * @return bool Success
501
 */
502
	public static function warning($message, $scope = array()) {
503
		return self::write(self::$_levelMap['warning'], $message, $scope);
504
	}
505
 
506
/**
507
 * Convenience method to log notice messages
508
 *
509
 * @param string $message log message
510
 * @param string|array $scope The scope(s) a log message is being created in.
511
 *    See CakeLog::config() for more information on logging scopes.
512
 * @return bool Success
513
 */
514
	public static function notice($message, $scope = array()) {
515
		return self::write(self::$_levelMap['notice'], $message, $scope);
516
	}
517
 
518
/**
519
 * Convenience method to log debug messages
520
 *
521
 * @param string $message log message
522
 * @param string|array $scope The scope(s) a log message is being created in.
523
 *    See CakeLog::config() for more information on logging scopes.
524
 * @return bool Success
525
 */
526
	public static function debug($message, $scope = array()) {
527
		return self::write(self::$_levelMap['debug'], $message, $scope);
528
	}
529
 
530
/**
531
 * Convenience method to log info messages
532
 *
533
 * @param string $message log message
534
 * @param string|array $scope The scope(s) a log message is being created in.
535
 *    See CakeLog::config() for more information on logging scopes.
536
 * @return bool Success
537
 */
538
	public static function info($message, $scope = array()) {
539
		return self::write(self::$_levelMap['info'], $message, $scope);
540
	}
541
 
542
}