---
title: "Log writers"
manual: "TYPO3 Explained"
version: "13.4"
permalink: "https://docs.typo3.org/permalink/t3coreapi:logging-writers@13.4"
source: "ApiOverview/Logging/Writers/Index.rst"
rendered: "2026-10-01T12:09:27+00:00"
---

# Log writers {#logging-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.

> [!NOTE]
> **See also**
>
> If you are looking for guidance on configuring logging for production
> environments — such as log rotation, file locations, retention, or
> integration with tools like Sentry — see the chapter
> [Logging considerations during production](https://docs.typo3.org/permalink/t3coreapi:production-logging@13.4).

Different log writers offer possibilities to log into different targets.
[Custom log writers](https://docs.typo3.org/permalink/t3coreapi:logging-writers-custom@13.4) can extend the functionality
shipped with TYPO3 Core.

****Table of Contents****

-   [Built-in log writers](https://docs.typo3.org/permalink/t3coreapi:built-in-log-writers@13.4)
-   [Custom log writers](https://docs.typo3.org/permalink/t3coreapi:custom-log-writers@13.4)
-   [Examples](https://docs.typo3.org/permalink/t3coreapi:examples@13.4)

## Built-in log writers {#logging-writers-builtin}

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](https://docs.typo3.org/permalink/t3coreapi:logging-configuration-writer@13.4) section on how to
use these options.

### DatabaseWriter {#logging-writers-database}

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
    -   *Default:* `sys_log`

    The database table to write to.

    > [!WARNING]
    > The **Admin Tools > Log** module is not adapted to the records
    > written by the `DatabaseWriter` into the `sys_log` table. If
    > you write such records there, you will not be able to see them using
    > that module.

    > [!TIP]
    > There is the third-party extension [`co-stack/logs`](https://packagist.org/packages/co-stack/logs) available for viewing
    > such records in the TYPO3 backend.

    Example of a `CREATE TABLE` statement for `logTable`:

    **EXT:my_extension/ext_tables.sql**

    ```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)
    );

    ```

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

    **EXT:my_extension/ext_localconf.php**

    ```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',
        ],
      ],
    ];

    ```

> [!WARNING]
> If you are using a MariaDB Galera Cluster you should definitely add a
> primary key field to the database definition, since it is required by
> Galera (this can be a normal `uid` autoincrement field as known from
> other tables):
> [MariaDB Galera Cluster - Known Limitations](https://mariadb.com/kb/en/mariadb/mariadb-galera-cluster-known-limitations/).

### FileWriter {#logging-writers-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()](https://docs.typo3.org/permalink/t3coreapi:environment-public-path@13.4)).

The filename is appended with a hash, that depends on the
[encryption key](https://docs.typo3.org/permalink/t3coreapi:typo3confvars-sys-encryptionkey@13.4). If
[$GLOBALS\['TYPO3_CONF_VARS'\]\['SYS'\]\['generateApacheHtaccess'\]](https://docs.typo3.org/permalink/t3coreapi:typo3confvars-sys-generateapachehtaccess@13.4)
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 {#file-writer-logfile}

-   **logFile**

    -   *Type:* string
    -   *Default:* `typo3temp/logs/typo3_<hash>.log` (for example, like `typo3temp/logs/typo3_7ac500bce5.log`)

    The path to the log file.

#### logFileInfix {#file-writer-logfileinfix}

-   **logFileInfix**

    -   *Type:* string
    -   *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
<?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',
    ],
  ],
];

```

### RotatingFileWriter {#logging-writers-rotatingfilewriter}

<!-- TODO: no Markdown rendering for "versionadded" -->

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](https://linux.die.net/man/8/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:

**typo3_root$**

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

The file writer `\TYPO3\CMS\Core\Log\Writer\RotatingFileWriter` extends the
[FileWriter](https://docs.typo3.org/permalink/t3coreapi:logging-writers-filewriter@13.4) class. The `RotatingFileWriter`
accepts all options of `FileWriter` in addition of the following:

#### interval {#rotating-file-writer-interval}

-   **interval**

    -   *Type:* `\TYPO3\CMS\Core\Log\Writer\Enum\Interval`, string
    -   *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 {#rotating-file-writer-maxfiles}

-   **maxFiles**

    -   *Type:* integer
    -   *Default:* `5`

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

> [!NOTE]
> When configuring the `RotatingFileWriter` in
> `system/settings.php`, the string representations of the
> `Interval` cases must be used for the option `interval` option,
> as otherwise this might break the Install Tool.

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

**config/system/additional.php | typo3conf/system/additional.php**

```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,
  ],
];

```

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

**config/system/additional.php | typo3conf/system/additional.php**

```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,
  ],
];

```

### PhpErrorLogWriter {#logging-writers-php}

This writer logs into the PHP error log using [error_log()](https://www.php.net/manual/en/function.error-log.php)

### SyslogWriter {#logging-writers-syslog}

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

The following option is available:

-   **facility**

    -   *Type:* string
    -   *Default:* `USER`

    The syslog [facility](https://en.wikipedia.org/wiki/Syslog#Facility) to log into.

## Custom log writers {#logging-writers-custom}

Custom log writers can be added through extensions. Every log writer has to
implement the interface [EXT:core/Classes/Log/Writer/WriterInterface.php (GitHub)](https://github.com/typo3/typo3/blob/13.4/typo3/sysext/core/Classes/Log/Writer/WriterInterface.php). It is
suggested to extend the abstract class [EXT:core/Classes/Log/Writer/AbstractWriter.php (GitHub)](https://github.com/typo3/typo3/blob/13.4/typo3/sysext/core/Classes/Log/Writer/AbstractWriter.php)
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](https://docs.typo3.org/permalink/t3coreapi:logging-writers-php@13.4) writer).

### Usage in a custom class {#logging-writers-usage}

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
<?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');
    }
  }
}

```

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
<?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');
    }
  }
}

```

One or more log writers for this class are configured in the file
[`ext_localconf.php`](../../../ExtensionArchitecture/FileStructure/ExtLocalconf.md#file-extension-ext-localconf-php):

**EXT:my_extension/ext_localconf.php**

```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',
    ],
  ],
];

```

## Examples {#logging-writers-examples}

Working examples of the usage of different Log writers can be found in the
extension [`t3docs/examples`](https://packagist.org/packages/t3docs/examples).
