parent
b384c11837
commit
157e0d8dd0
@ -1,3 +1,3 @@
|
||||
# XXX
|
||||
# PhpExtendedMonolog
|
||||
|
||||
XXX
|
||||
Some extensions for [Monolog](https://github.com/Seldaek/monolog)
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ExtendedMonolog;
|
||||
|
||||
use jrosset\ExceptionHelper\ExceptionHelper;
|
||||
use Monolog\Logger;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* A logger with method for managing exception directly
|
||||
*/
|
||||
class ExceptionLogger extends Logger implements ExceptionLoggerInterface {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function exception (int $level, Throwable $exception, array $context = []): void {
|
||||
$this->addRecord(
|
||||
$level,
|
||||
ExceptionHelper::toString($exception, false),
|
||||
array_merge(
|
||||
[
|
||||
'exception' => $exception,
|
||||
],
|
||||
$context
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ExtendedMonolog;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Describe a logger interface with method for managing exception directly
|
||||
*/
|
||||
interface ExceptionLoggerInterface extends LoggerInterface {
|
||||
/**
|
||||
* Adds a log record about an exception
|
||||
*
|
||||
* @param int $level The logging level (a Monolog or RFC 5424 level)
|
||||
* @param Throwable $exception The exception
|
||||
* @param array $context The log context
|
||||
*/
|
||||
public function exception (int $level, Throwable $exception, array $context = []): void;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ExtendedMonolog;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeImmutable;
|
||||
use DirectoryIterator;
|
||||
use jrosset\LastErrorException\LastErrorException;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* A handler for storing log in a directory: one file per day, with an auto-clean mechanism
|
||||
*
|
||||
* The default formatter is {@see LogFileFormatter}
|
||||
*/
|
||||
class LogDirectoryHandler extends StreamHandler {
|
||||
/**
|
||||
* Initialization
|
||||
*
|
||||
* @param string $dirPath The log directory path
|
||||
* @param int $historyNumberOfDays The maximum number of history files to keep (in number of days)
|
||||
*
|
||||
* @throws Throwable If an error occurs
|
||||
*/
|
||||
public function __construct (string $dirPath, int $historyNumberOfDays = 30) {
|
||||
$dirPath = realpath($dirPath) . DIRECTORY_SEPARATOR;
|
||||
$this->normalizeDirectory($dirPath, $historyNumberOfDays);
|
||||
|
||||
parent::__construct(
|
||||
$dirPath . date('Y-m-d') . '.log',
|
||||
Logger::WARNING
|
||||
);
|
||||
$this->setFormatter(new LogFileFormatter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a directory: create if missing and clear old files
|
||||
*
|
||||
* @param string $dirPath The directory path
|
||||
* @param int $historyNumberOfDays The maximum number of history files to keep (in number of days)
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Throwable If an error occurs
|
||||
*/
|
||||
private function normalizeDirectory (string $dirPath, int $historyNumberOfDays = 30): void {
|
||||
if (!file_exists($dirPath) || !is_dir($dirPath)) {
|
||||
error_clear_last();
|
||||
if (!mkdir($dirPath, 0755, true)) {
|
||||
throw new RuntimeException('Failed to create log directory: ' . $dirPath, 0, LastErrorException::createFromLastError());
|
||||
}
|
||||
}
|
||||
|
||||
$dateLimit = (new DateTimeImmutable('now'))->sub(new DateInterval('P' . $historyNumberOfDays . 'D'));
|
||||
|
||||
$iterator = new DirectoryIterator($dirPath);
|
||||
foreach ($iterator as $fileInfo) {
|
||||
if ($fileInfo->isDot() || mb_substr($fileInfo->getFilename(), 0, 1) === '.') {
|
||||
continue;
|
||||
}
|
||||
if (!$fileInfo->isFile()) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/^(?<date>\\d{4}-\\d{2}-\\d{2})(?:[_-].*)?\.log$/i', $fileInfo->getFilename(), $match) !== 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$date = DateTimeImmutable::createFromFormat('Y-m-d', $match['date']);
|
||||
if ($date >= $dateLimit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unlink($fileInfo->getPathname());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\ExtendedMonolog;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
|
||||
/**
|
||||
* A formater for log files
|
||||
*/
|
||||
class LogFileFormatter extends LineFormatter {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct () {
|
||||
parent::__construct(
|
||||
'[%datetime%] %level_name% : %message%' . PHP_EOL . '%context%' . PHP_EOL . '%extra%',
|
||||
'H:i:s',
|
||||
true,
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function format (array $record): string {
|
||||
return preg_replace('/((?<!\\\\)\\\\[rn])+$/', PHP_EOL, parent::format($record));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue