[BUGFIX] Handle exceptions in Logging API 02/37602/5
authorMarkus Klein <klein.t3@reelworx.at>
Fri, 6 Mar 2015 17:16:38 +0000 (18:16 +0100)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Sat, 7 Mar 2015 18:48:16 +0000 (19:48 +0100)
Do not run exceptions through json_encode() but convert them to strings
first.

Resolves: #65577
Releases: master, 6.2
Change-Id: I46e743480b32010bff39784a3572a5fe96cf0859
Reviewed-on: http://review.typo3.org/37602
Reviewed-by: Steffen Müller <typo3@t3node.com>
Tested-by: Steffen Müller <typo3@t3node.com>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
typo3/sysext/core/Classes/Log/LogRecord.php
typo3/sysext/core/Classes/Log/Processor/IntrospectionProcessor.php
typo3/sysext/core/Classes/Log/Writer/FileWriter.php
typo3/sysext/core/Tests/Unit/Log/LogRecordTest.php

index f956ef4..2a851ac 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Core\Log;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Core\Bootstrap;
+
 /**
  * Log record
  *
@@ -98,7 +100,7 @@ class LogRecord implements \ArrayAccess {
         * @param array $data Additional data
         */
        public function __construct($component = '', $level, $message, array $data = array()) {
-               $this->setRequestId(\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->getRequestId())
+               $this->setRequestId(Bootstrap::getInstance()->getRequestId())
                        ->setCreated(microtime(TRUE))
                        ->setComponent($component)
                        ->setLevel($level)
@@ -250,7 +252,15 @@ class LogRecord implements \ArrayAccess {
        public function __toString() {
                $timestamp = date('r', (int)$this->created);
                $levelName = LogLevel::getName($this->level);
-               $data = !empty($this->data) ? '- ' . json_encode($this->data) : '';
+               $data = '';
+               if (!empty($this->data)) {
+                       // According to PSR3 the exception-key may hold an \Exception
+                       // Since json_encode() does not encode an exception, we run the _toString() here
+                       if (isset($this->data['exception']) && $this->data['exception'] instanceof \Exception) {
+                               $this->data['exception'] = (string)$this->data['exception'];
+                       }
+                       $data = '- ' . json_encode($this->data);
+               }
                $logRecordString = sprintf('%s [%s] request="%s" component="%s": %s %s', $timestamp, $levelName, $this->requestId, $this->component, $this->message, $data);
                return $logRecordString;
        }
index c4077a3..29ed7f7 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Core\Log\Processor;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Log\LogRecord;
+
 /**
  * Introspection processor to automatically add where the log record came from.
  *
@@ -77,16 +79,16 @@ class IntrospectionProcessor extends AbstractProcessor {
         * Add debug backtrace information to logRecord
         * It adds: filepath, line number, class and function name
         *
-        * @param \TYPO3\CMS\Core\Log\LogRecord $logRecord The log record to process
-        * @return \TYPO3\CMS\Core\Log\LogRecord The processed log record with additional data
+        * @param LogRecord $logRecord The log record to process
+        * @return LogRecord The processed log record with additional data
         * @see debug_backtrace()
         */
-       public function processLogRecord(\TYPO3\CMS\Core\Log\LogRecord $logRecord) {
+       public function processLogRecord(LogRecord $logRecord) {
                $trace = $this->getDebugBacktrace();
 
                // skip TYPO3\CMS\Core\Log classes
                foreach ($trace as $traceEntry) {
-                       if (isset($traceEntry['class']) && FALSE !== strpos($traceEntry['class'], \TYPO3\CMS\Core\Log::class)) {
+                       if (isset($traceEntry['class']) && FALSE !== strpos($traceEntry['class'], 'TYPO3\\CMS\\Core\\Log')) {
                                $trace = $this->shiftBacktraceLevel($trace);
                        } else {
                                break;
@@ -94,7 +96,7 @@ class IntrospectionProcessor extends AbstractProcessor {
                }
 
                // shift a given number of entries from the trace
-               for($i = 0; $i < $this->shiftBackTraceLevel; $i++) {
+               for ($i = 0; $i < $this->shiftBackTraceLevel; $i++) {
                        // shift only if afterwards there is at least one entry left after.
                        if (count($trace) > 1) {
                                $trace = $this->shiftBacktraceLevel($trace);
index c7a948e..0f191d5 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Core\Log\Writer;
  */
 
 use TYPO3\CMS\Core\Log\Exception\InvalidLogWriterConfigurationException;
+use TYPO3\CMS\Core\Log\LogRecord;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -55,7 +56,7 @@ class FileWriter extends AbstractWriter {
         * Constructor, opens the log file handle
         *
         * @param array $options
-        * @return \TYPO3\CMS\Core\Log\Writer\FileWriter
+        * @return FileWriter
         */
        public function __construct(array $options = array()) {
                // the parent constructor reads $options and sets them
@@ -76,8 +77,8 @@ class FileWriter extends AbstractWriter {
         * Sets the path to the log file.
         *
         * @param string $logFile path to the log file, relative to PATH_site
-        * @return \TYPO3\CMS\Core\Log\Writer\WriterInterface
-        * @throws \TYPO3\CMS\Core\Log\Exception\InvalidLogWriterConfigurationException
+        * @return WriterInterface
+        * @throws InvalidLogWriterConfigurationException
         */
        public function setLogFile($logFile) {
 
@@ -106,11 +107,11 @@ class FileWriter extends AbstractWriter {
        /**
         * Writes the log record
         *
-        * @param \TYPO3\CMS\Core\Log\LogRecord $record Log record
-        * @return \TYPO3\CMS\Core\Log\Writer\WriterInterface $this
+        * @param LogRecord $record Log record
+        * @return WriterInterface $this
         * @throws \RuntimeException
         */
-       public function writeLog(\TYPO3\CMS\Core\Log\LogRecord $record) {
+       public function writeLog(LogRecord $record) {
                if (FALSE === fwrite(self::$logFileHandles[$this->logFile], $record . LF)) {
                        throw new \RuntimeException('Could not write log record to log file', 1345036335);
                }
index a10f05d..7685bb9 100644 (file)
@@ -151,4 +151,13 @@ class LogRecordTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $this->assertContains(json_encode($dataArray), (string)$record);
        }
 
+       /**
+        * @test
+        */
+       public function toStringIncludesExceptionDataAsJson() {
+               $dataArray = array('exception' => new \Exception('foo'));
+               $record = $this->getRecord(array('data' => $dataArray));
+               $this->assertContains('\'Exception\' with message \'foo\'', (string)$record);
+       }
+
 }