* SS_Log::add_writer(new SS_LogEmailWriter('my@email.com'), SS_Log::ERR); * * * Example usage of logging errors by file: * * SS_Log::add_writer(new SS_LogFileWriter('/var/log/silverstripe/errors.log'), SS_Log::ERR); * * * Example usage of logging at warnings and errors by setting the priority to '<=': * * SS_Log::add_writer(new SS_LogEmailWriter('my@email.com'), SS_Log::WARN, '<='); * * * 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: * * $logEmailWriter = new SS_LogEmailWriter('my@email.com'); * $myEmailFormatter = new MyLogEmailFormatter(); * $logEmailWriter->setFormatter($myEmailFormatter); * * * @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 SS_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 SS_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 SS_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 SS_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 } } }