ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
RotatingFileHandler.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the Monolog package.
5  *
6  * (c) Jordi Boggiano <j.boggiano@seld.be>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11 
12 namespace Monolog\Handler;
13 
14 use Monolog\Logger;
15 
26 {
27  const FILE_PER_DAY = 'Y-m-d';
28  const FILE_PER_MONTH = 'Y-m';
29  const FILE_PER_YEAR = 'Y';
30 
31  protected $filename;
32  protected $maxFiles;
33  protected $mustRotate;
34  protected $nextRotation;
35  protected $filenameFormat;
36  protected $dateFormat;
37 
46  public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
47  {
48  $this->filename = $filename;
49  $this->maxFiles = (int) $maxFiles;
50  $this->nextRotation = new \DateTime('tomorrow');
51  $this->filenameFormat = '{filename}-{date}';
52  $this->dateFormat = 'Y-m-d';
53 
54  parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
55  }
56 
60  public function close()
61  {
62  parent::close();
63 
64  if (true === $this->mustRotate) {
65  $this->rotate();
66  }
67  }
68 
72  public function reset()
73  {
74  parent::reset();
75 
76  if (true === $this->mustRotate) {
77  $this->rotate();
78  }
79  }
80 
82  {
83  if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
84  trigger_error(
85  'Invalid date format - format must be one of '.
86  'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '.
87  'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the '.
88  'date formats using slashes, underscores and/or dots instead of dashes.',
89  E_USER_DEPRECATED
90  );
91  }
92  if (substr_count($filenameFormat, '{date}') === 0) {
93  trigger_error(
94  'Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.',
95  E_USER_DEPRECATED
96  );
97  }
98  $this->filenameFormat = $filenameFormat;
99  $this->dateFormat = $dateFormat;
100  $this->url = $this->getTimedFilename();
101  $this->close();
102  }
103 
107  protected function write(array $record)
108  {
109  // on the first record written, if the log is new, we should rotate (once per day)
110  if (null === $this->mustRotate) {
111  $this->mustRotate = !file_exists($this->url);
112  }
113 
114  if ($this->nextRotation < $record['datetime']) {
115  $this->mustRotate = true;
116  $this->close();
117  }
118 
119  parent::write($record);
120  }
121 
125  protected function rotate()
126  {
127  // update filename
128  $this->url = $this->getTimedFilename();
129  $this->nextRotation = new \DateTime('tomorrow');
130 
131  // skip GC of old logs if files are unlimited
132  if (0 === $this->maxFiles) {
133  return;
134  }
135 
136  $logFiles = glob($this->getGlobPattern());
137  if ($this->maxFiles >= count($logFiles)) {
138  // no files to remove
139  return;
140  }
141 
142  // Sorting the files by name to remove the older ones
143  usort($logFiles, function ($a, $b) {
144  return strcmp($b, $a);
145  });
146 
147  foreach (array_slice($logFiles, $this->maxFiles) as $file) {
148  if (is_writable($file)) {
149  // suppress errors here as unlink() might fail if two processes
150  // are cleaning up/rotating at the same time
151  set_error_handler(function ($errno, $errstr, $errfile, $errline) {});
152  unlink($file);
153  restore_error_handler();
154  }
155  }
156 
157  $this->mustRotate = false;
158  }
159 
160  protected function getTimedFilename()
161  {
162  $fileInfo = pathinfo($this->filename);
163  $timedFilename = str_replace(
164  array('{filename}', '{date}'),
165  array($fileInfo['filename'], date($this->dateFormat)),
166  $fileInfo['dirname'] . '/' . $this->filenameFormat
167  );
168 
169  if (!empty($fileInfo['extension'])) {
170  $timedFilename .= '.'.$fileInfo['extension'];
171  }
172 
173  return $timedFilename;
174  }
175 
176  protected function getGlobPattern()
177  {
178  $fileInfo = pathinfo($this->filename);
179  $glob = str_replace(
180  array('{filename}', '{date}'),
181  array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'),
182  $fileInfo['dirname'] . '/' . $this->filenameFormat
183  );
184  if (!empty($fileInfo['extension'])) {
185  $glob .= '.'.$fileInfo['extension'];
186  }
187 
188  return $glob;
189  }
190 }
const DEBUG
Detailed debug information.
Definition: Logger.php:33
Stores logs to files that are rotated every day and a limited number of files are kept...
__construct($filename, $maxFiles=0, $level=Logger::DEBUG, $bubble=true, $filePermission=null, $useLocking=false)
Stores to any stream resource.
setFilenameFormat($filenameFormat, $dateFormat)