Feature: #100926 - Introduce RotatingFileWriter for log rotation

See forge#100926

Description

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 has been implemented, following the "copytruncate" approach: when rotating files, the currently opened log file is copied (e.g. to typo3_[hash].log.20230616094812) and the original log file is emptied. This saves the hassle with properly closing and re-creating open file handles.

A new file writer \TYPO3\CMS\Core\Log\Writer\RotatingFileWriter has been added, which extends the already existing \TYPO3\CMS\Core\Log\Writer\FileWriter class. The RotatingFileWriter accepts all options of FileWriter in addition of the following:

  • interval - how often logs should be rotated, can be any of

    • daily or \TYPO3\CMS\Core\Log\Writer\Enum\Interval::DAILY (default)

    • weekly or \TYPO3\CMS\Core\Log\Writer\Enum\Interval::WEEKLY

    • monthly or \TYPO3\CMS\Core\Log\Writer\Enum\Interval::MONTHLY

    • yearly or \TYPO3\CMS\Core\Log\Writer\Enum\Interval::YEARLY

  • maxFiles - how many files should be retained (by default 5 files, 0 never deletes any file)

The RotatingFileWriter is configured like any other log writer.

Note

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

Example

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

system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['LOG']['TYPO3']['CMS']['Core']['Resource']['ResourceStorage']['writerConfiguration'][\Psr\Log\LogLevel::ERROR] = [
    \TYPO3\CMS\Core\Log\Writer\RotatingFileWriter::class => [
        'interval' => \TYPO3\CMS\Core\Log\Writer\Enum\Interval::DAILY,
        'maxFiles' => 5,
    ],
    \TYPO3\CMS\Core\Log\Writer\DatabaseWriter::class => [], // this is part of the default configuration
];

The following example introduces log rotation for the "deprecation" log file.

system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['LOG']['TYPO3']['CMS']['deprecations']['writerConfiguration'][\Psr\Log\LogLevel::NOTICE] = [
    \TYPO3\CMS\Core\Log\Writer\RotatingFileWriter::class => [
        'logFileInfix' => 'deprecations',
        'interval' => \TYPO3\CMS\Core\Log\Writer\Enum\Interval::WEEKLY,
        'maxFiles' => 4,
        'disabled' => false,
    ],
    \TYPO3\CMS\Core\Log\Writer\DatabaseWriter::class => [], // this is part of the default configuration
];

Impact

When configured, log files may be rotated before writing a new log entry, depending on the configured interval, where Interval::DAILY is the default. When rotating, the log files are suffixed with a rotation incremental value.

Example:

Directory listing of var/log with rotated logs
$ ls -1 var/log
typo3_[hash].log
typo3_[hash].log.20230613065902
typo3_[hash].log.20230614084723
typo3_[hash].log.20230615084756
typo3_[hash].log.20230616094812

If maxFiles is configured with a value greater than 0, any exceeding log file is removed.