Compare commits

...

4 Commits
1.x ... master

@ -7,18 +7,19 @@
"config": {
"sort-packages": true
},
"extra": {
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
"dev-master": "2.x-dev"
}
},
"minimum-stability": "stable",
"require": {
"php": "^7.4 || ^8.0",
"jrosset/exceptionhelper": "^1.0",
"jrosset/lasterrorexception": "^1.0",
"monolog/monolog": "^2.9"
"require": {
"php": "^8.1",
"ext-mbstring": "*",
"jrosset/exceptionhelper": "^1.1",
"jrosset/lasterrorexception": "^1.1",
"monolog/monolog": "^3.8"
},
"autoload": {
"psr-4": {

@ -1,8 +1,10 @@
<?php
/** @noinspection PhpDocFinalChecksInspection */
namespace jrosset\ExtendedMonolog;
use jrosset\ExceptionHelper\ExceptionHelper;
use Monolog\Level;
use Monolog\Logger;
use Throwable;
@ -13,10 +15,10 @@ class ExceptionLogger extends Logger implements ExceptionLoggerInterface {
/**
* @inheritDoc
*/
public function exception (int $level, Throwable $exception, array $context = []): void {
public function exception (Level|int $level, Throwable $exception, array $context = []): void {
$this->addRecord(
$level,
ExceptionHelper::toString($exception, false),
ExceptionHelper::toString($exception, false) . PHP_EOL,
array_merge(
[
'exception' => $exception,

@ -2,6 +2,7 @@
namespace jrosset\ExtendedMonolog;
use Monolog\Level;
use Psr\Log\LoggerInterface;
use Throwable;
@ -12,9 +13,9 @@ interface ExceptionLoggerInterface extends LoggerInterface {
/**
* Adds a log record about an exception
*
* @param int $level The logging level (a Monolog or RFC 5424 level)
* @param Level|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;
public function exception (Level|int $level, Throwable $exception, array $context = []): void;
}

@ -7,7 +7,7 @@ use DateTimeImmutable;
use DirectoryIterator;
use jrosset\LastErrorException\LastErrorException;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Level;
use RuntimeException;
use Throwable;
@ -20,28 +20,30 @@ class LogDirectoryHandler extends StreamHandler {
/**
* Initialization
*
* @param string $dirPath The log directory path
* @param int|string $level The minimum logging level at which this handler will be triggered
* @param int $historyNumberOfDays The maximum number of history files to keep (in number of days)
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
* @param string $dirPath The log directory path
* @param Level $level The minimum logging level at which this handler will be triggered
* @param int $historyNumberOfDays The maximum number of history files to keep (in number of days)
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
* @param string|null $filenamePrefix The filename prefix
*
* @throws Throwable If an error occurs
*/
public function __construct (
string $dirPath,
$level = Logger::DEBUG,
int $historyNumberOfDays = 30,
bool $bubble = true,
?int $filePermission = null,
bool $useLocking = false
string $dirPath,
Level $level = Level::Debug,
int $historyNumberOfDays = 30,
bool $bubble = true,
?int $filePermission = null,
bool $useLocking = false,
?string $filenamePrefix = null
) {
$dirPath = $dirPath . DIRECTORY_SEPARATOR;
$this->normalizeDirectory($dirPath, $historyNumberOfDays);
$this->normalizeDirectory($dirPath, $filenamePrefix, $historyNumberOfDays);
parent::__construct(
$dirPath . date('Y-m-d') . '.log',
$dirPath . ($filenamePrefix ?? '') . date('Y-m-d') . '.log',
$level,
$bubble,
$filePermission,
@ -53,14 +55,15 @@ class LogDirectoryHandler extends StreamHandler {
/**
* 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)
* @param string $dirPath The directory path
* @param string|null $filenamePrefix The filename prefix
* @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 {
protected final function normalizeDirectory (string $dirPath, ?string $filenamePrefix, int $historyNumberOfDays = 30): void {
if (!file_exists($dirPath) || !is_dir($dirPath)) {
error_clear_last();
if (!mkdir($dirPath, 0755, true)) {
@ -78,7 +81,13 @@ class LogDirectoryHandler extends StreamHandler {
if (!$fileInfo->isFile()) {
continue;
}
if (preg_match('/^(?<date>\\d{4}-\\d{2}-\\d{2})(?:[_-].*)?\.log$/i', $fileInfo->getFilename(), $match) !== 1) {
if (
preg_match(
'/^' . preg_quote($filenamePrefix ?? '', '/') . '(?<date>\\d{4}-\\d{2}-\\d{2})(?:[_-].*)?\.log$/i',
$fileInfo->getFilename(),
$match
) !== 1
) {
continue;
}

@ -3,6 +3,7 @@
namespace jrosset\ExtendedMonolog;
use Monolog\Formatter\LineFormatter;
use Monolog\LogRecord;
/**
* A formater for log files
@ -24,7 +25,33 @@ class LogFileFormatter extends LineFormatter {
/**
* @inheritDoc
*/
public function format (array $record): string {
return preg_replace('/((?<!\\\\)\\\\[rn])+$/', PHP_EOL, parent::format($record));
public function format (LogRecord $record): string {
//region Get then remove newlines at record message end (*before* the formatting)
$messageEndNewlines = '';
$record = $record->with(
message: preg_replace_callback(
'/(?:(?<!\\\\)(?:\\\\[rn]|\\r|\\n))+$/',
function (array $match) use (&$messageEndNewlines): string {
$messageEndNewlines = $match[0];
return '';
},
$this->normalize($record->message)
)
);
//endregion
//region Format the record
$output = parent::format($record);
//endregion
//region Remove newlines at end (introduced by context, extra or record message itself)
$output = preg_replace('/(?:(?<!\\\\)(?:\\\\[rn]|\\r|\\n))+$/', '', $output);
//endregion
//region Re-add the newlines of record message end
$output .= $messageEndNewlines;
//endregion
//region Then finally, replace manual "\r" or "\n" by theirs equivalent
return preg_replace(
'/(?:(?<!\\\\)\\\\[rn])+/', PHP_EOL, $output
);
//endregion
}
}

@ -4,26 +4,34 @@ require_once __DIR__ . '/../vendor/autoload.php';
use jrosset\ExtendedMonolog\ExceptionLogger;
use jrosset\ExtendedMonolog\LogDirectoryHandler;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Level;
/** @noinspection PhpUnhandledExceptionInspection */
$logger = new ExceptionLogger(
'test',
[
new StreamHandler(STDOUT),
(new StreamHandler(STDOUT))
->setFormatter(
new LineFormatter(
'[%datetime%] %level_name% : %message%',
'Y-m-d H:i:s',
true
)
),
new LogDirectoryHandler(__DIR__ . '/logs/'),
]
);
try {
$logger->info('START');
$logger->info('======= test =======' . PHP_EOL . 'START' . PHP_EOL);
throw new RuntimeException('An unexpected error occurs');
/** @noinspection PhpUnreachableStatementInspection */
$logger->info('END');
$logger->info('END' . PHP_EOL);
}
catch (Throwable $exception) {
$logger->exception(Logger::ERROR, $exception);
$logger->exception(Level::Error, $exception);
}
Loading…
Cancel
Save