mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #184 from chillu/ss-log-tweaks
SS_Log: String args, extra data logging, "in line of..." formatting
This commit is contained in:
commit
1d4ac6842f
@ -163,7 +163,7 @@ class SS_Backtrace {
|
||||
foreach($bt as $item) {
|
||||
if($plainText) {
|
||||
$result .= self::full_func_name($item,true) . "\n";
|
||||
if(isset($item['line']) && isset($item['file'])) $result .= "line $item[line] of " . basename($item['file']) . "\n";
|
||||
if(isset($item['line']) && isset($item['file'])) $result .= basename($item['file']) . ":$item[line]\n";
|
||||
$result .= "\n";
|
||||
} else {
|
||||
if ($item['function'] == 'user_error') {
|
||||
@ -172,8 +172,8 @@ class SS_Backtrace {
|
||||
$name = self::full_func_name($item,true);
|
||||
}
|
||||
$result .= "<li><b>" . htmlentities($name, ENT_COMPAT, 'UTF-8') . "</b>\n<br />\n";
|
||||
$result .= isset($item['line']) ? "Line $item[line] of " : '';
|
||||
$result .= isset($item['file']) ? htmlentities(basename($item['file']), ENT_COMPAT, 'UTF-8') : '';
|
||||
$result .= isset($item['line']) ? ":$item[line]" : '';
|
||||
$result .= "</li>\n";
|
||||
}
|
||||
}
|
||||
|
@ -67,9 +67,9 @@ class Debug {
|
||||
if($showHeader) {
|
||||
$caller = Debug::caller();
|
||||
if(Director::is_ajax() || Director::is_cli())
|
||||
echo "Debug ($caller[class]$caller[type]$caller[function]() in line $caller[line] of " . basename($caller['file']) . ")\n";
|
||||
echo "Debug ($caller[class]$caller[type]$caller[function]() in " . basename($caller['file']) . ":$caller[line])\n";
|
||||
else
|
||||
echo "<div style=\"background-color: white; text-align: left;\">\n<hr>\n<h3>Debug <span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]() \n<span style=\"font-weight:normal\">in line</span> $caller[line] \n<span style=\"font-weight:normal\">of</span> " . basename($caller['file']) . ")</span>\n</h3>\n";
|
||||
echo "<div style=\"background-color: white; text-align: left;\">\n<hr>\n<h3>Debug <span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]() \nin " . basename($caller['file']) . ":$caller[line])</span>\n</h3>\n";
|
||||
}
|
||||
|
||||
echo Debug::text($val);
|
||||
@ -88,7 +88,7 @@ class Debug {
|
||||
static function endshow($val) {
|
||||
if(!Director::isLive()) {
|
||||
$caller = Debug::caller();
|
||||
echo "<hr>\n<h3>Debug \n<span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]() \n<span style=\"font-weight:normal\">in line</span> $caller[line] \n<span style=\"font-weight:normal\">of</span> " . basename($caller['file']) . ")</span>\n</h3>\n";
|
||||
echo "<hr>\n<h3>Debug \n<span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]() \nin " . basename($caller['file']) . ":$caller[line])</span>\n</h3>\n";
|
||||
echo Debug::text($val);
|
||||
die();
|
||||
}
|
||||
@ -102,7 +102,7 @@ class Debug {
|
||||
static function dump($val) {
|
||||
echo '<pre style="background-color:#ccc;padding:5px;font-size:14px;line-height:18px;">';
|
||||
$caller = Debug::caller();
|
||||
echo "<span style=\"font-size: 12px;color:#666;\">Line $caller[line] of " . basename($caller['file']) . ":</span>\n";
|
||||
echo "<span style=\"font-size: 12px;color:#666;\">" . basename($caller['file']) . ":$caller[line] - </span>\n";
|
||||
if (is_string($val)) print_r(wordwrap($val, 100));
|
||||
else print_r($val);
|
||||
echo '</pre>';
|
||||
|
46
dev/Log.php
46
dev/Log.php
@ -64,14 +64,41 @@ class SS_Log {
|
||||
protected static $logger;
|
||||
|
||||
/**
|
||||
* Get the logger currently in use, or create a new
|
||||
* one if it doesn't exist.
|
||||
* @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
|
||||
*/
|
||||
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(!self::$logger) {
|
||||
// Create default logger
|
||||
self::$logger = new self::$logger_class;
|
||||
|
||||
// Add default context (shouldn't change until the actual log event happens)
|
||||
foreach(self::$log_globals as $globalName => $keys) {
|
||||
foreach($keys as $key) {
|
||||
$val = @$GLOBALS[$globalName][$key];
|
||||
self::$logger->setEventItem(sprintf('$%s[\'%s\']', $globalName, $key), $val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return self::$logger;
|
||||
}
|
||||
@ -123,8 +150,9 @@ class SS_Log {
|
||||
*
|
||||
* @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) {
|
||||
public static function log($message, $priority, $extras = null) {
|
||||
if($message instanceof Exception) {
|
||||
$message = array(
|
||||
'errno' => '',
|
||||
@ -133,9 +161,19 @@ class SS_Log {
|
||||
'errline' => $message->getLine(),
|
||||
'errcontext' => $message->getTrace()
|
||||
);
|
||||
} elseif(is_string($message)) {
|
||||
$trace = SS_Backtrace::filtered_backtrace();
|
||||
$lastTrace = $trace[0];
|
||||
$message = array(
|
||||
'errno' => '',
|
||||
'errstr' => $message,
|
||||
'errfile' => @$lastTrace['file'],
|
||||
'errline' => @$lastTrace['line'],
|
||||
'errcontext' => $trace
|
||||
);
|
||||
}
|
||||
try {
|
||||
self::get_logger()->log($message, $priority);
|
||||
self::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
|
||||
|
@ -52,16 +52,30 @@ class SS_LogEmailWriter extends Zend_Log_Writer_Abstract {
|
||||
$subject = $formattedData['subject'];
|
||||
$data = $formattedData['data'];
|
||||
|
||||
$originalSMTP = ini_get('SMTP');
|
||||
// override the SMTP server with a custom one if required
|
||||
$originalSMTP = ini_get('SMTP');
|
||||
if($this->customSmtpServer) ini_set('SMTP', $this->customSmtpServer);
|
||||
|
||||
mail(
|
||||
$this->emailAddress,
|
||||
$subject,
|
||||
$data,
|
||||
"Content-type: text/html\nFrom: " . self::$send_from
|
||||
);
|
||||
// Use plain mail() implementation to avoid complexity of Mailer implementation.
|
||||
// Only use built-in mailer when we're in test mode (to allow introspection)
|
||||
$mailer = Email::mailer();
|
||||
if($mailer instanceof TestMailer) {
|
||||
$mailer->sendHTML(
|
||||
$this->emailAddress,
|
||||
null,
|
||||
$subject,
|
||||
$data,
|
||||
null,
|
||||
"Content-type: text/html\nFrom: " . self::$send_from
|
||||
);
|
||||
} else {
|
||||
mail(
|
||||
$this->emailAddress,
|
||||
$subject,
|
||||
$data,
|
||||
"Content-type: text/html\nFrom: " . self::$send_from
|
||||
);
|
||||
}
|
||||
|
||||
// reset the SMTP server to the original
|
||||
if($this->customSmtpServer) ini_set('SMTP', $originalSMTP);
|
||||
|
@ -35,8 +35,10 @@ class SS_LogErrorEmailFormatter implements Zend_Log_Formatter_Interface {
|
||||
$errline = $event['message']['errline'];
|
||||
$errcontext = $event['message']['errcontext'];
|
||||
|
||||
$data = "<div style=\"border: 5px $colour solid\">\n";
|
||||
$data .= "<p style=\"color: white; background-color: $colour; margin: 0\">$errorType: $errstr<br /> At line $errline in $errfile\n<br />\n<br />\n</p>\n";
|
||||
$data = '';
|
||||
$data .= '<style type="text/css">html, body, table {font-family: sans-serif; font-size: 12px;}</style>';
|
||||
$data .= "<div style=\"border: 5px $colour solid;\">\n";
|
||||
$data .= "<p style=\"color: white; background-color: $colour; margin: 0\">[$errorType] $errstr<br />$errfile:$errline\n<br />\n<br />\n</p>\n";
|
||||
|
||||
// Get a backtrace, filtering out debug method calls
|
||||
$data .= SS_Backtrace::backtrace(true, false, array(
|
||||
@ -44,15 +46,29 @@ class SS_LogErrorEmailFormatter implements Zend_Log_Formatter_Interface {
|
||||
'SS_LogEmailWriter->_write'
|
||||
));
|
||||
|
||||
// Compile extra data
|
||||
$blacklist = array('message', 'timestamp', 'priority', 'priorityName');
|
||||
$extras = array_diff_key($event, array_combine($blacklist, $blacklist));
|
||||
if($extras) {
|
||||
$data .= "<h3>Details</h3>\n";
|
||||
$data .= "<table class=\"extras\">\n";
|
||||
foreach($extras as $k => $v) {
|
||||
if(is_array($v)) $v = var_export($v, true);
|
||||
$data .= sprintf(
|
||||
"<tr><td><strong>%s</strong></td><td><pre>%s</pre></td></tr>\n", $k, $v);
|
||||
}
|
||||
$data .= "</table>\n";
|
||||
}
|
||||
|
||||
$data .= "</div>\n";
|
||||
|
||||
$relfile = Director::makeRelative($errfile);
|
||||
if($relfile[0] == '/') $relfile = substr($relfile, 1);
|
||||
if($relfile && $relfile[0] == '/') $relfile = substr($relfile, 1);
|
||||
|
||||
$host = @$_SERVER['HTTP_HOST'];
|
||||
$uri = @$_SERVER['REQUEST_URI'];
|
||||
|
||||
$subject = "$errorType at $relfile line {$errline} (http://{$host}{$uri})";
|
||||
$subject = "[$errorType] in $relfile:{$errline} (http://{$host}{$uri})";
|
||||
|
||||
return array(
|
||||
'subject' => $subject,
|
||||
|
@ -9,28 +9,62 @@ class SS_LogTest extends SapphireTest {
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
SS_Log::clear_writers(); // this test will break if existing writers are available!
|
||||
$this->testEmailWriter = new SS_LogEmailWriter('sean@silverstripe.com');
|
||||
$this->testFileWriter = new SS_LogFileWriter('../test.log');
|
||||
SS_Log::add_writer($this->testEmailWriter, SS_Log::ERR);
|
||||
SS_Log::add_writer($this->testFileWriter, SS_Log::WARN);
|
||||
|
||||
SS_Log::clear_writers();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
parent::tearDown();
|
||||
|
||||
SS_Log::clear_writers();
|
||||
}
|
||||
|
||||
function testExistingWriter() {
|
||||
$testEmailWriter = new SS_LogEmailWriter('test@test.com');
|
||||
$testFileWriter = new SS_LogFileWriter('../test.log');
|
||||
SS_Log::add_writer($testEmailWriter, SS_Log::ERR);
|
||||
SS_Log::add_writer($testFileWriter, SS_Log::WARN);
|
||||
|
||||
$writers = SS_Log::get_writers();
|
||||
$this->assertType('array', $writers);
|
||||
$this->assertEquals(2, count($writers));
|
||||
}
|
||||
|
||||
function testRemoveWriter() {
|
||||
SS_Log::remove_writer($this->testEmailWriter);
|
||||
$testEmailWriter = new SS_LogEmailWriter('test@test.com');
|
||||
$testFileWriter = new SS_LogFileWriter('../test.log');
|
||||
SS_Log::add_writer($testEmailWriter, SS_Log::ERR);
|
||||
SS_Log::add_writer($testFileWriter, SS_Log::WARN);
|
||||
|
||||
SS_Log::remove_writer($testEmailWriter);
|
||||
$writers = SS_Log::get_writers();
|
||||
$this->assertType('array', $writers);
|
||||
$this->assertEquals(1, count($writers));
|
||||
SS_Log::remove_writer($this->testFileWriter);
|
||||
|
||||
SS_Log::remove_writer($testFileWriter);
|
||||
$writers = SS_Log::get_writers();
|
||||
$this->assertType('array', $writers);
|
||||
$this->assertEquals(0, count($writers));
|
||||
}
|
||||
|
||||
function testEmailWriter() {
|
||||
$testEmailWriter = new SS_LogEmailWriter('test@test.com');
|
||||
SS_Log::add_writer($testEmailWriter, SS_Log::ERR);
|
||||
|
||||
SS_Log::log('Email test', SS_LOG::ERR, array('my-string' => 'test', 'my-array' => array('one' => 1)));
|
||||
$this->assertEmailSent('test@test.com');
|
||||
$email = $this->findEmail('test@test.com');
|
||||
$parser = new CSSContentParser($email['htmlContent']);
|
||||
$extras = $parser->getBySelector('table.extras');
|
||||
$extraRows = $extras[0]->tr;
|
||||
$this->assertContains('my-string', $extraRows[count($extraRows)-2]->td[0]->asXML(), 'Contains extra data key');
|
||||
$this->assertContains('test', $extraRows[count($extraRows)-2]->td[1]->asXML(), 'Contains extra data value');
|
||||
$this->assertContains('my-array', $extraRows[count($extraRows)-1]->td[0]->asXML(), 'Contains extra data key');
|
||||
$this->assertContains(
|
||||
"array('one'=>1,)",
|
||||
str_replace(array("\r", "\n", " "), '', $extraRows[count($extraRows)-1]->td[1]->asXML()),
|
||||
'Serializes arrays correctly'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user