統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Log / CakeLog.php @ 635eef61

履歴 | 表示 | アノテート | ダウンロード (15.363 KB)

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
}