Log.php
5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<?php
require_once 'Zend/Log.php';
/**
* Wrapper class for a logging handler like {@link Zend_Log}
* which takes a message (or a map of context variables) and
* sends it to one or more {@link Zend_Log_Writer_Abstract}
* subclasses for output.
*
* These priorities are currently supported:
* - SS_Log::ERR
* - SS_Log::WARN
* - SS_Log::NOTICE
*
* You can add an error writer by calling {@link SS_Log::add_writer()}
*
* Example usage of logging errors by email notification:
* <code>
* SS_Log::add_writer(new SS_LogEmailWriter('my@email.com'), SS_Log::ERR);
* </code>
*
* Example usage of logging errors by file:
* <code>
* SS_Log::add_writer(new SS_LogFileWriter('/var/log/silverstripe/errors.log'), SS_Log::ERR);
* </code>
*
* Example usage of logging at warnings and errors by setting the priority to '<=':
* <code>
* SS_Log::add_writer(new SS_LogEmailWriter('my@email.com'), SS_Log::WARN, '<=');
* </code>
*
* Each writer object can be assigned a formatter. The formatter is
* responsible for formatting the message before giving it to the writer.
* {@link SS_LogErrorEmailFormatter} is such an example that formats errors
* into HTML for human readability in an email client.
*
* Formatters are added to writers like this:
* <code>
* $logEmailWriter = new SS_LogEmailWriter('my@email.com');
* $myEmailFormatter = new MyLogEmailFormatter();
* $logEmailWriter->setFormatter($myEmailFormatter);
* </code>
*
* @package framework
* @subpackage dev
*/
class SS_Log {
const ERR = Zend_Log::ERR;
const WARN = Zend_Log::WARN;
const NOTICE = Zend_Log::NOTICE;
const INFO = Zend_Log::INFO;
const DEBUG = Zend_Log::DEBUG;
/**
* Logger class to use.
* @see SS_Log::get_logger()
* @var string
*/
public static $logger_class = 'SS_ZendLog';
/**
* @see SS_Log::get_logger()
* @var object
*/
protected static $logger;
/**
* @var array Logs additional context from PHP's superglobals.
* Caution: Depends on logger implementation (mainly targeted at {@link SS_LogEmailWriter}).
* @see http://framework.zend.com/manual/en/zend.log.overview.html#zend.log.overview.understanding-fields
*/
protected static $log_globals = array(
'_SERVER' => array(
'HTTP_ACCEPT',
'HTTP_ACCEPT_CHARSET',
'HTTP_ACCEPT_ENCODING',
'HTTP_ACCEPT_LANGUAGE',
'HTTP_REFERRER',
'HTTP_USER_AGENT',
'HTTPS',
'REMOTE_ADDR',
),
);
/**
* Get the logger currently in use, or create a new one if it doesn't exist.
*
* @return object
*/
public static function get_logger() {
if(!static::$logger) {
// Create default logger
static::$logger = new static::$logger_class;
// Add default context (shouldn't change until the actual log event happens)
foreach(static::$log_globals as $globalName => $keys) {
foreach($keys as $key) {
$val = isset($GLOBALS[$globalName][$key]) ? $GLOBALS[$globalName][$key] : null;
static::$logger->setEventItem(sprintf('$%s[\'%s\']', $globalName, $key), $val);
}
}
}
return static::$logger;
}
/**
* Get all writers in use by the logger.
* @return array Collection of Zend_Log_Writer_Abstract instances
*/
public static function get_writers() {
return static::get_logger()->getWriters();
}
/**
* Remove all writers currently in use.
*/
public static function clear_writers() {
static::get_logger()->clearWriters();
}
/**
* Remove a writer instance from the logger.
* @param object $writer Zend_Log_Writer_Abstract instance
*/
public static function remove_writer($writer) {
static::get_logger()->removeWriter($writer);
}
/**
* Add a writer instance to the logger.
* @param object $writer Zend_Log_Writer_Abstract instance
* @param const $priority Priority. Possible values: SS_Log::ERR, SS_Log::WARN or SS_Log::NOTICE
* @param $comparison Priority comparison operator. Acts on the integer values of the error
* levels, where more serious errors are lower numbers. By default this is "=", which means only
* the given priority will be logged. Set to "<=" if you want to track errors of *at least*
* the given priority.
*/
public static function add_writer($writer, $priority = null, $comparison = '=') {
if($priority) $writer->addFilter(new Zend_Log_Filter_Priority($priority, $comparison));
static::get_logger()->addWriter($writer);
}
/**
* Dispatch a message by priority level.
*
* The message parameter can be either a string (a simple error
* message), or an array of variables. The latter is useful for passing
* along a list of debug information for the writer to handle, such as
* error code, error line, error context (backtrace).
*
* @param mixed $message Exception object or array of error context variables
* @param const $priority Priority. Possible values: SS_Log::ERR, SS_Log::WARN or SS_Log::NOTICE
* @param mixed $extras Extra information to log in event
*/
public static function log($message, $priority, $extras = null) {
if($message instanceof Exception) {
$message = array(
'errno' => '',
'errstr' => $message->getMessage(),
'errfile' => $message->getFile(),
'errline' => $message->getLine(),
'errcontext' => $message->getTrace()
);
} elseif(is_string($message)) {
$trace = SS_Backtrace::filtered_backtrace();
$lastTrace = $trace[0];
$message = array(
'errno' => '',
'errstr' => $message,
'errfile' => isset($lastTrace['file']) ? $lastTrace['file'] : null,
'errline' => isset($lastTrace['line']) ? $lastTrace['line'] : null,
'errcontext' => $trace
);
}
try {
static::get_logger()->log($message, $priority, $extras);
} catch(Exception $e) {
// @todo How do we handle exceptions thrown from Zend_Log?
// For example, an exception is thrown if no writers are added
}
}
}