[FEATURE][DB][CONF]: Add a central logging API
authorSteffen Müller <typo3@t3node.com>
Sun, 12 Aug 2012 01:54:56 +0000 (03:54 +0200)
committerIngo Renner <ingo@typo3.org>
Thu, 16 Aug 2012 16:32:27 +0000 (18:32 +0200)
Change-Id: I58ec40a9ede4458374a33317e861a3064e518e2b
Resolves: #39712
Depends: #39738 (Documentation)
Releases: 6.0
Reviewed-on: http://review.typo3.org/13604
Reviewed-by: Ingo Renner
Tested-by: Ingo Renner
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Jigal van Hemert
Tested-by: Jigal van Hemert
40 files changed:
t3lib/core_autoload.php
t3lib/log/class.t3lib_log_level.php [new file with mode: 0644]
t3lib/log/class.t3lib_log_logger.php [new file with mode: 0644]
t3lib/log/class.t3lib_log_logmanager.php [new file with mode: 0644]
t3lib/log/class.t3lib_log_record.php [new file with mode: 0644]
t3lib/log/processor/class.t3lib_log_processor_abstract.php [new file with mode: 0644]
t3lib/log/processor/class.t3lib_log_processor_abstractmemory.php [new file with mode: 0644]
t3lib/log/processor/class.t3lib_log_processor_introspection.php [new file with mode: 0644]
t3lib/log/processor/class.t3lib_log_processor_memorypeakusage.php [new file with mode: 0644]
t3lib/log/processor/class.t3lib_log_processor_memoryusage.php [new file with mode: 0644]
t3lib/log/processor/class.t3lib_log_processor_null.php [new file with mode: 0644]
t3lib/log/processor/class.t3lib_log_processor_web.php [new file with mode: 0644]
t3lib/log/processor/interfaces/interface.t3lib_log_processor_processor.php [new file with mode: 0644]
t3lib/log/writer/class.t3lib_log_writer_abstract.php [new file with mode: 0644]
t3lib/log/writer/class.t3lib_log_writer_database.php [new file with mode: 0644]
t3lib/log/writer/class.t3lib_log_writer_file.php [new file with mode: 0644]
t3lib/log/writer/class.t3lib_log_writer_null.php [new file with mode: 0644]
t3lib/log/writer/class.t3lib_log_writer_phperrorlog.php [new file with mode: 0644]
t3lib/log/writer/class.t3lib_log_writer_syslog.php [new file with mode: 0644]
t3lib/log/writer/interfaces/interface.t3lib_log_writer_writer.php [new file with mode: 0644]
t3lib/stddb/DefaultConfiguration.php
t3lib/stddb/tables.sql
tests/Unit/t3lib/log/class.t3lib_log_levelTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/class.t3lib_log_loggerTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/class.t3lib_log_logmanagerTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/class.t3lib_log_recordTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_abstractTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_abstractmemoryTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_introspectionTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_memoryPeakUsageTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_memoryUsageTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_processorTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_test.php [new file with mode: 0644]
tests/Unit/t3lib/log/processor/class.t3lib_log_processor_webTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/writer/class.t3lib_log_writer_abstractTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/writer/class.t3lib_log_writer_databaseTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/writer/class.t3lib_log_writer_failing.php [new file with mode: 0644]
tests/Unit/t3lib/log/writer/class.t3lib_log_writer_fileTest.php [new file with mode: 0644]
tests/Unit/t3lib/log/writer/class.t3lib_log_writer_test.php [new file with mode: 0644]
typo3/classes/Bootstrap/BaseSetup.php

index d20de05..1fd1a05 100644 (file)
@@ -188,6 +188,25 @@ $t3libClasses = array(
        't3lib_loadmodules' => PATH_t3lib . 'class.t3lib_loadmodules.php',
        't3lib_localrecordlistgettablehook' => PATH_t3lib . 'interfaces/interface.t3lib_localrecordlistgettablehook.php',
        't3lib_lock' => PATH_t3lib . 'class.t3lib_lock.php',
+       't3lib_log_level' => PATH_t3lib . 'log/class.t3lib_log_level.php',
+       't3lib_log_logger' => PATH_t3lib . 'log/class.t3lib_log_logger.php',
+       't3lib_log_logmanager' => PATH_t3lib . 'log/class.t3lib_log_logmanager.php',
+       't3lib_log_processor_abstract' => PATH_t3lib . 'log/processor/class.t3lib_log_processor_abstract.php',
+       't3lib_log_processor_abstractmemory' => PATH_t3lib . 'log/processor/class.t3lib_log_processor_abstractmemory.php',
+       't3lib_log_processor_introspection' => PATH_t3lib . 'log/processor/class.t3lib_log_processor_introspection.php',
+       't3lib_log_processor_memorypeakusage' => PATH_t3lib . 'log/processor/class.t3lib_log_processor_memorypeakusage.php',
+       't3lib_log_processor_memoryusage' => PATH_t3lib . 'log/processor/class.t3lib_log_processor_memoryusage.php',
+       't3lib_log_processor_null' => PATH_t3lib . 'log/processor/class.t3lib_log_processor_null.php',
+       't3lib_log_processor_processor' => PATH_t3lib . 'log/processor/interfaces/interface.t3lib_log_processor_processor.php',
+       't3lib_log_processor_web' => PATH_t3lib . 'log/processor/class.t3lib_log_processor_web.php',
+       't3lib_log_record' => PATH_t3lib . 'log/class.t3lib_log_record.php',
+       't3lib_log_writer_abstract' => PATH_t3lib . 'log/writer/class.t3lib_log_writer_abstract.php',
+       't3lib_log_writer_database' => PATH_t3lib . 'log/writer/class.t3lib_log_writer_database.php',
+       't3lib_log_writer_file' => PATH_t3lib . 'log/writer/class.t3lib_log_writer_file.php',
+       't3lib_log_writer_null' => PATH_t3lib . 'log/writer/class.t3lib_log_writer_null.php',
+       't3lib_log_writer_phperrorlog' => PATH_t3lib . 'log/writer/class.t3lib_log_writer_phperrorlog.php',
+       't3lib_log_writer_syslog' => PATH_t3lib . 'log/writer/class.t3lib_log_writer_syslog.php',
+       't3lib_log_writer_writer' => PATH_t3lib . 'log/writer/interfaces/interface.t3lib_log_writer_writer.php',
        't3lib_mail_mailer' => PATH_t3lib . 'mail/class.t3lib_mail_mailer.php',
        't3lib_mail_maileradapter' => PATH_t3lib . 'interfaces/interface.t3lib_mail_maileradapter.php',
        't3lib_mail_mboxtransport' => PATH_t3lib . 'mail/class.t3lib_mail_mboxtransport.php',
diff --git a/t3lib/log/class.t3lib_log_level.php b/t3lib/log/class.t3lib_log_level.php
new file mode 100644 (file)
index 0000000..95f612a
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Log levels according to RFC 3164
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_Level {
+
+       /**
+        * Emergency: system is unusable
+        *
+        * You'd likely not be able to reach the system. You better have an SLA in
+        * place when this happens.
+        *
+        * @var integer
+        */
+       const EMERGENCY = 0;
+
+       /**
+        * Alert: action must be taken immediately
+        *
+        * Example: Entire website down, database unavailable, etc.
+        *
+        * @var integer
+        */
+       const ALERT = 1;
+
+       /**
+        * Critical: critical conditions
+        *
+        * Example: unexpected exception.
+        *
+        * @var integer
+        */
+       const CRITICAL = 2;
+
+       /**
+        * Error: error conditions
+        *
+        * Example: Runtime error.
+        *
+        * @var integer
+        */
+       const ERROR = 3;
+
+       /**
+        * Warning: warning conditions
+        *
+        * Examples: Use of deprecated APIs, undesirable things that are not
+        * necessarily wrong.
+        *
+        * @var integer
+        */
+       const WARNING = 4;
+
+       /**
+        * Notice: normal but significant condition
+        *
+        * Example: things you should have a look at, nothing to worry about though.
+        *
+        * @var integer
+        */
+       const NOTICE = 5;
+
+       /**
+        * Informational: informational messages
+        *
+        * Examples: User logs in, SQL logs.
+        *
+        * @var integer
+        */
+       const INFO = 6;
+
+       /**
+        * Debug: debug-level messages
+        *
+        * Example: Detailed status information.
+        *
+        * @var integer
+        */
+       const DEBUG = 7;
+
+       /**
+        * Reverse look up of log level to level name.
+        *
+        * @var array
+        */
+       protected static $levels = array(
+               self::EMERGENCY => 'EMERGENCY',
+               self::ALERT     => 'ALERT',
+               self::CRITICAL  => 'CRITICAL',
+               self::ERROR     => 'ERROR',
+               self::WARNING   => 'WARNING',
+               self::NOTICE    => 'NOTICE',
+               self::INFO      => 'INFO',
+               self::DEBUG     => 'DEBUG'
+       );
+
+       /**
+        * Resolves the name of a log level.
+        *
+        * @param integer $level Log level.
+        * @return string Log level name.
+        */
+       public static function getName($level) {
+               self::validateLevel($level);
+
+               return self::$levels[$level];
+       }
+
+       /**
+        * Checks a level for validity,
+        * whether it is an integer and in the range of 0-7.
+        *
+        * @param integer $level log level to validate
+        * @return boolean TRUE if the given log level is valid, FALSE otherwise
+        */
+       public static function isValidLevel($level) {
+               return t3lib_utility_Math::isIntegerInRange($level, self::EMERGENCY, self::DEBUG);
+       }
+
+       /**
+        * Validates a log level.
+        *
+        * @param integer $level log level to validate
+        * @return void
+        * @throws RangeException if the given log level is invalid
+        */
+       public static function validateLevel($level) {
+               if (!self::isValidLevel($level)) {
+                       throw new RangeException('Invalid Log Level "' . $level . '".', 1321637121);
+               }
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/class.t3lib_log_logger.php b/t3lib/log/class.t3lib_log_logger.php
new file mode 100644 (file)
index 0000000..3513185
--- /dev/null
@@ -0,0 +1,332 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2011-2012 Steffen Müller (typo3@t3node.com)
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Logger to log events and data for different components.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_Logger {
+
+       /**
+        * Logger name or component for which this logger is meant to be used for.
+        * This should be a dot-separated name and should normally be based on
+        * the class name or the name of a subsystem, such as
+        * core.t3lib.cache.manager, core.backend.workspaces or extension.news
+        *
+        * @var string
+        */
+       protected $name = '';
+
+       /**
+        * Minimum log level, anything below this level will be ignored.
+        *
+        * @var integer
+        */
+       protected $minimumLogLevel = t3lib_log_Level::EMERGENCY;
+
+       /**
+        * Writers used by this logger
+        *
+        * @var array
+        */
+       protected $writers = array();
+
+       /**
+        * Processors used by this logger
+        *
+        * @var array
+        */
+       protected $processors = array();
+
+       /**
+        * Constructor.
+        *
+        * @param string $name A name for the logger.
+        * @return t3lib_log_Logger
+        */
+       public function __construct($name) {
+               $this->name = $name;
+       }
+
+       /**
+        * Sets the minimum log level for which log records are written.
+        *
+        * @param integer $level Minimum log level
+        * @return t3lib_log_Logger $this
+        */
+       protected function setMinimumLogLevel($level) {
+               t3lib_log_Level::validateLevel($level);
+
+               $this->minimumLogLevel = $level;
+
+               return $this;
+       }
+
+       /**
+        * Gets the minimum log level for which log records are written.
+        *
+        * @return integer Minimum log level
+        */
+       protected function getMinimumLogLevel() {
+               return $this->minimumLogLevel;
+       }
+
+       /**
+        * Gets the logger's name.
+        *
+        * @return string Logger name.
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       /**
+        * Adds a writer to this logger
+        *
+        * @param integer $minimumLevel
+        * @param t3lib_log_writer_Writer $writer Writer object
+        * @return t3lib_log_Logger $this
+        */
+       public function addWriter($minimumLevel, t3lib_log_writer_Writer $writer) {
+               t3lib_log_Level::validateLevel($minimumLevel);
+
+                       // Cycle through all the log levels which are as severe as or higher
+                       // than $minimumLevel and add $writer to each severity level
+               for ($logLevelWhichTriggersWriter = t3lib_log_Level::EMERGENCY; $logLevelWhichTriggersWriter <= $minimumLevel; $logLevelWhichTriggersWriter++) {
+                       if (!isset($this->writers[$logLevelWhichTriggersWriter])) {
+                               $this->writers[$logLevelWhichTriggersWriter] = array();
+                       }
+                       $this->writers[$logLevelWhichTriggersWriter][] = $writer;
+               }
+
+               if ($minimumLevel > $this->getMinimumLogLevel()) {
+                       $this->setMinimumLogLevel($minimumLevel);
+               }
+
+               return $this;
+       }
+
+       /**
+        * Returns all configured writers indexed by log level
+        *
+        * @return array
+        */
+       public function getWriters() {
+               return $this->writers;
+       }
+
+       /**
+        * Adds a processor to the logger.
+        *
+        * @param integer $minimumLevel
+        * @param t3lib_log_processor_Processor $processor The processor to add.
+        * @return void
+        */
+       public function addProcessor($minimumLevel, t3lib_log_processor_Processor $processor) {
+               t3lib_log_Level::validateLevel($minimumLevel);
+
+                       // Cycle through all the log levels which are as severe as or higher
+                       // than $minimumLevel and add $processor to each severity level
+               for ($logLevelWhichTriggersProcessor = t3lib_log_Level::EMERGENCY; $logLevelWhichTriggersProcessor <= $minimumLevel; $logLevelWhichTriggersProcessor++) {
+                       if (!isset($this->processors[$logLevelWhichTriggersProcessor])) {
+                               $this->processors[$logLevelWhichTriggersProcessor] = array();
+                       }
+                       $this->processors[$logLevelWhichTriggersProcessor][] = $processor;
+               }
+
+               if ($minimumLevel > $this->getMinimumLogLevel()) {
+                       $this->setMinimumLogLevel($minimumLevel);
+               }
+       }
+
+       /**
+        * Returns all added processors indexed by log level
+        *
+        * @return array
+        */
+       public function getProcessors() {
+               return $this->processors;
+       }
+
+       /**
+        * Adds a log record.
+        *
+        * @param integer $level Log level.
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return mixed
+        */
+       public function log($level, $message, array $data = array()) {
+               t3lib_log_Level::validateLevel($level);
+               if ($level > $this->minimumLogLevel) {
+                       return $this;
+               }
+
+               /** @var $record t3lib_log_Record */
+               $record = t3lib_div::makeInstance('t3lib_log_Record',
+                       $this->name,
+                       $level,
+                       $message,
+                       $data
+               );
+
+               $record = $this->callProcessors($record);
+
+               $this->writeLog($record);
+
+               return $this;
+       }
+
+       /**
+        * Calls all processors and returns log record
+        *
+        * @param t3lib_log_Record $record Record to process
+        * @throws RuntimeException
+        * @return t3lib_log_Record Processed log record
+        */
+       protected function callProcessors(t3lib_log_Record $record) {
+               if (!empty($this->processors[$record->getLevel()])) {
+                       foreach ($this->processors[$record->getLevel()] as $processor) {
+                               $processedRecord = $processor->processLogRecord($record);
+                               if (!$processedRecord instanceof t3lib_log_Record) {
+                                       throw new RuntimeException('Processor ' . get_class($processor) . ' returned invalid data. Instance of t3lib_log_Record expected', 1343593398);
+                               }
+                               $record = $processedRecord;
+                       }
+               }
+               return $record;
+       }
+
+       /**
+        * Passes the t3lib_log_Record to all registered writers.
+        *
+        * @param t3lib_log_Record $record
+        * @return void
+        */
+       protected function writeLog(t3lib_log_Record $record) {
+               if (!empty($this->writers[$record->getLevel()])) {
+                       foreach ($this->writers[$record->getLevel()] as $writer) {
+                               $writer->writeLog($record);
+                       }
+               }
+       }
+
+       /**
+        * Shortcut to log an EMERGENCY record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function emergency($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::EMERGENCY, $message, $data);
+       }
+
+       /**
+        * Shortcut to log an ALERT record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function alert($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::ALERT, $message, $data);
+       }
+
+       /**
+        * Shortcut to log a CRITICAL record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function critical($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::CRITICAL, $message, $data);
+       }
+
+       /**
+        * Shortcut to log an ERROR record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function error($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::ERROR, $message, $data);
+       }
+
+       /**
+        * Shortcut to log a WARNING record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function warning($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::WARNING, $message, $data);
+       }
+
+       /**
+        * Shortcut to log a NOTICE record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function notice($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::NOTICE, $message, $data);
+       }
+
+       /**
+        * Shortcut to log an INFORMATION record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function info($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::INFO, $message, $data);
+       }
+
+       /**
+        * Shortcut to log a DEBUG record.
+        *
+        * @param string $message Log message.
+        * @param array $data Additional data to log
+        * @return t3lib_log_Logger $this
+        */
+       public function debug($message, array $data = array()) {
+               return $this->log(t3lib_log_Level::DEBUG, $message, $data);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/class.t3lib_log_logmanager.php b/t3lib/log/class.t3lib_log_logmanager.php
new file mode 100644 (file)
index 0000000..fe17de1
--- /dev/null
@@ -0,0 +1,237 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2011-2012 Steffen Müller (typo3@t3node.com)
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org))
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+
+/**
+ * Global LogManager that keeps track of global logging information.
+ *
+ * Inspired by java.util.logging
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_LogManager implements t3lib_Singleton {
+
+       /**
+        * @var string
+        */
+       const CONFIGURATION_TYPE_WRITER = 'writer';
+
+       /**
+        * @var string
+        */
+       const CONFIGURATION_TYPE_PROCESSOR = 'processor';
+
+       /**
+        * Loggers to retrieve them for repeated use.
+        *
+        * @var array
+        */
+       protected $loggers = array();
+
+       /**
+        * Default / global / root logger.
+        *
+        * @var t3lib_log_Logger
+        */
+       protected $rootLogger = NULL;
+
+
+       /**
+        * Constructor
+        */
+       public function __construct() {
+               $this->rootLogger  = t3lib_div::makeInstance('t3lib_log_Logger', '');
+               $this->loggers[''] = $this->rootLogger;
+       }
+
+       /**
+        * For use in unit test context only. Resets the internal logger registry.
+        *
+        * @return void
+        */
+       public function reset() {
+               $this->loggers = array();
+       }
+
+       /**
+        * Gets a logger instance for the given name.
+        *
+        * t3lib_div::makeInstance('t3lib_log_LogManager')->getLogger('main.sub.subsub');
+        *
+        * $name can also be submitted as a underscore-separated string, which will
+        * be converted to dots. This is useful to call this method with __CLASS__
+        * as parameter.
+        *
+        * @param string $name Logger name, empty to get the global "root" logger.
+        * @return t3lib_log_Logger Logger with name $name
+        */
+       public function getLogger($name = '') {
+
+               /** @var $logger t3lib_log_Logger */
+               $logger = NULL;
+
+                       // Transform class names to the dot-name style
+               $name = str_replace('_', '.', $name);
+
+               if (isset($this->loggers[$name])) {
+                       $logger = $this->loggers[$name];
+               } else {
+
+                               // Lazy instantiation
+                       /** @var $logger t3lib_log_Logger */
+                       $logger = t3lib_div::makeInstance('t3lib_log_Logger', $name);
+                       $this->loggers[$name] = $logger;
+
+                       $this->setWritersForLogger($logger);
+                       $this->setProcessorsForLogger($logger);
+               }
+
+               return $logger;
+       }
+
+       /**
+        * For use in unit test context only.
+        *
+        * @param string $name
+        * @return void
+        */
+       public function registerLogger($name) {
+               $this->loggers[$name] = NULL;
+       }
+
+       /**
+        * For use in unit test context only.
+        *
+        * @return array
+        */
+       public function getLoggerNames() {
+               return array_keys($this->loggers);
+       }
+
+       /**
+        * Appends the writers to the given logger as configured.
+        *
+        * @param t3lib_log_Logger $logger Logger to configure
+        * @return void
+        * @throws RangeException
+        */
+       protected function setWritersForLogger(t3lib_log_Logger $logger) {
+               $configuration = $this->getConfigurationForLogger(self::CONFIGURATION_TYPE_WRITER, $logger->getName());
+
+               foreach ($configuration as $severityLevel => $writer) {
+                       foreach ($writer as $logWriterClassName => $logWriterOptions) {
+
+                               /** @var $logWriter t3lib_log_writer_Writer */
+                               $logWriter = NULL;
+                               try {
+                                       $logWriter = t3lib_div::makeInstance($logWriterClassName, $logWriterOptions);
+                                       $logger->addWriter($severityLevel, $logWriter);
+                               } catch (RangeException $e) {
+                                       $logger->warning('Instantiation of LogWriter "' . $logWriterClassName . '" failed for logger ' . $logger->getName() . ' (' . $e->getMessage() . ')');
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Appends the processors to the given logger as configured.
+        *
+        * @param t3lib_log_Logger $logger Logger to configure
+        * @return void
+        * @throws RangeException
+        */
+       protected function setProcessorsForLogger(t3lib_log_Logger $logger) {
+               $configuration = $this->getConfigurationForLogger(self::CONFIGURATION_TYPE_PROCESSOR, $logger->getName());
+
+               foreach ($configuration as $severityLevel => $processor) {
+                       foreach ($processor as $logProcessorClassName => $logProcessorOptions) {
+
+                               /** @var $logProcessor t3lib_log_processor_Processor */
+                               $logProcessor = NULL;
+                               try {
+                                       $logProcessor = t3lib_div::makeInstance($logProcessorClassName, $logProcessorOptions);
+                                       $logger->addProcessor($severityLevel, $logProcessor);
+                               } catch (RangeException $e) {
+                                       $logger->warning('Instantiation of LogProcessor "' . $logProcessorClassName . '" failed for logger ' . $logger->getName() . ' (' . $e->getMessage() . ')');
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Returns the configuration from $TYPO3_CONF_VARS['LOG'] as
+        * hierarchical array for different components of the class hierarchy.
+        *
+        * @param string $configurationType Type of config to return (writer, processor)
+        * @param string $loggerName Logger name
+        * @throws RangeException
+        * @return array
+        */
+       protected function getConfigurationForLogger($configurationType, $loggerName) {
+
+                       // Split up the logger name (dot-separated) into its parts
+               $explodedName = explode('.', $loggerName);
+
+                       // Search in the $TYPO3_CONF_VARS['LOG'] array
+                       // for these keys, for example "writerConfiguration"
+               $configurationKey = $configurationType . 'Configuration';
+
+               $configuration = $GLOBALS['TYPO3_CONF_VARS']['LOG'];
+
+               $result = (!empty($configuration[$configurationKey]) ? $configuration[$configurationKey] : array());
+
+                       // Walk from general to special (t3lib, t3lib.db, t3lib.db.foo)
+                       // and search for the most specific configuration
+               foreach ($explodedName as $partOfClassName) {
+                       if (!empty($configuration[$partOfClassName][$configurationKey])) {
+                               $result = $configuration[$partOfClassName][$configurationKey];
+                       }
+                       $configuration = $configuration[$partOfClassName];
+               }
+
+                       // Validate the config
+               foreach ($result as $level => $unused) {
+                       try {
+                               t3lib_log_Level::validateLevel($level);
+                       } catch (RangeException $e) {
+                               throw new RangeException(
+                                       'The given severity level "' . htmlspecialchars($level) . '" for ' . $configurationKey . ' of logger "' .
+                                               $loggerName . '" is not valid.',
+                                       1326406447
+                               );
+                       }
+               }
+
+               return $result;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/class.t3lib_log_record.php b/t3lib/log/class.t3lib_log_record.php
new file mode 100644 (file)
index 0000000..d06df87
--- /dev/null
@@ -0,0 +1,354 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Log record
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller (typo3@t3node.com)
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_Record implements ArrayAccess {
+
+       /**
+        * Unique ID of the request
+        *
+        * @var string
+        */
+       protected $requestId = '';
+
+       /**
+        * Creation timestamp with microseconds
+        *
+        * @var float
+        */
+       protected $created = 0.0;
+
+       /**
+        * The component where the record was created
+        *
+        * @var string
+        */
+       protected $component = '';
+
+       /**
+        * Severity level
+        *
+        * @var integer
+        */
+       protected $level = t3lib_log_Level::INFO;
+
+       /**
+        * Log message one-liner
+        *
+        * @var string
+        */
+       protected $message = '';
+
+       /**
+        * Additional log data
+        *
+        * @var array
+        */
+       protected $data = array();
+
+       /**
+        * Gettable properties for ArrayAccess
+        *
+        * @var array
+        */
+       private $gettableProperties = array(
+               'requestId',
+               'created',
+               'component',
+               'level',
+               'message',
+               'data'
+       );
+
+       /**
+        * Settable properties for ArrayAccess
+        *
+        * @var array
+        */
+       private $settableProperties = array(
+               'level',
+               'message',
+               'data'
+       );
+
+       /**
+        * Constructor.
+        *
+        * @param string $component Affected component
+        * @param integer $level Severity level (see t3lib_log_Level)
+        * @param string $message Log message
+        * @param array $data Additional data
+        */
+       public function __construct($component = '', $level, $message, array $data = array()) {
+
+               $this->setRequestId(Typo3_Bootstrap::getInstance()->getRequestId())
+                       ->setCreated(microtime(TRUE))
+                       ->setComponent($component)
+                       ->setLevel($level)
+                       ->setMessage($message)
+                       ->setData($data);
+       }
+
+       /**
+        * Sets the affected component
+        *
+        * @param string $component Component key
+        * @return t3lib_log_Record
+        */
+       public function setComponent($component) {
+               $this->component = $component;
+               return $this;
+       }
+
+       /**
+        * Returns the component
+        *
+        * @return string Component key
+        */
+       public function getComponent() {
+               return $this->component;
+       }
+
+       /**
+        * Sets the the creation time
+        *
+        * @param float $created Creation time as float
+        * @return t3lib_log_Record
+        */
+       public function setCreated($created) {
+               $this->created = $created;
+               return $this;
+       }
+
+       /**
+        * Returns the creation time
+        *
+        * @return float Creation time as float
+        */
+       public function getCreated() {
+               return $this->created;
+       }
+
+       /**
+        * Sets the severity level
+        *
+        * @param integer $level Severity level
+        * @return t3lib_log_Record
+        * @throws RangeException if the given log level is invalid
+        * @see t3lib_log_Level
+        */
+       public function setLevel($level) {
+               t3lib_log_Level::validateLevel($level);
+               $this->level = $level;
+               return $this;
+       }
+
+       /**
+        * Returns the severity level
+        *
+        * @see t3lib_log_Level
+        * @return int Severity level
+        */
+       public function getLevel() {
+               return $this->level;
+       }
+
+       /**
+        * Sets log data array
+        *
+        * @param array $data
+        * @return t3lib_log_Record
+        */
+       public function setData($data) {
+               $this->data = $data;
+               return $this;
+       }
+
+       /**
+        * Returns the log data
+        *
+        * @return array
+        */
+       public function getData() {
+               return $this->data;
+       }
+
+       /**
+        * Adds additional log data to already existing data
+        * and overwrites previously data using the same array keys.
+        *
+        * @param array $data
+        * @return t3lib_log_Record
+        */
+       public function addData(array $data) {
+               $this->data = array_merge($this->data, $data);
+               return $this;
+       }
+
+       /**
+        * Sets the log message
+        *
+        * @param string $message Log message
+        * @return t3lib_log_Record
+        */
+       public function setMessage($message) {
+               $this->message = $message;
+               return $this;
+       }
+
+       /**
+        * Returns the log message
+        *
+        * @return string Log message
+        */
+       public function getMessage() {
+               return $this->message;
+       }
+
+       /**
+        * Sets the request ID
+        *
+        * @param string $requestId
+        * @return t3lib_log_Record
+        */
+       public function setRequestId($requestId) {
+               $this->requestId = $requestId;
+               return $this;
+       }
+
+       /**
+        * Returns the request ID
+        *
+        * @return string
+        */
+       public function getRequestId() {
+               return $this->requestId;
+       }
+
+       /**
+        * Convert record to string for simple output, like echo().
+        * Contents of data array is appended as JSON-encoded string
+        *
+        * @return string
+        */
+       public function __toString() {
+               $timestamp = date('r', (int) $this->created);
+               $levelName = t3lib_log_Level::getName($this->level);
+               $data = (!empty($this->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;
+       }
+
+       /**
+        * Convert record to array
+        *
+        * @return array
+        */
+       public function toArray() {
+               return array(
+                       'requestId' => $this->requestId,
+                       'created' => $this->created,
+                       'component' => $this->component,
+                       'level' => $this->level,
+                       'message' => $this->message,
+                       'data' => $this->data
+               );
+       }
+
+       /**
+        * Checks whether an offset exists, required by ArrayAccess interface
+        *
+        * @param mixed $offset
+        * @return boolean
+        */
+       public function offsetExists($offset) {
+               $offsetExists = FALSE;
+
+               if (in_array($offset, $this->gettableProperties, TRUE) && isset($this->$offset)) {
+                       $offsetExists = TRUE;
+               }
+
+               return $offsetExists;
+       }
+
+       /**
+        * Offset to retrieve, required by ArrayAccess interface
+        *
+        * @param mixed $offset
+        * @return mixed
+        */
+       public function offsetGet($offset) {
+               if (!in_array($offset, $this->gettableProperties, TRUE)) {
+                       return NULL;
+               }
+
+               return $this->$offset;
+       }
+
+       /**
+        * Offset to set, required by ArrayAccess interface
+        *
+        * @param mixed $offset
+        * @param mixed $value
+        * @return void
+        */
+       public function offsetSet($offset, $value) {
+               if (in_array($offset, $this->settableProperties, TRUE)) {
+                       $this->$offset = $offset;
+               }
+       }
+
+       /**
+        * Offset to unset, required by ArrayAccess interface
+        *
+        * @param mixed $offset
+        * @return void
+        */
+       public function offsetUnset($offset) {
+               if (in_array($offset, $this->settableProperties, TRUE)) {
+                       unset($this->$offset);
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/class.t3lib_log_processor_abstract.php b/t3lib/log/processor/class.t3lib_log_processor_abstract.php
new file mode 100644 (file)
index 0000000..b795e7c
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Abstract implementation of a log processor
+ *
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+abstract class t3lib_log_processor_Abstract implements t3lib_log_processor_Processor {
+
+       /**
+        * Constructs this log processor
+        *
+        * @param array $options Configuration options - depends on the actual processor
+        * @throws InvalidArgumentException
+        */
+       public function __construct(array $options = array()) {
+               foreach ($options as $optionKey => $optionValue) {
+                       $methodName = 'set' . ucfirst($optionKey);
+
+                       if (method_exists($this, $methodName)) {
+                               $this->$methodName($optionValue);
+                       } else {
+                               throw new InvalidArgumentException(
+                                       'Invalid log processor option "' . $optionKey . '" for log processor of type "' . get_class($this) . '"',
+                                       1321696151
+                               );
+                       }
+               }
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/class.t3lib_log_processor_abstractmemory.php b/t3lib/log/processor/class.t3lib_log_processor_abstractmemory.php
new file mode 100644 (file)
index 0000000..53d5660
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Common memory processor methods.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+abstract class t3lib_log_processor_AbstractMemory extends t3lib_log_processor_Abstract {
+
+       /**
+        * Allocated memory usage type to use
+        * If set, the real size of memory allocated from system is used.
+        * Otherwise the memory used by emalloc() is used.
+        *
+        * @var boolean
+        * @see memory_get_usage()
+        * @see memory_get_peak_usage()
+        */
+       protected $realMemoryUsage = TRUE;
+
+       /**
+        * Whether the size is formatted, e.g. in megabytes
+        *
+        * @var boolean
+        * @see t3lib_div::formatSize()
+        */
+       protected $formatSize = TRUE;
+
+       /**
+        * Sets the allocated memory usage type
+        *
+        * @param boolean $realMemoryUsage Which allocated memory type to use
+        * @return void
+        */
+       public function setRealMemoryUsage($realMemoryUsage) {
+               $this->realMemoryUsage = (boolean) $realMemoryUsage;
+       }
+
+       /**
+        * Returns the allocated memory usage type
+        *
+        * @return boolean
+        */
+       public function getRealMemoryUsage() {
+               return $this->realMemoryUsage;
+       }
+
+       /**
+        * Sets whether size should be formatted
+        *
+        * @param boolean $formatSize
+        * @return void
+        */
+       public function setFormatSize($formatSize) {
+               $this->formatSize = (boolean) $formatSize;
+       }
+
+       /**
+        * Returns whether size should be formatted
+        *
+        * @return boolean
+        */
+       public function getFormatSize() {
+               return $this->formatSize;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/class.t3lib_log_processor_introspection.php b/t3lib/log/processor/class.t3lib_log_processor_introspection.php
new file mode 100644 (file)
index 0000000..005023d
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Introspection processor to automatically add where the log record came from.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_Introspection extends t3lib_log_processor_Abstract {
+
+       /**
+        * Add debug backtrace information to logRecord
+        * It adds: filepath, line number, class and function name
+        *
+        * @param t3lib_log_Record $logRecord The log record to process
+        * @return t3lib_log_Record The processed log record with additional data
+        * @see debug_backtrace()
+        */
+       public function processLogRecord(t3lib_log_Record $logRecord) {
+               $trace = debug_backtrace();
+
+                       // skip first since it's always the current method
+               array_shift($trace);
+
+                       // the call_user_func call is also skipped
+               array_shift($trace);
+
+                       // skip t3lib_log classes
+               $i = 0;
+               while (isset($trace[$i]['class']) && FALSE !== strpos($trace[$i]['class'], 't3lib_log_')) {
+                       $i++;
+               }
+
+                       // we should have the call source now
+               $logRecord->addData(array(
+                       'file'     => isset($trace[$i]['file'])     ? $trace[$i]['file']     : NULL,
+                       'line'     => isset($trace[$i]['line'])     ? $trace[$i]['line']     : NULL,
+                       'class'    => isset($trace[$i]['class'])    ? $trace[$i]['class']    : NULL,
+                       'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : NULL,
+               ));
+
+               return $logRecord;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/class.t3lib_log_processor_memorypeakusage.php b/t3lib/log/processor/class.t3lib_log_processor_memorypeakusage.php
new file mode 100644 (file)
index 0000000..de407d0
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Memory peak usage processor methods.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_MemoryPeakUsage extends t3lib_log_processor_AbstractMemory {
+
+       /**
+        * Processes a log record and adds memory peak usage information.
+        *
+        * @param t3lib_log_Record $logRecord The log record to process
+        * @return t3lib_log_Record The processed log record with additional data
+        * @see memory_get_peak_usage()
+        */
+       public function processLogRecord(t3lib_log_Record $logRecord) {
+               $bytes = memory_get_peak_usage($this->getRealMemoryUsage());
+
+               if ($this->formatSize) {
+                       $size = t3lib_div::formatSize($bytes);
+               } else {
+                       $size = $bytes;
+               }
+
+               $logRecord->addData(array(
+                       'memoryPeakUsage' => $size
+               ));
+
+               return $logRecord;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/class.t3lib_log_processor_memoryusage.php b/t3lib/log/processor/class.t3lib_log_processor_memoryusage.php
new file mode 100644 (file)
index 0000000..88e55c4
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Memory usage processor methods.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_MemoryUsage extends t3lib_log_processor_AbstractMemory {
+
+       /**
+        * Processes a log record and adds memory usage information.
+        *
+        * @param t3lib_log_Record $logRecord The log record to process
+        * @return t3lib_log_Record The processed log record with additional data
+        * @see memory_get_usage()
+        */
+       public function processLogRecord(t3lib_log_Record $logRecord) {
+               $bytes = memory_get_usage($this->getRealMemoryUsage());
+
+               if ($this->formatSize) {
+                       $size = t3lib_div::formatSize($bytes);
+               } else {
+                       $size = $bytes;
+               }
+
+               $logRecord->addData(array(
+                       'memoryUsage' => $size
+               ));
+
+               return $logRecord;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/class.t3lib_log_processor_null.php b/t3lib/log/processor/class.t3lib_log_processor_null.php
new file mode 100644 (file)
index 0000000..af7dca9
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * A log processor that does nothing. Used in unit tests.
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_Null extends t3lib_log_processor_Abstract {
+
+       /**
+        * Processes a log record and returns the same.
+        *
+        * @param t3lib_log_Record $logRecord The log record to process
+        * @return t3lib_log_Record The processed log record with additional data
+        */
+       public function processLogRecord(t3lib_log_Record $logRecord) {
+               return $logRecord;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/class.t3lib_log_processor_web.php b/t3lib/log/processor/class.t3lib_log_processor_web.php
new file mode 100644 (file)
index 0000000..ab0e365
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Web log processor to automatically add web request related data to a log
+ * record.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_Web extends t3lib_log_processor_Abstract {
+
+       /**
+        * Processes a log record and adds webserver environment data.
+        * We use the usual "Debug System Information"
+        *
+        * @param t3lib_log_Record $logRecord The log record to process
+        * @return t3lib_log_Record The processed log record with additional data
+        * @see t3lib_div::getIndpEnv()
+        */
+       public function processLogRecord(t3lib_log_Record $logRecord) {
+               $logRecord->addData(t3lib_div::getIndpEnv('_ARRAY'));
+
+               return $logRecord;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/processor/interfaces/interface.t3lib_log_processor_processor.php b/t3lib/log/processor/interfaces/interface.t3lib_log_processor_processor.php
new file mode 100644 (file)
index 0000000..d35aaa8
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Log processor interface
+ *
+ * Processors provide additional data in an automatic way, without having to
+ * collect that data yourself.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+interface t3lib_log_processor_Processor {
+
+       /**
+        * Processes a log record and adds additional data.
+        *
+        * @param t3lib_log_Record $logRecord The log record to process
+        * @return t3lib_log_Record The processed log record with additional data
+        */
+       public function processLogRecord(t3lib_log_Record $logRecord);
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/writer/class.t3lib_log_writer_abstract.php b/t3lib/log/writer/class.t3lib_log_writer_abstract.php
new file mode 100644 (file)
index 0000000..25fd1e8
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+
+/**
+ * Abstract implementation of a log writer
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+abstract class t3lib_log_writer_Abstract implements t3lib_log_writer_Writer {
+
+       /**
+        * Constructs this log writer
+        *
+        * @param array $options Configuration options - depends on the actual log writer
+        * @throws InvalidArgumentException
+        */
+       public function __construct(array $options = array()) {
+               foreach ($options as $optionKey => $optionValue) {
+                       $methodName = 'set' . ucfirst($optionKey);
+
+                       if (method_exists($this, $methodName)) {
+                               $this->$methodName($optionValue);
+                       } else {
+                               throw new InvalidArgumentException(
+                                       'Invalid log writer option "' . $optionKey . '" for log writer of type "' . get_class($this) . '"',
+                                       1321696151
+                               );
+                       }
+               }
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/writer/class.t3lib_log_writer_database.php b/t3lib/log/writer/class.t3lib_log_writer_database.php
new file mode 100644 (file)
index 0000000..acbe328
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Log writer that writes the log records into a database table.
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_writer_Database extends t3lib_log_writer_Abstract {
+
+       /**
+        * Table to write the log records to.
+        *
+        * @var string
+        */
+       protected $logTable = 'sys_log';
+
+       /**
+        * Set name of database log table
+        *
+        * @param string $tableName Database table name
+        * @return t3lib_log_writer_Abstract
+        */
+       public function setLogTable($tableName) {
+               $this->logTable = $tableName;
+
+               return $this;
+       }
+
+       /**
+        * Get name of database log table
+        *
+        * @return string Database table name
+        */
+       public function getLogTable() {
+               return $this->logTable;
+       }
+
+       /**
+        * Writes the log record
+        *
+        * @param t3lib_log_Record $record Log record
+        * @return t3lib_log_writer_Writer $this
+        * @throws RuntimeException
+        */
+       public function writeLog(t3lib_log_Record $record) {
+               $data = array(
+                       'request_id' => $record['requestId'],
+                       'time_micro' => $record['created'],
+                       'component'  => $record['component'],
+                       'level'      => $record['level'],
+                       'message'    => $record['message'],
+                       'data'       => (!empty($record['data'])) ? json_encode($record['data']) : '',
+               );
+
+               if (FALSE === $GLOBALS['TYPO3_DB']->exec_INSERTquery($this->logTable, $data)) {
+                       throw new RuntimeException('Could not write log record to database', 1345036334);
+               }
+
+               return $this;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/writer/class.t3lib_log_writer_file.php b/t3lib/log/writer/class.t3lib_log_writer_file.php
new file mode 100644 (file)
index 0000000..a3e02a3
--- /dev/null
@@ -0,0 +1,204 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * (c) 2011-2012 Steffen Müller (typo3@t3node.com)
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Log writer that writes the log records into a file.
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_writer_File extends t3lib_log_writer_Abstract {
+
+       /**
+        * Log file path, relative to PATH_site
+        *
+        * @var string
+        */
+       protected  $logFile = '';
+
+       /**
+        * Default log file path
+        *
+        * @var string
+        */
+       protected $defaultLogFile = 'typo3temp/logs/typo3.log';
+
+       /**
+        * Log file handle
+        *
+        * @static
+        * @var resource
+        */
+       static $logFileHandle = NULL;
+
+       /**
+        * Constructor, opens the log file handle
+        *
+        * @param array $options
+        * @return t3lib_log_writer_File
+        */
+       public function __construct(array $options = array()) {
+
+                       // the parent constructor reads $options and sets them
+               parent::__construct($options);
+
+               if (empty($options['logFile'])) {
+                       $this->setLogFile($this->defaultLogFile);
+               }
+       }
+
+       /**
+        * Destructor, closes the log file handle
+        *
+        */
+       public function __destruct() {
+               $this->closeLogFile();
+       }
+
+       /**
+        * Sets the path to the log file.
+        *
+        * @param string $logFile path to the log file, relative to PATH_site
+        * @return t3lib_log_writer_Writer
+        * @throws InvalidArgumentException
+        */
+       public function setLogFile($logFile) {
+               if (is_resource(self::$logFileHandle)) {
+                       $this->closeLogFile();
+               }
+
+                       // Skip handling if logFile is a stream resource
+                       // This is used by unit tests with vfs:// directories
+               if (FALSE === strpos($logFile, '://')) {
+                       if (!t3lib_div::isAllowedAbsPath(PATH_site . $logFile)) {
+                               throw new InvalidArgumentException(
+                                       'Log file path "' . $logFile . '" is not valid!',
+                                       1326411176
+                               );
+                       }
+                       $logFile = t3lib_div::getFileAbsFileName($logFile);
+               }
+
+               $this->logFile = $logFile;
+               $this->openLogFile();
+
+               return $this;
+       }
+
+       /**
+        * Gets the path to the log file.
+        *
+        * @return string Path to the log file.
+        */
+       public function getLogFile() {
+               return $this->logFile;
+       }
+
+       /**
+        * Writes the log record
+        *
+        * @param t3lib_log_Record $record Log record
+        * @return t3lib_log_writer_Writer $this
+        * @throws RuntimeException
+        */
+       public function writeLog(t3lib_log_Record $record) {
+               if (FALSE === fwrite(self::$logFileHandle, $record . LF)) {
+                       throw new RuntimeException('Could not write log record to log file', 1345036335);
+               }
+
+               return $this;
+       }
+
+       /**
+        * Opens the log file handle
+        *
+        * @return void
+        * @throws RuntimeException if the log file can't be opened.
+        */
+       protected function openLogFile() {
+               $this->createLogFile();
+
+               self::$logFileHandle = fopen($this->logFile, 'a');
+
+               if (!is_resource(self::$logFileHandle)) {
+                       throw new RuntimeException('Could not open log file "' . $this->logFile . '"', 1321804422);
+               }
+       }
+
+       /**
+        * Closes the log file handle.
+        *
+        * @return void
+        */
+       protected function closeLogFile() {
+               if (is_resource(self::$logFileHandle)) {
+                       fclose(self::$logFileHandle);
+               }
+       }
+
+       /**
+        * Creates the log file with correct permissions
+        * and parent directories, if needed
+        *
+        * @return void
+        */
+       protected function createLogFile() {
+               if (file_exists($this->logFile)) {
+                       return;
+               }
+
+               $logFileDirectory = dirname($this->logFile);
+               if (!@is_dir($logFileDirectory)) {
+                       t3lib_div::mkdir_deep($logFileDirectory);
+
+                               // only create .htaccess, if we created the directory on our own
+                       $this->createHtaccessFile($logFileDirectory . '/.htaccess');
+               }
+
+                       // create the log file
+               t3lib_div::writeFile($this->logFile, '');
+       }
+
+       /**
+        * Creates .htaccess file inside a new directory to access protect it
+        *
+        * @param string $htaccessFile Path of .htaccess file
+        * @return void
+        */
+       protected function createHtaccessFile($htaccessFile) {
+                       // write .htaccess file to protect the log file
+               if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['generateApacheHtaccess']) && !file_exists($htaccessFile)) {
+                       t3lib_div::writeFile($htaccessFile, 'Deny From All');
+               }
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/writer/class.t3lib_log_writer_null.php b/t3lib/log/writer/class.t3lib_log_writer_null.php
new file mode 100644 (file)
index 0000000..b5e0c15
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Null writer - just forgets about everything
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_writer_Null extends t3lib_log_writer_Abstract {
+
+       /**
+        * Writes the log record
+        *
+        * @param t3lib_log_Record $record Log record
+        * @return t3lib_log_writer_Writer $this
+        */
+       public function writeLog(t3lib_log_Record $record) {
+                       // do nothing
+               return $this;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/writer/class.t3lib_log_writer_phperrorlog.php b/t3lib/log/writer/class.t3lib_log_writer_phperrorlog.php
new file mode 100644 (file)
index 0000000..254ea5f
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Log writer that writes the log records into PHP error log.
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_writer_PhpErrorLog extends t3lib_log_writer_Abstract {
+
+       /**
+        * Writes the log record
+        *
+        * @param t3lib_log_Record $record Log record
+        * @return t3lib_log_writer_Writer $this
+        * @throws RuntimeException
+        */
+       public function writeLog(t3lib_log_Record $record) {
+               $levelName = t3lib_log_Level::getName($record->getLevel());
+
+               $data = $record->getData();
+               $data = (!empty($data)) ? '- ' . json_encode($data) : '';
+
+               $message = sprintf(
+                       'TYPO3 [%s] request="%s" component="%s": %s %s',
+                       $levelName,
+                       $record->getRequestId(),
+                       $record->getComponent(),
+                       $record->getMessage(),
+                       $data
+               );
+
+               if (FALSE === error_log($message)) {
+                       throw new RuntimeException('Could not write log record to PHP error log', 1345036336);
+               }
+
+               return $this;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/writer/class.t3lib_log_writer_syslog.php b/t3lib/log/writer/class.t3lib_log_writer_syslog.php
new file mode 100644 (file)
index 0000000..25b34ec
--- /dev/null
@@ -0,0 +1,154 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2011-2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Log writer that writes to syslog
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_writer_Syslog extends t3lib_log_writer_Abstract {
+
+       /**
+        * List of valid syslog facility names.
+        * private as it's not supposed to be changed.
+        *
+        * @var array Facilities
+        */
+       private $facilities = array(
+               'auth'     => LOG_AUTH,
+               'authpriv' => LOG_AUTHPRIV,
+               'cron'     => LOG_CRON,
+               'daemon'   => LOG_DAEMON,
+               'kern'     => LOG_KERN,
+               'lpr'      => LOG_LPR,
+               'mail'     => LOG_MAIL,
+               'news'     => LOG_NEWS,
+               'syslog'   => LOG_SYSLOG,
+               'user'     => LOG_USER,
+               'uucp'     => LOG_UUCP,
+       );
+
+       /**
+        * Type of program that is logging to syslog.
+        *
+        * @var integer
+        */
+       protected $facility = LOG_USER;
+
+       /**
+        * Constructor, adds facilities on *nix environments.
+        *
+        * @param array $options Configuration options
+        * @throws RuntimeException if connection to syslog cannot be opened
+        * @see t3lib_log_writer_Abstract
+        */
+       public function __construct(array $options = array()) {
+                       // additional facilities for *nix environments
+               if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
+                       $this->facilities['local0'] = LOG_LOCAL0;
+                       $this->facilities['local1'] = LOG_LOCAL1;
+                       $this->facilities['local2'] = LOG_LOCAL2;
+                       $this->facilities['local3'] = LOG_LOCAL3;
+                       $this->facilities['local4'] = LOG_LOCAL4;
+                       $this->facilities['local5'] = LOG_LOCAL5;
+                       $this->facilities['local6'] = LOG_LOCAL6;
+                       $this->facilities['local7'] = LOG_LOCAL7;
+               }
+
+               parent::__construct($options);
+
+               if (!openlog('TYPO3', LOG_ODELAY | LOG_PID, $this->facility)) {
+                       $facilityName = array_search($this->facility, $this->facilities);
+
+                       throw new RuntimeException(
+                               'Could not open syslog for facility ' . $facilityName,
+                               1321722682
+                       );
+               }
+       }
+
+       /**
+        * Destructor, closes connection to syslog.
+        *
+        */
+       public function __destruct() {
+               closelog();
+       }
+
+       /**
+        * Sets the facility to use when logging to syslog.
+        *
+        * @param integer $facility Facility to use when logging.
+        * @return void
+        */
+       public function setFacility($facility) {
+               if (array_key_exists(strtolower($facility), $this->facilities)) {
+                       $this->facility = $this->facilities[strtolower($facility)];
+               }
+       }
+
+       /**
+        * Returns the data of the record in syslog format
+        *
+        * @param t3lib_log_Record $record
+        * @return string
+        */
+       public function getMessageForSyslog(t3lib_log_Record $record) {
+               $data = $record->getData();
+               $data = (!empty($data)) ? '- ' . json_encode($data) : '';
+
+               $message = sprintf(
+                       '[request="%s" component="%s"] %s %s',
+                       $record->getRequestId(),
+                       $record->getComponent(),
+                       $record->getMessage(),
+                       $data
+               );
+
+               return $message;
+       }
+
+       /**
+        * Writes the log record to syslog
+        *
+        * @param t3lib_log_Record $record Log record
+        * @return t3lib_log_writer_Writer
+        * @throws RuntimeException
+        */
+       public function writeLog(t3lib_log_Record $record) {
+               if (FALSE === syslog($record->getLevel(), $this->getMessageForSyslog($record))) {
+                       throw new RuntimeException('Could not write log record to syslog', 1345036337);
+               }
+
+               return $this;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/log/writer/interfaces/interface.t3lib_log_writer_writer.php b/t3lib/log/writer/interfaces/interface.t3lib_log_writer_writer.php
new file mode 100644 (file)
index 0000000..8488362
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Log writer interface
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+interface t3lib_log_writer_Writer {
+
+       /**
+        * Writes the log record
+        *
+        * @param t3lib_log_Record $record Log record
+        * @return t3lib_log_writer_Writer $this
+        * @throws Exception
+        */
+       public function writeLog(t3lib_log_Record $record);
+
+}
+
+
+?>
\ No newline at end of file
index 707d7a3..dc75471 100644 (file)
@@ -670,6 +670,23 @@ return array(
                'ssl_passphrase' => '',                         // String: Passphrase with which local certificate was encoded.
                'userAgent' => 'TYPO3/' . TYPO3_version,        // String: Default user agent. If empty, this will be "TYPO3/4.x", while x is the current branch version. This overrides the constant <em>TYPO3_user_agent</em>.
        ),
+       'LOG' => array(
+               'writerConfiguration' => array(
+                       t3lib_log_Level::DEBUG => array(
+                               't3lib_log_writer_File' => array(
+                               ),
+                       )
+               ),
+               'deprecated' => array(
+                       'writerConfiguration' => array(
+                               t3lib_log_Level::WARNING => array(
+                                       't3lib_log_writer_File' => array(
+                                               'logFile' => 'typo3conf/deprecation.log'
+                                       )
+                               )
+                       )
+               ),
+       ),
        'MODS' => array(                // Backend Module Configuration (obsolete, make extension instead)
        ),
        'USER' => array(                // Here you may define your own setup-vars for use in your include-scripts. (obsolete, make extension instead)
index bab3909..7b0164b 100644 (file)
@@ -574,11 +574,18 @@ CREATE TABLE sys_log (
   event_pid int(11) DEFAULT '-1' NOT NULL,
   workspace int(11) DEFAULT '0' NOT NULL,
   NEWid varchar(20) DEFAULT '' NOT NULL,
+  request_id varchar(13) DEFAULT '' NOT NULL,
+  time_micro float DEFAULT '0' NOT NULL,
+  component varchar(255) DEFAULT '' NOT NULL,
+  level tinyint(1) unsigned DEFAULT '0' NOT NULL,
+  message text,
+  data text,
   PRIMARY KEY (uid),
   KEY parent (pid),
   KEY event (userid,event_pid),
   KEY recuidIdx (recuid,uid),
-  KEY user_auth (type,action,tstamp)
+  KEY user_auth (type,action,tstamp),
+  KEY request (request_id)
 ) ENGINE=InnoDB;
 
 #
diff --git a/tests/Unit/t3lib/log/class.t3lib_log_levelTest.php b/tests/Unit/t3lib/log/class.t3lib_log_levelTest.php
new file mode 100644 (file)
index 0000000..a58156e
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for t3lib_log_Level.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_LevelTest extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        */
+       public function isValidLevelValidatesValidLevels() {
+               $validLevels = array(0, 1, 2, 3, 4, 5, 6, 7);
+
+               foreach ($validLevels as $validLevel) {
+                       $this->assertTrue(t3lib_log_Level::isValidLevel($validLevel));
+               }
+       }
+
+       /**
+        * @test
+        */
+       public function isValidLevelDoesNotValidateInvalidLevels() {
+               $invalidLevels = array(-1, 8, 1.5, 'string', array(), new stdClass(), FALSE, NULL);
+
+               foreach ($invalidLevels as $invalidLevel) {
+                       $this->assertFalse(t3lib_log_Level::isValidLevel($invalidLevel));
+               }
+       }
+
+       /**
+        * Data provider or isValidLevelThrowsExceptionOnInvalidLevelIfAskedToDoSo
+        */
+       public function isValidLevelThrowsExceptionOnInvalidLevelIfAskedToDoSoDataProvider() {
+               return array(
+                       'negative integer'           => array(-1),
+                       'higher level than expected' => array(8),
+                       'float'                      => array(1.5),
+                       'string'                     => array('string'),
+                       'array'                      => array(array()),
+                       'object'                     => array(new stdClass()),
+                       'boolean FALSE'              => array(FALSE),
+                       'NULL'                       => array(NULL),
+               );
+       }
+
+       /**
+        * @test
+        * @dataprovider isValidLevelThrowsExceptionOnInvalidLevelIfAskedToDoSoDataProvider
+        */
+       public function isValidLevelThrowsExceptionOnInvalidLevelIfAskedToDoSo($inputValue) {
+               $this->setExpectedException('RangeException');
+
+               t3lib_log_Level::validateLevel($inputValue);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/class.t3lib_log_loggerTest.php b/tests/Unit/t3lib/log/class.t3lib_log_loggerTest.php
new file mode 100644 (file)
index 0000000..3a5f68f
--- /dev/null
@@ -0,0 +1,216 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+require_once('writer/class.t3lib_log_writer_test.php');
+require_once('writer/class.t3lib_log_writer_failing.php');
+
+/**
+ * Testcase for t3lib_log_Logger.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_LoggerTest extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        */
+       public function getNameGetsLoggerName() {
+               $logger = new t3lib_log_Logger('test.core.log');
+               $this->assertSame('test.core.log', $logger->getName());
+       }
+
+       /**
+        * @test
+        */
+       public function loggerDoesNotLogRecordsLessCriticalThanLogLevel() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = new t3lib_log_writer_Test();
+               $logger->addWriter(t3lib_log_Level::ERROR, $writer);
+
+                       // warning < error, thus must not be logged
+               $logger->log(t3lib_log_Level::WARNING, 'test message');
+
+               $this->assertAttributeEmpty('records', $writer);
+       }
+
+       /**
+        * @test
+        */
+       public function loggerReturnsItselfAfterLogging() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = new t3lib_log_writer_Test();
+               $logger->addWriter(t3lib_log_Level::DEBUG, $writer);
+
+               $returnValue = $logger->log(t3lib_log_Level::WARNING, 'test message');
+
+               $this->assertInstanceOf('t3lib_log_Logger', $returnValue);
+       }
+
+       /**
+        * @test
+        */
+       public function loggerReturnsItselfAfterLoggingWithoutWriter() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $returnValue = $logger->log(t3lib_log_Level::WARNING, 'test message');
+
+               $this->assertInstanceOf('t3lib_log_Logger', $returnValue);
+       }
+
+       /**
+        * @test
+        */
+       public function loggerReturnsItselfAfterLoggingLessCritical() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = new t3lib_log_writer_Test();
+               $logger->addWriter(t3lib_log_Level::EMERGENCY, $writer);
+
+               $returnValue = $logger->log(t3lib_log_Level::WARNING, 'test message');
+
+               $this->assertInstanceOf('t3lib_log_Logger', $returnValue);
+       }
+
+       /**
+        * @test
+        */
+       public function loggerCallsProcessor() {
+               $component = 'test.core.log';
+               $level     = t3lib_log_Level::DEBUG;
+               $message   = 'test';
+
+               $logger = new t3lib_log_Logger($component);
+
+               /** @var $processor t3lib_log_processor_Processor */
+               $processor = $this->getMock('t3lib_log_processor_Null', array('processLogRecord'));
+               $processor->expects($this->once())
+                       ->method('processLogRecord')
+                       ->will($this->returnValue(new t3lib_log_Record($component, $level, $message)));
+
+               $logger->addProcessor($level, $processor);
+
+                       // we need a writer, otherwise we will not process log records
+               $logger->addWriter($level, new t3lib_log_writer_Null());
+
+               $logger->warning($message);
+       }
+
+       /**
+        * @test
+        */
+       public function loggerLogsRecord() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = $this->getMock('t3lib_log_writer_Null', array('writeLog'));
+               $writer->expects($this->once())
+                       ->method('writeLog');
+
+               $logger->addWriter(t3lib_log_Level::DEBUG, $writer);
+
+               $logger->warning('test');
+       }
+
+       /**
+        * @test
+        */
+       public function loggerLogsRecordsAtLeastAsCriticalAsLogLevel() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = new t3lib_log_writer_Test();
+               $logger->addWriter(t3lib_log_Level::NOTICE, $writer);
+
+                       // notice == notice, thus must be logged
+               $logger->log(t3lib_log_Level::NOTICE, 'test message');
+
+               $this->assertAttributeNotEmpty('records', $writer);
+       }
+
+       /**
+        * @test
+        */
+       public function loggerLogsRecordsThroughShorthandMethodDataProvider() {
+               return array(
+                       array('emergency'),
+                       array('alert'),
+                       array('critical'),
+                       array('error'),
+                       array('warning'),
+                       array('notice'),
+                       array('info'),
+                       array('debug'),
+               );
+       }
+
+       /**
+        * @test
+        * @param string $shorthandMethod
+        * @dataProvider loggerLogsRecordsThroughShorthandMethodDataProvider
+        */
+       public function loggerLogsRecordsThroughShorthandMethod($shorthandMethod) {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = new t3lib_log_writer_Test();
+               $logger->addWriter(t3lib_log_Level::DEBUG, $writer);
+
+               call_user_func(array($logger, $shorthandMethod), 'test message');
+
+               $this->assertAttributeNotEmpty('records', $writer);
+       }
+
+       /**
+        * @test
+        */
+       public function loggerLogsRecordsMoreCriticalThanLogLevel() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = new t3lib_log_writer_Test();
+               $logger->addWriter(t3lib_log_Level::NOTICE, $writer);
+
+                       // warning > notice, thus must be logged
+               $logger->log(t3lib_log_Level::WARNING, 'test message');
+
+               $this->assertAttributeNotEmpty('records', $writer);
+       }
+
+       /**
+        * @test
+        */
+       public function addWriterAddsWriter() {
+               $logger = new t3lib_log_Logger('test.core.log');
+
+               $writer = new t3lib_log_writer_Test();
+               $logger->addWriter(t3lib_log_Level::NOTICE, $writer);
+
+               $this->markTestSkipped("writers attribute is multi-dimensional - how to test this?");
+               $this->assertAttributeContains($writer, 'writers', $logger);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/class.t3lib_log_logmanagerTest.php b/tests/Unit/t3lib/log/class.t3lib_log_logmanagerTest.php
new file mode 100644 (file)
index 0000000..37e2445
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for t3lib_log_LogManager.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_LogManagerTest extends tx_phpunit_testcase {
+
+       /**
+        * Enable backup of global and system variables
+        *
+        * @var boolean
+        */
+       protected $backupGlobals = TRUE;
+
+       /**
+        * Exclude TYPO3_DB from backup/ restore of $GLOBALS
+        * because resource types cannot be handled during serializing
+        *
+        * @var array
+        */
+       protected $backupGlobalsBlacklist = array('TYPO3_DB');
+
+       /**
+        * @var t3lib_log_LogManager
+       */
+       protected $logManagerInstance = NULL;
+
+       public function setUp() {
+               $this->logManagerInstance = t3lib_div::makeInstance('t3lib_log_LogManager');
+       }
+
+       public function tearDown() {
+               t3lib_div::makeInstance('t3lib_log_LogManager')->reset();
+       }
+
+       /**
+        * @test
+        */
+       public function logManagerReturnsLoggerWhenRequestedWithGetLogger() {
+               $this->assertInstanceOf('t3lib_log_Logger', $this->logManagerInstance->getLogger('test'));
+       }
+
+       /**
+        * @test
+        */
+       public function logManagerTurnsUnderScoreStyleLoggerNamesIntoDotStyleLoggerNames() {
+               $this->assertSame('test.a.b', $this->logManagerInstance->getLogger('test_a_b')->getName());
+       }
+
+       /**
+        * @test
+        */
+       public function managerReturnsSameLoggerOnRepeatedRequest() {
+               $loggerName = uniqid('test.core.log');
+               $this->logManagerInstance->registerLogger($loggerName);
+
+               $logger1 = $this->logManagerInstance->getLogger($loggerName);
+               $logger2 = $this->logManagerInstance->getLogger($loggerName);
+
+               $this->assertSame($logger1, $logger2);
+       }
+
+       /**
+        * @test
+        */
+       public function configuresLoggerWithConfiguredWriter() {
+               $component = 'test';
+               $writer    = 't3lib_log_writer_Null';
+               $level     = t3lib_log_Level::DEBUG;
+
+               $GLOBALS['TYPO3_CONF_VARS']['LOG'][$component]['writerConfiguration'] = array(
+                       $level => array(
+                               $writer => array()
+                       )
+               );
+
+               /** @var $logger t3lib_log_Logger */
+               $logger  = $this->logManagerInstance->getLogger($component);
+               $writers = $logger->getWriters();
+
+               $this->assertInstanceOf($writer, $writers[$level][0]);
+       }
+
+       /**
+        * @test
+        */
+       public function configuresLoggerWithConfiguredProcessor() {
+               $component = 'test';
+               $processor = 't3lib_log_processor_Null';
+               $level     = t3lib_log_Level::DEBUG;
+
+               $GLOBALS['TYPO3_CONF_VARS']['LOG'][$component]['processorConfiguration'] = array(
+                       $level => array(
+                               $processor => array()
+                       )
+               );
+
+               /** @var $logger t3lib_log_Logger */
+               $logger = $this->logManagerInstance->getLogger($component);
+               $processors = $logger->getProcessors();
+
+               $this->assertInstanceOf($processor, $processors[$level][0]);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/class.t3lib_log_recordTest.php b/tests/Unit/t3lib/log/class.t3lib_log_recordTest.php
new file mode 100644 (file)
index 0000000..f3f573c
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Testcase for t3lib_log_Record.
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_RecordTest extends tx_phpunit_testcase {
+
+       /**
+        * Returns a t3lib_log_Record
+        *
+        * @param array $parameters Parameters to set in t3lib_log_Record constructor.
+        * @return t3lib_log_Record
+        */
+       protected function getRecord(array $parameters = array()) {
+               /** @var $record t3lib_log_Record */
+               $record = new t3lib_log_Record(
+                       (!empty($parameters['component']) ? $parameters['component'] : 'test.core.log'),
+                       (!empty($parameters['level']) ? $parameters['level'] : t3lib_log_Level::DEBUG),
+                       (!empty($parameters['message']) ? $parameters['message'] : 'test message'),
+                       (!empty($parameters['data']) ? $parameters['data'] : array())
+               );
+
+               return $record;
+       }
+       /**
+        * @test
+        */
+       public function constructorSetsCorrectComponent() {
+               $component = 'test.core.log';
+
+               $record = $this->getRecord(array('component' => $component));
+
+               $this->assertEquals(
+                       $component,
+                       $record->getComponent()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function constructorSetsCorrectLogLevel() {
+               $logLevel = t3lib_log_Level::CRITICAL;
+
+               $record = $this->getRecord(array('level' => $logLevel));
+
+               $this->assertEquals(
+                       $logLevel,
+                       $record->getLevel()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function constructorSetsCorrectMessage() {
+               $logMessage = 'test message';
+
+               $record = $this->getRecord(array('message' => $logMessage));
+
+               $this->assertEquals(
+                       $logMessage,
+                       $record->getMessage()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function constructorSetsCorrectData() {
+               $dataArray = array(
+                       'foo' => 'bar',
+               );
+
+               $record = $this->getRecord(array('data' => $dataArray));
+
+               $this->assertEquals(
+                       $dataArray,
+                       $record->getData()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setComponentSetsComponent() {
+               $record = $this->getRecord();
+
+               $component = 'testcomponent';
+
+               $this->assertEquals(
+                       $component,
+                       $record->setComponent($component)->getComponent()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setLevelSetsLevel() {
+               $record = $this->getRecord();
+
+               $level = t3lib_log_Level::EMERGENCY;
+
+               $this->assertEquals(
+                       $level,
+                       $record->setLevel($level)->getLevel()
+               );
+       }
+
+       /**
+        * @test
+        * @expectedException RangeException
+        */
+       public function setLevelValidatesLevel() {
+               $record = $this->getRecord();
+
+               $record->setLevel(100);
+       }
+
+       /**
+        * @test
+        */
+       public function setMessageSetsMessage() {
+               $record = $this->getRecord();
+
+               $message = 'testmessage';
+
+               $this->assertEquals(
+                       $message,
+                       $record->setMessage($message)->getMessage()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setCreatedSetsCreated() {
+               $record = $this->getRecord();
+
+               $created = 123.45;
+
+               $this->assertEquals(
+                       $created,
+                       $record->setCreated($created)->getCreated()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function setRequestIdSetsRequestId() {
+               $record = $this->getRecord();
+
+               $requestId = 'testrequestid';
+
+               $this->assertEquals(
+                       $requestId,
+                       $record->setRequestId($requestId)->getRequestId()
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function toArrayReturnsCorrectValues() {
+               $component = 'test.core.log';
+               $level = t3lib_log_Level::DEBUG;
+               $message = 'test message';
+               $data = array('foo' => 'bar');
+
+               /** @var $record t3lib_log_Record */
+               $record = new t3lib_log_Record(
+                       $component,
+                       $level,
+                       $message,
+                       $data
+               );
+
+               $recordArray = $record->toArray();
+
+               $this->assertEquals(
+                       $component,
+                       $recordArray['component']
+               );
+
+               $this->assertEquals(
+                       $level,
+                       $recordArray['level']
+
+               );
+
+               $this->assertEquals(
+                       $message,
+                       $recordArray['message']
+               );
+
+               $this->assertEquals(
+                       $data,
+                       $recordArray['data']
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function toStringIncludesDataAsJson() {
+               $dataArray = array('foo' => 'bar');
+               $record = $this->getRecord(array('data' => $dataArray));
+
+               $this->assertContains(
+                       json_encode($dataArray),
+                       (string) $record
+               );
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_abstractTest.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_abstractTest.php
new file mode 100644 (file)
index 0000000..7a59b8a
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for t3lib_log_processor_Abstract
+ *
+ * @author Steffen Müller <typo3@t3node.com>
+ */
+class t3lib_log_processor_AbstractTest extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        * @expectedException InvalidArgumentException
+        */
+       public function processorRefusesInvalidConfigurationOptions() {
+               $invalidConfiguration = array(
+                       'foo' => 'bar'
+               );
+
+               $processor = t3lib_div::makeInstance('t3lib_log_processor_Test', $invalidConfiguration);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_abstractmemoryTest.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_abstractmemoryTest.php
new file mode 100644 (file)
index 0000000..674f54f
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for t3lib_log_processor_AbstractMemory
+ *
+ * @author Steffen Müller <typo3@t3node.com>
+ */
+class t3lib_log_processor_AbstractMemoryTest extends tx_phpunit_testcase {
+
+
+       /**
+        * @test
+        */
+       function getRealMemoryUsageGetsRealMemoryUsage() {
+                       /** @var $processor t3lib_log_processor_AbstractMemory */
+               $processor = $this->getMockForAbstractClass('t3lib_log_processor_AbstractMemory');
+               $this->assertAttributeEquals($processor->getRealMemoryUsage(), 'realMemoryUsage', $processor);
+       }
+
+       /**
+        * @test
+        */
+       function setRealMemoryUsageSetsRealMemoryUsage() {
+                       /** @var $processor t3lib_log_processor_AbstractMemory */
+               $processor = $this->getMockForAbstractClass('t3lib_log_processor_AbstractMemory');
+               $processor->setRealMemoryUsage(FALSE);
+               $this->assertAttributeEquals(FALSE, 'realMemoryUsage', $processor);
+       }
+
+       /**
+        * @test
+        */
+       function getFormatSizeGetsFormatSize() {
+                       /** @var $processor t3lib_log_processor_AbstractMemory */
+               $processor = $this->getMockForAbstractClass('t3lib_log_processor_AbstractMemory');
+               $this->assertAttributeEquals($processor->getFormatSize(), 'formatSize', $processor);
+       }
+
+       /**
+        * @test
+        */
+       function setFormatSizeSetsFormatSize() {
+                       /** @var $processor t3lib_log_processor_AbstractMemory */
+               $processor = $this->getMockForAbstractClass('t3lib_log_processor_AbstractMemory');
+               $processor->setFormatSize(FALSE);
+               $this->assertAttributeEquals(FALSE, 'formatSize', $processor);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_introspectionTest.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_introspectionTest.php
new file mode 100644 (file)
index 0000000..682f287
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for the web introspection processor.
+ *
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_IntrospectionTest extends tx_phpunit_testcase {
+
+       /**
+        * Tests if debug_backtrace values are added to LogRecord
+        * The debug_backtrace in t3lib_log_processor_Introspection will always process a phpunit class.
+        * The result is unpredictable values. So we only test if values are not empty/0
+        *
+        * @test
+        */
+       public function introspectionProcessorAddsIntrospectionDataToLogRecord() {
+               $logRecord = new t3lib_log_Record('test.core.log', t3lib_log_Level::DEBUG, 'test');
+               $processor = new t3lib_log_processor_Introspection();
+
+               $logRecord = $processor->processLogRecord($logRecord);
+
+               $this->assertNotEmpty($logRecord['data']['file'], 'Asserting that file name in debug_backtrace() is not empty');
+               $this->assertGreaterThan(0, $logRecord['data']['line'], 'Asserting that line numer in debug_backtrace() is greater than 0');
+               $this->assertNotEmpty($logRecord['data']['class'], 'Asserting that class in debug_backtrace() is not empty');
+               $this->assertNotEmpty($logRecord['data']['function'], 'Asserting that function in debug_backtrace() is not empty');
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_memoryPeakUsageTest.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_memoryPeakUsageTest.php
new file mode 100644 (file)
index 0000000..8faa95b
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for the memoryPeakUsage log processor.
+ *
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_memoryPeakUsageTest extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        */
+       public function memoryPeakUsagePRocessorAddsMemoryPeakUsageDataToLogRecord() {
+               $logRecord = new t3lib_log_Record('test.core.log', t3lib_log_Level::DEBUG, 'test');
+               $processor = new t3lib_log_processor_MemoryPeakUsage();
+
+               $logRecord = $processor->processLogRecord($logRecord);
+
+               $this->assertArrayHasKey('memoryPeakUsage', $logRecord['data']);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_memoryUsageTest.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_memoryUsageTest.php
new file mode 100644 (file)
index 0000000..6476a03
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for the memoryUsage log processor.
+ *
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_memoryUsageTest extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        */
+       public function memoryUsagePRocessorAddsMemoryUsageDataToLogRecord() {
+               $logRecord = new t3lib_log_Record('test.core.log', t3lib_log_Level::DEBUG, 'test');
+               $processor = new t3lib_log_processor_MemoryUsage();
+
+               $logRecord = $processor->processLogRecord($logRecord);
+
+               $this->assertArrayHasKey('memoryUsage', $logRecord['data']);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_processorTest.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_processorTest.php
new file mode 100644 (file)
index 0000000..356f27b
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for log processors.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_ProcessorTest extends tx_phpunit_testcase implements t3lib_log_processor_Processor {
+
+       /**
+        * @var bool
+        */
+       public $processorCalled = FALSE;
+
+       /**
+        * Processes a log record and adds server data.
+        *
+        * @param t3lib_log_Record $logRecord The log record to process
+        * @return t3lib_log_Record The processed log record with addtional data
+        */
+       public function processLogRecord(t3lib_log_Record $logRecord) {
+               $this->processorCalled = TRUE;
+
+               return $logRecord;
+       }
+
+       /**
+        * @test
+        */
+       public function loggerExecutesProcessors() {
+               $logger = new t3lib_log_Logger('test.core.log');
+               $writer = new t3lib_log_writer_Null();
+               $level = t3lib_log_Level::DEBUG;
+
+               $logger->addWriter($level, $writer);
+               $logger->addProcessor($level, $this);
+
+               $logger->warning('test');
+
+               $this->assertTrue($this->processorCalled);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_test.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_test.php
new file mode 100644 (file)
index 0000000..948ea4e
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * A processor dedicated for testing
+ *
+ * @author Steffen Müller <typo3@t3node.com>
+ */
+class t3lib_log_processor_Test extends t3lib_log_processor_Abstract {
+
+       /**
+        * Processing the record
+        *
+        * @param t3lib_log_Record $record
+        * @return t3lib_log_Record
+        */
+       public function processLogRecord(t3lib_log_Record $record) {
+               return $record;
+       }
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_webTest.php b/tests/Unit/t3lib/log/processor/class.t3lib_log_processor_webTest.php
new file mode 100644 (file)
index 0000000..d850ef2
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Ingo Renner (ingo@typo3.org)
+ * (c) 2012 Steffen Müller (typo3@t3node.com)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for the web log processor.
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Steffen Müller <typo3@t3node.com>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_log_processor_WebTest extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        */
+       public function webProcessorAddsWebDataToLogRecord() {
+               $environmentVariables = t3lib_div::getIndpEnv('_ARRAY');
+
+               $logRecord = new t3lib_log_Record('test.core.log', t3lib_log_Level::DEBUG, 'test');
+               $processor = new t3lib_log_processor_Web();
+
+               $logRecord = $processor->processLogRecord($logRecord);
+
+               foreach ($environmentVariables as $key => $value) {
+                       $this->assertEquals($value, $logRecord['data'][$key]);
+               }
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_abstractTest.php b/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_abstractTest.php
new file mode 100644 (file)
index 0000000..2ca3ee3
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for t3lib_log_writer_Abstract
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ */
+class t3lib_log_writer_AbstractTest extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        * @expectedException InvalidArgumentException
+        */
+       public function refusesInvalidConfigurationOptions() {
+               $invalidConfiguration = array(
+                       'foo' => 'bar'
+               );
+
+               $writer = t3lib_div::makeInstance('t3lib_log_writer_Test', $invalidConfiguration);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_databaseTest.php b/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_databaseTest.php
new file mode 100644 (file)
index 0000000..7931ecc
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for t3lib_log_writer_Database
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ */
+class t3lib_log_writer_DatabaseTest extends tx_phpunit_testcase {
+
+       /**
+        * Backup and restore of the $GLOBALS array.
+        *
+        * @var boolean
+        */
+       protected $backupGlobalsArray = array();
+
+       /**
+        * Mock object of t3lib_db
+        *
+        * @var PHPUnit_Framework_MockObject_MockObject
+        */
+       private $databaseStub;
+
+       /**
+        * Create a new database mock object for every test
+        * and backup the original global database object.
+        *
+        * @return void
+        */
+       public function setUp() {
+               $this->backupGlobalsArray['TYPO3_DB'] = $GLOBALS['TYPO3_DB'];
+               $this->databaseStub = $this->setUpAndReturnDatabaseStub();
+       }
+
+       /**
+        * Restore global database object.
+        *
+        * @return void
+        */
+       protected function tearDown() {
+               $GLOBALS['TYPO3_DB'] = $this->backupGlobalsArray['TYPO3_DB'];
+       }
+
+       //////////////////////
+       // Utility functions
+       //////////////////////
+
+       /**
+        * Set up the stub to be able to get the result of the prepared statement.
+        *
+        * @return PHPUnit_Framework_MockObject_MockObject
+        */
+       private function setUpAndReturnDatabaseStub() {
+               $databaseLink = $GLOBALS['TYPO3_DB']->link;
+
+               $GLOBALS['TYPO3_DB'] = $this->getMock('t3lib_DB', array('exec_INSERTquery'), array(), '', FALSE, FALSE);
+               $GLOBALS['TYPO3_DB']->link = $databaseLink;
+
+               return $GLOBALS['TYPO3_DB'];
+       }
+
+       /**
+        * Creates a test logger
+        *
+        * @return t3lib_log_Logger
+        */
+       protected function createLogger() {
+               $loggerName = uniqid('test.core.datbaseWriter');
+
+               /** @var t3lib_log_Logger $logger */
+               $logger = t3lib_div::makeInstance('t3lib_log_LogManager')->getLogger($loggerName);
+
+               return $logger;
+       }
+
+       /**
+        * Creates a database writer
+        *
+        * @return t3lib_log_writer_Database
+        */
+       protected function createWriter() {
+               /** @var t3lib_log_writer_Database $writer */
+               $writer = t3lib_div::makeInstance('t3lib_log_writer_Database');
+
+               return $writer;
+       }
+
+       /**
+        * @test
+        */
+       public function setLogTableSetsLogTable() {
+               $logTable = uniqid('logtable_');
+
+               $this->assertSame(
+                       $logTable,
+                       $this->createWriter()->setLogTable($logTable)->getLogTable()
+               );
+       }
+
+       /**
+        * @return array
+        */
+       public function writerLogsToDatabaseDataProvider() {
+               $simpleRecord = t3lib_div::makeInstance('t3lib_log_Record',
+                       'test.core.databaseWriter.simpleRecord',
+                       t3lib_log_Level::ALERT,
+                       'test entry'
+               );
+
+               $recordWithData = t3lib_div::makeInstance('t3lib_log_Record',
+                       'test.core.databaseWriter.recordWithData',
+                       t3lib_log_Level::ALERT,
+                       'test entry with data',
+                       array('foo' => array('bar' => 'baz'))
+               );
+
+               return array(
+                       'simple record'    => array($simpleRecord),
+                       'record with data' => array($recordWithData),
+               );
+       }
+
+       /**
+        * @test
+        * @param t3lib_log_Record $record Record Test Data
+        * @dataProvider writerLogsToDatabaseDataProvider
+        */
+       public function writerLogsToDatabase(t3lib_log_Record $record) {
+               $logger = $this->createLogger();
+               $databaseWriter = $this->createWriter();
+               $logger->addWriter(t3lib_log_Level::NOTICE, $databaseWriter);
+
+               $this->databaseStub
+                       ->expects($this->once())
+                       ->method('exec_INSERTquery');
+
+               $logger->log($record->getLevel(), $record->getMessage());
+
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_failing.php b/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_failing.php
new file mode 100644 (file)
index 0000000..53c204e
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * A log writer that always fails to write (for testing purposes ;-))
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ */
+class t3lib_log_writer_Failing implements t3lib_log_writer_Writer {
+
+       /**
+        * Try to write the log entry - but throw an exception in our case
+        *
+        * @param t3lib_log_Record $record
+        * @return t3lib_log_writer_Writer|void
+        * @throws RuntimeException
+        */
+       public function writeLog(t3lib_log_Record $record) {
+               throw new RuntimeException("t3lib_log_writer_Failing failed");
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_fileTest.php b/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_fileTest.php
new file mode 100644 (file)
index 0000000..5d682d9
--- /dev/null
@@ -0,0 +1,210 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * Testcase for t3lib_log_writer_File
+ *
+ * @author Steffen Gebert <steffen.gebert@typo3.org>
+ */
+class t3lib_log_writer_FileTest extends tx_phpunit_testcase {
+
+       /**
+        * @var string
+        */
+       protected $logFileDirectory = 'Log';
+
+       /**
+        * @var string
+        */
+       protected $logFileName = 'test.log';
+
+
+       protected function setUpVfsStream() {
+               if (!class_exists('vfsStream')) {
+                       $this->markTestSkipped('File backend tests are not available with this phpunit version.');
+               }
+
+               vfsStream::setup('LogRoot');
+       }
+
+       /**
+        * Creates a test logger
+        *
+        * @param string $name
+        * @internal param string $component Component key
+        * @return t3lib_log_Logger
+        */
+       protected function createLogger($name = '') {
+               if (empty($name)) {
+                       $name = uniqid('test.core.log.');
+               }
+
+               t3lib_div::makeInstance('t3lib_log_LogManager')->registerLogger($name);
+
+               /** @var t3lib_log_Logger $logger */
+               $logger = t3lib_div::makeInstance('t3lib_log_LogManager')->getLogger($name);
+
+               return $logger;
+       }
+
+       /**
+        * Creates a file writer
+        *
+        * @return t3lib_log_writer_File
+        */
+       protected function createWriter() {
+               /** @var t3lib_log_writer_File $writer */
+               $writer = t3lib_div::makeInstance('t3lib_log_writer_File', array(
+                       'logFile' => 'vfs://LogRoot/' . $this->logFileDirectory . '/' . $this->logFileName
+               ));
+
+               return $writer;
+       }
+
+       protected function getDefaultFileName() {
+               return 'vfs://LogRoot/' . $this->logFileDirectory . '/' . $this->logFileName;
+       }
+
+
+
+       /**
+        * @test
+        */
+       public function setLogFileSetsLogFile() {
+               $this->setUpVfsStream();
+               vfsStream::newFile($this->logFileName)->at(vfsStreamWrapper::getRoot());
+
+               $writer = t3lib_div::makeInstance('t3lib_log_writer_File');
+               $writer->setLogFile($this->getDefaultFileName());
+
+               $this->assertAttributeEquals($this->getDefaultFileName(), 'logFile', $writer);
+       }
+
+       /**
+        * @test
+        * @expectedException InvalidArgumentException
+        */
+       public function setLogFileRefusesIllegalPath() {
+               $writer = t3lib_div::makeInstance('t3lib_log_writer_File');
+               $writer->setLogFile('/tmp/typo3.log');
+       }
+
+       /**
+        * @test
+        */
+       public function createsLogFileDirectory() {
+               $this->setUpVfsStream();
+
+               $this->createWriter();
+
+               $this->assertTrue(vfsStreamWrapper::getRoot()->hasChild($this->logFileDirectory));
+       }
+
+
+       /**
+        * @test
+        */
+       public function createsLogFile() {
+               $this->setUpVfsStream();
+
+               $this->createWriter();
+
+               $this->assertTrue(vfsStreamWrapper::getRoot()->getChild($this->logFileDirectory)->hasChild($this->logFileName));
+       }
+
+       /**
+        * @return array
+        */
+       public function logsToFileDataProvider() {
+               $simpleRecord = t3lib_div::makeInstance('t3lib_log_Record',
+                       uniqid('test.core.log.fileWriter.simpleRecord.'),
+                       t3lib_log_Level::INFO,
+                       'test record'
+               );
+
+               $recordWithData = t3lib_div::makeInstance('t3lib_log_Record',
+                       uniqid('test.core.log.fileWriter.recordWithData.'),
+                       t3lib_log_Level::ALERT,
+                       'test record with data',
+                       array('foo' => array('bar' => 'baz'))
+               );
+
+               return array(
+                       'simple record'    => array($simpleRecord,   (string) $simpleRecord),
+                       'record with data' => array($recordWithData, (string) $recordWithData),
+               );
+       }
+
+       /**
+        * @test
+        * @param t3lib_log_Record $record Record Test Data
+        * @param string $expectedResult Needle
+        * @dataProvider logsToFileDataProvider
+        */
+       public function logsToFile(t3lib_log_Record $record, $expectedResult) {
+
+               $this->setUpVfsStream();
+
+               $this->createWriter()->writeLog($record);
+
+               $logFileContents = file_get_contents($this->getDefaultFileName());
+               $logFileContents = trim($logFileContents);
+               $expectedResult = trim($expectedResult);
+
+               $this->assertEquals($logFileContents, $expectedResult);
+       }
+
+       /**
+        * @test
+        */
+       public function createsHtaccessForNewDirectory() {
+               $this->setUpVfsStream();
+               $directory = uniqid('Log');
+
+               $logFile = 'vfs://LogRoot/' . $directory . '/' . $this->logFileName;
+               $this->createWriter()->setLogFile($logFile);
+
+               $this->assertFileExists('vfs://LogRoot/' . $directory . '/.htaccess');
+       }
+
+       /**
+        * @test
+        */
+       public function createsNoHtaccessForExistingDirectory() {
+               $this->setUpVfsStream();
+               $directory = uniqid('Log');
+                       // create a directory
+               vfsStreamWrapper::getRoot()->addChild(new vfsStreamDirectory($directory));
+
+               $logFile = 'vfs://LogRoot/' . $directory . '/' . $this->logFileName;
+               $this->assertTrue(is_dir('vfs://LogRoot/' . $directory));
+
+               $this->createWriter()->setLogFile($logFile);
+
+               $this->assertFileNotExists('vfs://LogRoot/' . $directory . '/.htaccess');
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_test.php b/tests/Unit/t3lib/log/writer/class.t3lib_log_writer_test.php
new file mode 100644 (file)
index 0000000..0a4b84b
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+
+/**
+ * A writer dedicated for testing
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+class t3lib_log_writer_Test extends t3lib_log_writer_Abstract {
+
+       /**
+        * @var array
+        */
+       protected $records = array();
+
+       public function writeLog(t3lib_log_Record $record) {
+               $this->records[] = $record;
+       }
+
+}
+
+
+?>
\ No newline at end of file
index c0fe5e1..393ba4c 100644 (file)
@@ -227,6 +227,7 @@ class Typo3_Bootstrap_BaseSetup {
                require_once(PATH_t3lib . 'cache/backend/interfaces/interface.t3lib_cache_backend_phpcapablebackend.php');
                require_once(PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_simplefilebackend.php');
                require_once(PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_nullbackend.php');
+               require_once(PATH_t3lib . 'log/class.t3lib_log_level.php');
 
                require_once(PATH_t3lib . 'class.t3lib_autoloader.php');
        }