source: Dev/branches/cakephp/cake/libs/cake_log.php @ 126

Last change on this file since 126 was 126, checked in by fpvanagthoven, 14 years ago

Cakephp branch.

File size: 7.7 KB
Line 
1<?php
2/**
3 * Logging.
4 *
5 * Log messages to text files.
6 *
7 * PHP versions 4 and 5
8 *
9 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
10 * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
11 *
12 * Licensed under The MIT License
13 * Redistributions of files must retain the above copyright notice.
14 *
15 * @copyright     Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
16 * @link          http://cakephp.org CakePHP(tm) Project
17 * @package       cake
18 * @subpackage    cake.cake.libs
19 * @since         CakePHP(tm) v 0.2.9
20 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
21 */
22/**
23 * Set up error level constants to be used within the framework if they are not defined within the
24 * system.
25 *
26 */
27        if (!defined('LOG_WARNING')) {
28                define('LOG_WARNING', 3);
29        }
30        if (!defined('LOG_NOTICE')) {
31                define('LOG_NOTICE', 4);
32        }
33        if (!defined('LOG_DEBUG')) {
34                define('LOG_DEBUG', 5);
35        }
36        if (!defined('LOG_INFO')) {
37                define('LOG_INFO', 6);
38        }
39
40/**
41 * Logs messages to configured Log adapters.  One or more adapters can be configured
42 * using CakeLogs's methods.  If you don't configure any adapters, and write to the logs
43 * a default FileLog will be autoconfigured for you.
44 *
45 * @package       cake
46 * @subpackage    cake.cake.libs
47 */
48class CakeLog {
49
50/**
51 * An array of connected streams.
52 * Each stream represents a callable that will be called when write() is called.
53 *
54 * @var array
55 * @access protected
56 */
57        var $_streams = array();
58
59/**
60 * Get an instance
61 *
62 * @return void
63 * @static
64 */
65        function &getInstance() {
66                static $instance = array();
67                if (!isset($instance[0])) {
68                        $instance[0] =& new CakeLog();
69                }
70                return $instance[0];
71        }
72
73/**
74 * Configure and add a new logging stream to CakeLog
75 * You can use add loggers from app/libs use app.loggername, or any plugin/libs using plugin.loggername.
76 *
77 * ### Usage:
78 *
79 * {{{
80 * CakeLog::config('second_file', array(
81 *              'engine' => 'FileLog',
82 *              'path' => '/var/logs/my_app/'
83 * ));
84 * }}}
85 *
86 * Will configure a FileLog instance to use the specified path.  All options that are not `engine`
87 * are passed onto the logging adapter, and handled there.  Any class can be configured as a logging
88 * adapter as long as it implements a `write` method with the following signature.
89 *
90 * `write($type, $message)`
91 *
92 * For an explaination of these parameters, see CakeLog::write()
93 *
94 * @param string $key The keyname for this logger, used to remove the logger later.
95 * @param array $config Array of configuration information for the logger
96 * @return boolean success of configuration.
97 * @static
98 */
99        function config($key, $config) {
100                if (empty($config['engine'])) {
101                        trigger_error(__('Missing logger classname', true), E_USER_WARNING);
102                        return false;
103                }
104                $self =& CakeLog::getInstance();
105                $className = $self->_getLogger($config['engine']);
106                if (!$className) {
107                        return false;
108                }
109                unset($config['engine']);
110                $self->_streams[$key] = new $className($config);
111                return true;
112        }
113
114/**
115 * Attempts to import a logger class from the various paths it could be on.
116 * Checks that the logger class implements a write method as well.
117 *
118 * @param string $loggerName the plugin.className of the logger class you want to build.
119 * @return mixed boolean false on any failures, string of classname to use if search was successful.
120 * @access protected
121 */
122        function _getLogger($loggerName) {
123                list($plugin, $loggerName) = pluginSplit($loggerName);
124
125                if ($plugin) {
126                        App::import('Lib', $plugin . '.log/' . $loggerName);
127                } else {
128                        if (!App::import('Lib', 'log/' . $loggerName)) {
129                                App::import('Core', 'log/' . $loggerName);
130                        }
131                }
132                if (!class_exists($loggerName)) {
133                        trigger_error(sprintf(__('Could not load logger class %s', true), $loggerName), E_USER_WARNING);
134                        return false;
135                }
136                if (!is_callable(array($loggerName, 'write'))) {
137                        trigger_error(
138                                sprintf(__('logger class %s does not implement a write method.', true), $loggerName),
139                                E_USER_WARNING
140                        );
141                        return false;
142                }
143                return $loggerName;
144        }
145
146/**
147 * Returns the keynames of the currently active streams
148 *
149 * @return array Array of configured log streams.
150 * @access public
151 * @static
152 */
153        function configured() {
154                $self =& CakeLog::getInstance();
155                return array_keys($self->_streams);
156        }
157
158/**
159 * Removes a stream from the active streams.  Once a stream has been removed
160 * it will no longer have messages sent to it.
161 *
162 * @param string $keyname Key name of a configured stream to remove.
163 * @return void
164 * @access public
165 * @static
166 */
167        function drop($streamName) {
168                $self =& CakeLog::getInstance();
169                unset($self->_streams[$streamName]);
170        }
171
172/**
173 * Configures the automatic/default stream a FileLog.
174 *
175 * @return void
176 * @access protected
177 */
178        function _autoConfig() {
179                if (!class_exists('FileLog')) {
180                        App::import('Core', 'log/FileLog');
181                }
182                $this->_streams['default'] =& new FileLog(array('path' => LOGS));
183        }
184
185/**
186 * Writes the given message and type to all of the configured log adapters.
187 * Configured adapters are passed both the $type and $message variables. $type
188 * is one of the following strings/values.
189 *
190 * ### Types:
191 *
192 * - `LOG_WARNING` => 'warning',
193 * - `LOG_NOTICE` => 'notice',
194 * - `LOG_INFO` => 'info',
195 * - `LOG_DEBUG` => 'debug',
196 * - `LOG_ERR` => 'error',
197 * - `LOG_ERROR` => 'error'
198 *
199 * ### Usage:
200 *
201 * Write a message to the 'warning' log:
202 *
203 * `CakeLog::write('warning', 'Stuff is broken here');`
204 *
205 * @param string $type Type of message being written
206 * @param string $message Message content to log
207 * @return boolean Success
208 * @access public
209 * @static
210 */
211        function write($type, $message) {
212                if (!defined('LOG_ERROR')) {
213                        define('LOG_ERROR', 2);
214                }
215                if (!defined('LOG_ERR')) {
216                        define('LOG_ERR', LOG_ERROR);
217                }
218                $levels = array(
219                        LOG_WARNING => 'warning',
220                        LOG_NOTICE => 'notice',
221                        LOG_INFO => 'info',
222                        LOG_DEBUG => 'debug',
223                        LOG_ERR => 'error',
224                        LOG_ERROR => 'error'
225                );
226
227                if (is_int($type) && isset($levels[$type])) {
228                        $type = $levels[$type];
229                }
230                $self =& CakeLog::getInstance();
231                if (empty($self->_streams)) {
232                        $self->_autoConfig();
233                }
234                $keys = array_keys($self->_streams);
235                foreach ($keys as $key) {
236                        $logger =& $self->_streams[$key];
237                        $logger->write($type, $message);
238                }
239                return true;
240        }
241
242/**
243 * An error_handler that will log errors to file using CakeLog::write();
244 * You can control how verbose and what type of errors this error_handler will
245 * catch using `Configure::write('log', $value)`.  See core.php for more information.
246 *
247 *
248 * @param integer $code Code of error
249 * @param string $description Error description
250 * @param string $file File on which error occurred
251 * @param integer $line Line that triggered the error
252 * @param array $context Context
253 * @return void
254 */
255        function handleError($code, $description, $file = null, $line = null, $context = null) {
256                if ($code === 2048 || $code === 8192 || error_reporting() === 0) {
257                        return;
258                }
259                switch ($code) {
260                        case E_PARSE:
261                        case E_ERROR:
262                        case E_CORE_ERROR:
263                        case E_COMPILE_ERROR:
264                        case E_USER_ERROR:
265                                $error = 'Fatal Error';
266                                $level = LOG_ERROR;
267                        break;
268                        case E_WARNING:
269                        case E_USER_WARNING:
270                        case E_COMPILE_WARNING:
271                        case E_RECOVERABLE_ERROR:
272                                $error = 'Warning';
273                                $level = LOG_WARNING;
274                        break;
275                        case E_NOTICE:
276                        case E_USER_NOTICE:
277                                $error = 'Notice';
278                                $level = LOG_NOTICE;
279                        break;
280                        default:
281                                return;
282                        break;
283                }
284                $message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
285                CakeLog::write($level, $message);
286        }
287}
288
289if (!defined('DISABLE_DEFAULT_ERROR_HANDLING')) {
290        $cakeLog =& CakeLog::getInstance();
291        if (PHP5) {
292                set_error_handler(array($cakeLog, 'handleError'), error_reporting());
293        } else {
294                set_error_handler(array($cakeLog, 'handleError'));
295        }
296}
Note: See TracBrowser for help on using the repository browser.