‪TYPO3CMS  ‪main
RotatingFileWriter.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
27 
33 {
34  private const ‪ROTATION_DATE_FORMAT = 'YmdHis';
35 
36  private ‪Interval ‪$interval = Interval::DAILY;
37  private int ‪$maxFiles = 5;
38  private \DateTimeImmutable ‪$lastRotation;
39  private \DateTimeImmutable ‪$nextRotation;
40 
41  public function ‪__construct(array $options = [])
42  {
43  parent::__construct($options);
44  }
45 
46  public function ‪setLogFile(string $relativeLogFile): self
47  {
48  parent::setLogFile($relativeLogFile);
49 
51 
52  return $this;
53  }
54 
58  protected function ‪setInterval(string|‪Interval ‪$interval): void
59  {
60  if (is_string(‪$interval)) {
61  // String support is required for use in system/settings.php
62  $this->interval = Interval::tryFrom(‪$interval) ?? Interval::DAILY;
63  } else {
64  $this->interval = ‪$interval;
65  }
66  }
67 
71  protected function ‪setMaxFiles(int ‪$maxFiles): void
72  {
73  $this->maxFiles = max(0, ‪$maxFiles);
74  }
75 
77  {
78  if ($this->‪needsRotation()) {
79  $lockFactory = GeneralUtility::makeInstance(LockFactory::class);
80  try {
81  $lock = $lockFactory->createLocker('rotate-' . $this->logFile);
82  if ($lock->acquire()) {
84  // check again if rotation is still needed (could have happened in the meantime)
85  if ($this->‪needsRotation()) {
86  $this->‪rotate();
87  }
88  }
89  $lock->release();
91  }
92  }
93  return parent::writeLog(‪$record);
94  }
95 
103  protected function ‪rotate(): void
104  {
105  $rotationSuffix = date(self::ROTATION_DATE_FORMAT);
106 
107  // copytruncate: Rotate the currently used log file
108  copy($this->logFile, $this->logFile . '.' . $rotationSuffix);
109  ftruncate(self::$logFileHandles[$this->logFile], 0);
110 
111  $rotatedLogFiles = glob($this->logFile . '.*');
112  rsort($rotatedLogFiles, SORT_NATURAL);
113 
114  // Remove any excess files
115  $excessFiles = array_slice($rotatedLogFiles, $this->maxFiles);
116  foreach ($excessFiles as $excessFile) {
117  unlink($excessFile);
118  }
119 
120  $this->‪updateRuntimeRotationState(new \DateTimeImmutable());
121  }
122 
123  protected function ‪getLastRotation(): \DateTimeImmutable
124  {
125  // Rotate already rotated files again
126  $rotatedLogFiles = glob($this->logFile . '.*');
127 
128  if ($rotatedLogFiles !== []) {
129  // Sort rotated files to handle the newest one first
130  rsort($rotatedLogFiles, SORT_NATURAL);
131  $newestLog = current($rotatedLogFiles);
132 
133  $rotationDelimiterPosition = strrpos($newestLog, '.');
134  $timestamp = substr($newestLog, $rotationDelimiterPosition + 1);
135 
136  $latestRotationDateTime = \DateTimeImmutable::createFromFormat(self::ROTATION_DATE_FORMAT, $timestamp);
137  if ($latestRotationDateTime instanceof \DateTimeImmutable) {
138  return $latestRotationDateTime;
139  }
140  }
141 
142  return new \DateTimeImmutable('@0');
143  }
144 
145  protected function ‪determineNextRotation(): \DateTimeImmutable
146  {
147  return $this->lastRotation->add(new \DateInterval($this->interval->getDateInterval()));
148  }
149 
158  protected function ‪needsRotation(): bool
159  {
160  return ($this->nextRotation <= new \DateTimeImmutable() || $this->lastRotation->getTimestamp() === 0) && filesize($this->logFile) > 0;
161  }
162 
163  protected function ‪updateRuntimeRotationState(\DateTimeImmutable ‪$lastRotation): void
164  {
165  $this->lastRotation = ‪$lastRotation;
166  $this->nextRotation = $this->‪determineNextRotation();
167  }
168 }
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\rotate
‪rotate()
Definition: RotatingFileWriter.php:103
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\setInterval
‪setInterval(string|Interval $interval)
Definition: RotatingFileWriter.php:58
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\ROTATION_DATE_FORMAT
‪const ROTATION_DATE_FORMAT
Definition: RotatingFileWriter.php:34
‪TYPO3\CMS\Core\Locking\Exception\LockAcquireWouldBlockException
Definition: LockAcquireWouldBlockException.php:21
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\needsRotation
‪needsRotation()
Definition: RotatingFileWriter.php:158
‪TYPO3\CMS\Core\Log\LogRecord
Definition: LogRecord.php:24
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\writeLog
‪writeLog(LogRecord $record)
Definition: RotatingFileWriter.php:76
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\updateRuntimeRotationState
‪updateRuntimeRotationState(\DateTimeImmutable $lastRotation)
Definition: RotatingFileWriter.php:163
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\$maxFiles
‪int $maxFiles
Definition: RotatingFileWriter.php:37
‪TYPO3\CMS\Core\Log\Writer\FileWriter
Definition: FileWriter.php:29
‪TYPO3\CMS\Core\Locking\Exception\LockAcquireException
Definition: LockAcquireException.php:23
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\setMaxFiles
‪setMaxFiles(int $maxFiles)
Definition: RotatingFileWriter.php:71
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter
Definition: RotatingFileWriter.php:33
‪TYPO3\CMS\Core\Locking\Exception\LockCreateException
Definition: LockCreateException.php:23
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\__construct
‪__construct(array $options=[])
Definition: RotatingFileWriter.php:41
‪TYPO3\CMS\Core\Log\Writer
Definition: AbstractWriter.php:16
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\determineNextRotation
‪determineNextRotation()
Definition: RotatingFileWriter.php:145
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\$lastRotation
‪DateTimeImmutable $lastRotation
Definition: RotatingFileWriter.php:38
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\$interval
‪Interval $interval
Definition: RotatingFileWriter.php:36
‪TYPO3\CMS\Core\Locking\LockFactory
Definition: LockFactory.php:27
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\$nextRotation
‪DateTimeImmutable $nextRotation
Definition: RotatingFileWriter.php:39
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\getLastRotation
‪getLastRotation()
Definition: RotatingFileWriter.php:123
‪TYPO3\CMS\Core\Log\Writer\Enum\Interval
‪Interval
Definition: Interval.php:21
‪TYPO3\CMS\Core\Log\Writer\RotatingFileWriter\setLogFile
‪setLogFile(string $relativeLogFile)
Definition: RotatingFileWriter.php:46