Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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