Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- New #109: Add context provider (@vjik)
- Chg #109: Deprecate `Logger` methods `setTraceLevel()` and `setExcludedTracePaths()` in favor of context provider
usage (@vjik)
- New #111: Add `DateTime` and `DateTimeImmutable` support as time in log context (@vjik)

## 2.0.0 May 22, 2022

Expand Down
37 changes: 28 additions & 9 deletions src/Message/Formatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
namespace Yiisoft\Log\Message;

use DateTime;
use DateTimeInterface;
use Exception;
use LogicException;
use RuntimeException;
use Yiisoft\Log\Message;
use Yiisoft\VarDumper\VarDumper;
Expand All @@ -14,7 +17,6 @@
use function is_string;
use function is_object;
use function method_exists;
use function microtime;
use function sprintf;

/**
Expand Down Expand Up @@ -140,16 +142,33 @@ private function defaultFormat(Message $message, array $commonContext): string
*/
private function getTime(Message $message): string
{
/** @psalm-suppress PossiblyInvalidCast */
$timestamp = (string) $message->context('time', microtime(true));
$time = $message->context('time');

$format = match (true) {
str_contains($timestamp, '.') => 'U.u',
str_contains($timestamp, ',') => 'U,u',
default => 'U',
};
if (is_int($time) || is_float($time)) {
try {
$date = new DateTime('@' . $time);
} catch (Exception $e) {
throw new LogicException('Invalid time value in log context: ' . $time . '.', previous: $e);
}
} elseif (is_string($time)) {
$format = match (true) {
str_contains($time, '.') => 'U.u',
str_contains($time, ',') => 'U,u',
default => 'U',
};
$date = DateTime::createFromFormat($format, $time);
if ($date === false) {
throw new LogicException('Invalid time value in log context: "' . $time . '".');
}
} elseif ($time instanceof DateTimeInterface) {
$date = $time;
} elseif ($time === null) {
$date = new DateTime();
} else {
throw new LogicException('Invalid time value in log context. Got "' . get_debug_type($time) . '".');
}

return DateTime::createFromFormat($format, $timestamp)->format($this->timestampFormat);
return $date->format($this->timestampFormat);
}

/**
Expand Down
54 changes: 54 additions & 0 deletions tests/Message/FormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Yiisoft\Log\Tests\Message;

use DateTime;
use Exception;
use LogicException;
use PHPUnit\Framework\TestCase;
use Psr\Log\LogLevel;
use RuntimeException;
Expand Down Expand Up @@ -262,4 +264,56 @@ public function testFormatMessageThrowExceptionForPrefixCallableReturnNotString(
$this->expectException(RuntimeException::class);
$this->formatter->format(new Message(LogLevel::INFO, 'test', ['foo' => 'bar']), []);
}

public static function dataTime(): array
{
return [
'int' => ['1970-01-01 00:00:01.000000', 1],
'float' => ['1970-01-01 00:00:01.230000', 1.23],
'string-int' => ['1970-01-01 00:00:23.000000', '23'],
'string-float' => ['1970-01-01 00:00:23.600000', '23.6'],
'string-float-comma' => ['1970-01-01 00:00:23.600000', '23,6'],
'datetime' => ['1970-01-01 00:00:23.00000', new DateTime('@23')],
];
}

/**
* @dataProvider dataTime
*/
public function testTime(string $expected, mixed $value): void
{
$formatter = new Formatter();
$result = $formatter->format(new Message(LogLevel::INFO, 'test', ['time' => $value]), []);
$this->assertStringStartsWith($expected, $result);
}

public function testTimeWithInvalidFloat(): void
{
$formatter = new Formatter();
$message = new Message(LogLevel::INFO, 'test', ['time' => 1234231.9135123512]);

$this->expectException(LogicException::class);
$this->expectExceptionMessage('Invalid time value in log context: 1234231.9135124.');
$formatter->format($message, []);
}

public function testTimeWithInvalidString(): void
{
$formatter = new Formatter();
$message = new Message(LogLevel::INFO, 'test', ['time' => 'hello']);

$this->expectException(LogicException::class);
$this->expectExceptionMessage('Invalid time value in log context: "hello".');
$formatter->format($message, []);
}

public function testTimeWithInvalidType(): void
{
$formatter = new Formatter();
$message = new Message(LogLevel::INFO, 'test', ['time' => []]);

$this->expectException(LogicException::class);
$this->expectExceptionMessage('Invalid time value in log context. Got "array".');
$formatter->format($message, []);
}
}