Flexible logging with TYPO3

tl;dr TYPO3 offers a simple API to create a flexible logging setup. Developers may write a log file with just two lines of code, and configure custom logging endpoints for individual classes.

Sometimes it is necessary to write logs in an extension. For example if a script imports data periodically, the developer may want to log all status messages of the import action, like “Import successfull”.

The obvious solution is to write a custom logging method, which appends such status messages to a defined file. The pitfall of this solution is, that this logging method is fixed and tied to the extension only. Several extensions may use different files and different formats.

Another, often used solution was the \TYPO3\CMS\Core\Utility\GeneralUtility::devLog method, provided by the TYPO3 core. This method did not log anything, but offered a hook for extensions, to pass log messages to handlers of the these extensions. The very popular extension »devlog« has a handler which saves all messages to a database table and offers a backend module to list and filter these entries. This is usefull in development, but should never be used in production as this may blow up the database very fast.

Since version 6.0 TYPO3 offers a simple logging API, which has the huge advantage that the logging endpoints may be set independently of the extension which called the logger.

To use the logger in a class, two lines of code are sufficient:

$logger = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
$logger->info('Everything is fine.');

The logger offers several different severity levels. The info method is a shorthand which passes the level \TYPO3\CMS\Core\Log\LogLevel::INFO to the main log method. It is also possible to pass data bound to an array, for both the main- and the shorthand method:

$logger->log(
    \TYPO3\CMS\Core\Log\LogLevel::ERROR,
    'Everything is burning!',
    ['foo' => 'hello world']
);

By default TYPO3 will write a log file, which has the schema typo3temp/logs/typo3_<hash>.log and may look like this:

Fri, 08 Mar 2013 09:45:00 +0100 [INFO] request="5139a50bee3a1" component="SomeController": Everything is fine.
Fri, 08 Mar 2013 09:45:00 +0100 [ERROR] request="5139a50bee3a1" component="SomeController": Everything is burning! - {"foo":"bar"}

The way to write log messages is configured in $GLOBALS['TYPO3_CONF_VARS']['LOG']['writerConfiguration']. This array may be modified in the AdditionalConfiguration.php file. TYPO3 offers several log writers like a database logger or a file logger out of the box. It is possible to configure different loggers for each severity level, or concat loggers for the same severity level. It is even possible to set up custom logging for single classes.

In the following example code the system is writing all »error« log messages to a file and to the PHP error log using error_log(). If the installation has the application context »Development«, then all »info« messages are written to a file as well.

$GLOBALS['TYPO3_CONF_VARS']['LOG']['writerConfiguration'] = [
  \TYPO3\CMS\Core\Log\LogLevel::ERROR => [
    'TYPO3\\CMS\\Core\\Log\\Writer\\FileWriter' => [
      'logFile' => 'typo3temp/logs/typo3_error.log'
    ]
    , 'TYPO3\\CMS\\Core\\Log\\Writer\\PhpErrorLogWriter' => []
  ],
];

if(\TYPO3\CMS\Core\Utility\GeneralUtility::getApplicationContext()->isDevelopment()) {
  $GLOBALS['TYPO3_CONF_VARS']['LOG']['writerConfiguration'][\TYPO3\CMS\Core\Log\LogLevel::INFO] = [
    'TYPO3\\CMS\\Core\\Log\\Writer\\FileWriter' => [
      'logFile' => 'typo3temp/logs/typo3_info.log' . \TYPO3\CMS\Core\Log\LogLevel::INFO
    ]
  ];
}

It is possible to write custom log writers and preprocess log messages, for example to add a backtrace or server environment variables.

The logging API allows to write custom log writers. If some fancy writers are desired, then it is advantageous to take a look at EXT:logging. This extension adds the »Monolog« package to TYPO3, which allows actions like logging warning messages in a file, send errors of class X to a Slack channel and errors of class Y to an E-Mail recipient.

Update: Daniel Siepmann wrote a configuration snippet to pass all devLog calls to the logging API and write them into a file. This replaces the devlog extension and has the advantage that the configuration may be limited to testsystem using a condition.

⌛ Warning! This post is old. The information may be outdated.

No comments on this notepad. If you would like to add something, then dont hesitate to contact me via E-Mail or Twitter.