Skip to content

Commit

Permalink
New Logfile tasks for Robo (#994)
Browse files Browse the repository at this point in the history
  • Loading branch information
christingruber authored and andrzejkupczyk committed Oct 20, 2020
1 parent 5747a6c commit 184aa8b
Show file tree
Hide file tree
Showing 10 changed files with 550 additions and 0 deletions.
32 changes: 32 additions & 0 deletions docs/tasks/Logfile.md
@@ -0,0 +1,32 @@
# Logfile Tasks

## Rotate logfile


Rotate and purge obsolete logs.

``` php
<?php
$this->taskRotateLog(['logfile.log'])->run();
// as shortcut
$this->_rotateLog(['logfile.log']);
?>
```

* `chmod(int $chmod)` Changes file mode to octal $chmod, default is disabled.
* `keep(int $keep)` Logfiles to keep, default is 3.

## Truncate logfile


Truncates or create empty logfile if logfile not exists.

``` php
<?php
$this->taskTruncateLog(['logfile.log'])->run();
// as shortcut
$this->_rotateTruncate(['logfile.log']);
?>
```

* `chmod(int $chmod)` Changes file mode to octal $chmod, default is disabled.
2 changes: 2 additions & 0 deletions src/LoadAllTasks.php
Expand Up @@ -15,6 +15,7 @@ trait LoadAllTasks
use Task\File\Tasks;
use Task\Archive\Tasks;
use Task\Vcs\Tasks;
use Task\Logfile\Tasks;

// package managers
use Task\Composer\Tasks;
Expand All @@ -37,4 +38,5 @@ trait LoadAllTasks
use Task\Base\Shortcuts;
use Task\Filesystem\Shortcuts;
use Task\Vcs\Shortcuts;
use Task\Logfile\Shortcuts;
}
47 changes: 47 additions & 0 deletions src/Task/Logfile/BaseLogfile.php
@@ -0,0 +1,47 @@
<?php

namespace Robo\Task\Logfile;

use Robo\Task\BaseTask;
use Symfony\Component\Filesystem\Filesystem;

abstract class BaseLogfile extends BaseTask
{
/**
* @var string|string[] Array with log files.
*/
protected $logfiles = [];

/**
* @var \Symfony\Component\Filesystem\Filesystem
*/
protected $filesystem;

/**
* @var int|bool Octal file mode for log files like 0600.
*/
protected $chmod = false;

/**
* @param string|string[] $logfiles
*/
public function __construct($logfiles)
{
is_array($logfiles)
? $this->logfiles = $logfiles
: $this->logfiles[] = $logfiles;

$this->filesystem = new Filesystem();
}

/**
* @param int $chmod
* @return $this
*/
public function chmod(int $chmod)
{
$this->chmod = $chmod;

return $this;
}
}
163 changes: 163 additions & 0 deletions src/Task/Logfile/RotateLog.php
@@ -0,0 +1,163 @@
<?php

namespace Robo\Task\Logfile;

use Robo\Result;

/**
* Rotates a log (or any other) file
*
* ``` php
* <?php
* $this->taskRotateLog(['logfile.log'])->run();
* // or use shortcut
* $this->_rotateLog(['logfile.log']);
*
* ?>
* ```
*/
class RotateLog extends BaseLogfile
{
/**
* @var int Number of copies to keep, default is 3.
*/
protected $keep = 3;

/**
* @var string|string[] Logfile to rotate.
*/
private $logfile;

/**
* @param string|string[] $logfiles
*/
public function __construct($logfiles)
{
parent::__construct($logfiles);
}

/**
* @param int $keep
* @return RotateLog
* @throws \Exception
*/
public function keep(int $keep): self
{
if ($keep < 1) {
throw new \InvalidArgumentException(
'Keep should be greater than one, to truncate a logfile use taskTruncateLog($logfile).'
);
}

$this->keep = $keep;

return $this;
}

/**
* {@inheritdoc}
*/
public function run(): Result
{
foreach ($this->logfiles as $logfile) {
$this->loadLogfile($logfile)
->process();
}

return Result::success($this);
}

/**
* @param string $logfile
* @return RotateLog
*/
private function loadLogfile(string $logfile): self
{
$this->logfile = new \SplFileInfo($logfile);

return $this;
}

/**
* @return RotateLog
*/
private function process(): self
{
$rotation = 0;
foreach (scandir($this->logfile->getPath(), SCANDIR_SORT_DESCENDING) as $origin) {
$origin = new \SplFileInfo($this->logfile->getPath().'/'.$origin);
if ($origin->isFile() && $this->isLogfile($origin)) {
if ($this->version($origin) < $this->keep) {
$rotated = $this->rotate($origin);
$this->printTaskInfo(
'Rotated from {origin} to {rotated}',
[
'origin' => $origin->getPathname(),
'rotated' => $rotated
]
);
} elseif ($this->version($origin) > $this->keep) {
$this->filesystem->remove($origin->getPathname());
}
}

$rotation++;
}

$this->filesystem->dumpFile($this->logfile->getPathname(), false);
if ($this->chmod) {
$this->filesystem->chmod($this->logfile->getPathname(), $this->chmod);
}

return $this;
}

/**
* @param \SplFileInfo $origin
* @return bool
*/
private function isLogfile(\SplFileInfo $origin): bool
{
if (substr($origin->getFilename(), 0, strlen($this->logfile->getFilename())) != $this->logfile->getFilename()) {
return false;
}

return true;
}

/**
* @param \SplFileInfo $origin
* @return int
*/
private function version(\SplFileInfo $origin): int
{
return $origin->getExtension() === $this->logfile->getExtension()
? 0
: $origin->getExtension();
}

/**
* @param \SplFileInfo $origin
* @return int
*/
private function next(\SplFileInfo $origin): int
{
return $this->version($origin) + 1;
}

/**
* @param \SplFileInfo $origin
* @return string
*/
private function rotate(\SplFileInfo $origin): string
{
$rotated = $this->logfile->getPathname().'.'.$this->next($origin);
if ($this->next($origin) === $this->keep) {
$this->filesystem->remove($rotated);
}

$this->filesystem->rename($origin->getPathname(), $rotated);

return $rotated;
}
}
28 changes: 28 additions & 0 deletions src/Task/Logfile/Shortcuts.php
@@ -0,0 +1,28 @@
<?php

namespace Robo\Task\Logfile;

use Robo\Result;

trait Shortcuts
{
/**
* @param string|string[] $logfile
*
* @return \Robo\Result
*/
protected function _rotateLog($logfile): Result
{
return $this->taskRotateLog($logfile)->run();
}

/**
* @param string|string[] $logfile
*
* @return \Robo\Result
*/
protected function _truncateLog($logfile): Result
{
return $this->taskTruncateLog($logfile)->run();
}
}
28 changes: 28 additions & 0 deletions src/Task/Logfile/Tasks.php
@@ -0,0 +1,28 @@
<?php

namespace Robo\Task\Logfile;

use Robo\Collection\CollectionBuilder;

trait Tasks
{
/**
* @param string|string[] $logfile
*
* @return \Robo\Task\Logfile\RotateLog|\Robo\Collection\CollectionBuilder
*/
protected function taskRotateLog($logfile): CollectionBuilder
{
return $this->task(RotateLog::class, $logfile);
}

/**
* @param string|string[] $logfile
*
* @return \Robo\Task\Logfile\TruncateLog|\Robo\Collection\CollectionBuilder
*/
protected function taskTruncateLog($logfile): CollectionBuilder
{
return $this->task(TruncateLog::class, $logfile);
}
}
36 changes: 36 additions & 0 deletions src/Task/Logfile/TruncateLog.php
@@ -0,0 +1,36 @@
<?php

namespace Robo\Task\Logfile;

use Robo\Result;

/**
* Truncates a log (or any other) file
*
* ``` php
* <?php
* $this->taskTruncateLog(['logfile.log'])->run();
* // or use shortcut
* $this->_truncateLog(['logfile.log']);
*
* ?>
* ```
*/
class TruncateLog extends BaseLogfile
{
/**
* {@inheritdoc}
*/
public function run(): Result
{
foreach ($this->logfiles as $logfile) {
$this->filesystem->dumpFile($logfile, false);
if ($this->chmod) {
$this->filesystem->chmod($logfile, $this->chmod);
}
$this->printTaskInfo("Truncated {logfile}", ['logfile' => $logfile]);
}

return Result::success($this);
}
}

0 comments on commit 184aa8b

Please sign in to comment.