Permalink
Browse files

ENHANCEMENT Allow logging of extra data in SS_Log::log() (currently o…

…nly displayed through SS_LogEmailWriter)
  • Loading branch information...
1 parent d3be6ed commit 24e2003e35adfe2062e55edcfd6c7f3f7677d5f5 @chillu chillu committed Feb 6, 2012
Showing with 108 additions and 18 deletions.
  1. +32 −4 dev/Log.php
  2. +21 −7 dev/LogEmailWriter.php
  3. +14 −0 dev/LogErrorEmailFormatter.php
  4. +41 −7 tests/dev/LogTest.php
View
@@ -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 @@ public static function add_writer($writer, $priority = null, $comparison = '=')
*
* @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' => '',
@@ -145,7 +173,7 @@ public static function log($message, $priority) {
);
}
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
View
@@ -52,16 +52,30 @@ public function _write($event) {
$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);
@@ -46,6 +46,20 @@ public function format($event) {
'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);
View
@@ -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'=&gt;1,)",
+ str_replace(array("\r", "\n", " "), '', $extraRows[count($extraRows)-1]->td[1]->asXML()),
+ 'Serializes arrays correctly'
+ );
+ }
+
}

0 comments on commit 24e2003

Please sign in to comment.