commands/FileOutput.php
<?php
/**
* @see http://www.yiiframework.com/
*
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiicod\cron\commands;
use yii\base\InvalidConfigException;
/**
* FileOutput records log messages in a file.
*/
class FileOutput
{
/**
* @var string log file path or path alias. If not set, it will use the "@runtime/logs/app.log" file.
* The directory containing the log files will be automatically created if not existing.
*/
public $logFile;
/**
* @var int maximum log file size, in kilo-bytes. Defaults to 10240, meaning 10MB.
*/
public $maxFileSize = 10240; // in KB
/**
* @var int number of log files used for rotation. Defaults to 5.
*/
public $maxLogFiles = 5;
/**
* @var bool Whether to rotate log files by copy and truncate in contrast to rotation by
* renaming files. Defaults to `true` to be more compatible with log tailers and is windows
* systems which do not play well with rename on open files. Rotation by renaming however is
* a bit faster.
*
* The problem with windows systems where the [rename()](http://www.php.net/manual/en/function.rename.php)
* function does not work with files that are opened by some process is described in a
* [comment by Martin Pelletier](http://www.php.net/manual/en/function.rename.php#102274) in
* the PHP documentation. By setting rotateByCopy to `true` you can work
* around this problem.
*/
public $rotateByCopy = true;
/**
* Initializes the route.
* This method is invoked after the route is created by the route manager.
*/
public function __construct($logFile)
{
$this->logFile = $logFile;
}
/**
* Writes log messages to a file.
*
* @throws InvalidConfigException if unable to open the log file for writing
*/
public function stdout($text)
{
/* Disable empty output */
if (empty($text)) {
return;
}
$text = sprintf("\n---------------------------------\n%s Stack output:\n---------------------------------\n%s", date('Y-m-d H:i:s'), $text);
if (false === ($fp = @fopen($this->logFile, 'a'))) {
throw new InvalidConfigException("Unable to append to log file: {$this->logFile}");
}
@flock($fp, LOCK_EX);
// clear stat cache to ensure getting the real current file size and not a cached one
// this may result in rotating twice when cached file size is used on subsequent calls
clearstatcache();
if (@filesize($this->logFile) > $this->maxFileSize * 1024) {
$this->rotateFiles();
@flock($fp, LOCK_UN);
@fclose($fp);
@file_put_contents($this->logFile, $text, FILE_APPEND | LOCK_EX);
} else {
@fwrite($fp, $text);
@flock($fp, LOCK_UN);
@fclose($fp);
}
}
/**
* Rotates log files.
*/
protected function rotateFiles()
{
$file = $this->logFile;
for ($i = $this->maxLogFiles; $i >= 0; --$i) {
// $i == 0 is the original log file
$rotateFile = $file . (0 === $i ? '' : '.' . $i);
if (is_file($rotateFile)) {
// suppress errors because it's possible multiple processes enter into this section
if ($i === $this->maxLogFiles) {
@unlink($rotateFile);
} else {
if ($this->rotateByCopy) {
@copy($rotateFile, $file . '.' . ($i + 1));
if ($fp = @fopen($rotateFile, 'a')) {
@ftruncate($fp, 0);
@fclose($fp);
}
} else {
@rename($rotateFile, $file . '.' . ($i + 1));
}
}
}
}
}
}