Log writers

The purpose of a log writer is (usually) to save all log records into a persistent storage, like a log file, a database table, or to a remote syslog server.

Different log writers offer possibilities to log into different targets. Custom log writers can extend the functionality shipped with TYPO3 Core.

Built-in log writers

This section describes the log writers shipped with the TYPO3 Core. Some writers have options to allow customization of the particular writer. See the configuration section on how to use these options.

DatabaseWriter

The database writer logs into a database table. This table has to reside in the database used by TYPO3 and is not automatically created.

The following option is available:

logTable
type

string

Mandatory

no

Default

sys_log

The database table to write to.

Example of a CREATE TABLE statement for logTable:

EXT:my_extension/ext_tables.sql
#
# Table structure for table 'tx_examples_log'
#
# The KEY on request_id is optional
#
CREATE TABLE tx_examples_log
(
    request_id varchar(13) DEFAULT '' NOT NULL,
    time_micro double(16, 4) NOT NULL default '0.0000',
    component varchar(255) DEFAULT '' NOT NULL,
    level tinyint(1) unsigned DEFAULT '0' NOT NULL,
    message text,
    data text,

    KEY request (request_id)
);
Copied!

The corresponding configuration might look like this for the example class \T3docs\Examples\Controller:

EXT:my_extension/ext_localconf.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Log\LogLevel;
use TYPO3\CMS\Core\Log\Writer\DatabaseWriter;

defined('TYPO3') or die();

$GLOBALS['TYPO3_CONF_VARS']['LOG']['T3docs']['Examples']['Controller']['writerConfiguration'] = [
    LogLevel::DEBUG => [
        DatabaseWriter::class => [
            'logTable' => 'tx_examples_log',
        ],
    ],
];
Copied!

FileWriter

The file writer logs into a log file, one log record per line. If the log file does not exist, it will be created (including parent directories, if needed).

Please make sure:

  • Your web server has write permissions to that path.
  • The path is below the root directory of your website (defined by Environment::getPublicPath()).

The filename is appended with a hash, that depends on the encryption key. If $GLOBALS['TYPO3_CONF_VARS']['SYS']['generateApacheHtaccess'] is set, an .htaccess file is added to the directory. It protects your log files from being accessed from the web. If the logFile option is not set, TYPO3 will use a filename containing a random hash, like typo3temp/logs/typo3_7ac500bce5.log.

The following options are available:

logFile
type

string

Mandatory

no

Default

typo3temp/logs/typo3_<hash>.log (for example, like typo3temp/logs/typo3_7ac500bce5.log)

The path to the log file.

logFileInfix
type

string

Mandatory

no

Default

(empty string)

This option allows to set a different name for the log file that is created by the FileWriter without having to define a full path to the file. For example, the settings 'logFileInfix' => 'special' results in typo3_special_<hash>.log.

The corresponding configuration might look like this for the example class \T3docs\Examples\Controller:

EXT:my_extension/ext_localconf.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Log\LogLevel;
use TYPO3\CMS\Core\Log\Writer\FileWriter;

defined('TYPO3') or die();

// Add example configuration for the logging API
$GLOBALS['TYPO3_CONF_VARS']['LOG']['T3docs']['Examples']['Controller']['writerConfiguration'] = [
    // configuration for ERROR level log entries
    LogLevel::ERROR => [
        // Add a FileWriter
        FileWriter::class => [
            // Configuration for the writer
            'logFile' => Environment::getVarPath() . '/log/typo3_examples.log',
        ],
    ],
];
Copied!

RotatingFileWriter

New in version 13.0

TYPO3 log files tend to grow over time if not manually cleaned on a regular basis, potentially leading to full disks. Also, reading its contents may be hard when several weeks of log entries are printed as a wall of text.

To circumvent such issues, established tools like logrotate are available for a long time already. However, TYPO3 may be installed on a hosting environment where "logrotate" is not available and cannot be installed by the customer. To cover such cases, a simple log rotation approach is available, following the "copy/truncate" approach: when rotating files, the currently opened log file is copied (for example, to typo3_<hash>.log.20230616094812) and the original log file is emptied.

Example of the var/log/ folder with rotated log files:

$ ls -1 var/log
typo3_<hash>.log
typo3_<hash>.log.20230613065902
typo3_<hash>.log.20230614084723
typo3_<hash>.log.20230615084756
typo3_<hash>.log.20230616094812
Copied!

The file writer \TYPO3\CMS\Core\Log\Writer\RotatingFileWriter extends the FileWriter class. The RotatingFileWriter accepts all options of FileWriter in addition of the following:

interval
type

\TYPO3\CMS\Core\Log\Writer\Enum\Interval, string

Mandatory

no

Default

\TYPO3\CMS\Core\Log\Writer\Enum\Interval::DAILY

The interval defines how often logs should be rotated. Use one of the following options:

  • \TYPO3\CMS\Core\Log\Writer\Enum\Interval::DAILY or daily
  • \TYPO3\CMS\Core\Log\Writer\Enum\Interval::WEEKLY or weekly
  • \TYPO3\CMS\Core\Log\Writer\Enum\Interval::MONTHLY or monthly
  • \TYPO3\CMS\Core\Log\Writer\Enum\Interval::YEARLY or yearly
maxFiles
type

integer

Mandatory

non

Default

5

This option configured how many files should be retained (use 0 to never delete any file).

The following example introduces log rotation for the "main" log file:

config/system/additional.php | typo3conf/system/additional.php
<?php

declare(strict_types=1);

use Psr\Log\LogLevel;
use TYPO3\CMS\Core\Log\Writer\Enum\Interval;
use TYPO3\CMS\Core\Log\Writer\RotatingFileWriter;

$GLOBALS['TYPO3_CONF_VARS']['LOG']['writerConfiguration'][LogLevel::ERROR] = [
    RotatingFileWriter::class => [
        'interval' => Interval::DAILY,
        'maxFiles' => 5,
    ],
];
Copied!

Another example introduces log rotation for the "deprecation" log file:

config/system/additional.php | typo3conf/system/additional.php
<?php

declare(strict_types=1);

use Psr\Log\LogLevel;
use TYPO3\CMS\Core\Log\Writer\Enum\Interval;
use TYPO3\CMS\Core\Log\Writer\RotatingFileWriter;

$GLOBALS['TYPO3_CONF_VARS']['LOG']['TYPO3']['CMS']['deprecations']['writerConfiguration'][LogLevel::NOTICE] = [
    RotatingFileWriter::class => [
        'logFileInfix' => 'deprecations',
        'interval' => Interval::WEEKLY,
        'maxFiles' => 4,
        'disabled' => false,
    ],
];
Copied!

PhpErrorLogWriter

This writer logs into the PHP error log using error_log()

SyslogWriter

The syslog writer logs into the syslog (Unix only).

The following option is available:

facility
type

string

Mandatory

no

Default

USER

The syslog facility to log into.

Custom log writers

Custom log writers can be added through extensions. Every log writer has to implement the interface EXT:core/Classes/Log/Writer/WriterInterface.php (GitHub). It is suggested to extend the abstract class EXT:core/Classes/Log/Writer/AbstractWriter.php (GitHub) which allows you to use configuration options by adding the corresponding properties and setter methods.

Please keep in mind that TYPO3 will silently continue operating, in case a log writer is throwing an exception while executing the writeLog() method. Only in the case that all registered writers fail, the log entry with additional information will be added to the configured fallback logger (which defaults to the PhpErrorLog writer).

Usage in a custom class

All log writers can be used in your own classes. If the service is configured to use autowiring you can inject a logger into the __construct() method of your class \MyVendor\MyExtension\MyFolder\MyClass) since TYPO3 v11 LTS.

EXT:my_extension/Classes/MyClass.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension;

use Psr\Log\LoggerInterface;

final class MyClass
{
    public function __construct(
        private readonly LoggerInterface $logger,
    ) {}

    public function doSomething()
    {
        $this->logger->info('My class is executed.');

        $error = false;

        // ... something is done ...

        if ($error) {
            $this->logger->error('Error in class MyClass');
        }
    }
}
Copied!

If autowiring is disabled, the service class however must implement the interface \Psr\Log\LoggerAwareInterface and use the \Psr\Log\LoggerAwareTrait.

EXT:my_extension/Classes/MyClass.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension;

use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;

final class MyClass implements LoggerAwareInterface
{
    use LoggerAwareTrait;

    public function doSomething()
    {
        $this->logger->info('My class is executed.');

        $error = false;

        // ... something is done ...

        if ($error) {
            $this->logger->error('Error in class MyClass');
        }
    }
}
Copied!

One or more log writers for this class are configured in the file ext_localconf.php:

EXT:my_extension/ext_localconf.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Log\LogLevel;
use TYPO3\CMS\Core\Log\Writer\FileWriter;

defined('TYPO3') or die();

// Add example configuration for the logging API
$GLOBALS['TYPO3_CONF_VARS']['LOG']['MyVendor']['MyExtension']['MyClass']['writerConfiguration'] = [
    // Configuration for ERROR level log entries
    LogLevel::ERROR => [
        // Add a FileWriter
        FileWriter::class => [
            // Configuration for the writer
            'logFile' => Environment::getVarPath() . '/log/my_extension.log',
        ],
    ],
];
Copied!

Examples

Working examples of the usage of different Log writers can be found in the extension EXT:examples.