Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Timestamp;
|
||||
use App\Framework\DateTime\Exceptions\InvalidDateTimeException;
|
||||
use App\Framework\DateTime\Exceptions\InvalidTimezoneException;
|
||||
use DateTimeImmutable;
|
||||
use Exception;
|
||||
|
||||
interface Clock
|
||||
{
|
||||
@@ -19,10 +21,10 @@ interface Clock
|
||||
/**
|
||||
* Erzeugt ein DateTimeImmutable-Objekt aus einem Zeitstempel.
|
||||
*
|
||||
* @param int $timestamp UNIX-Zeitstempel
|
||||
* @param Timestamp $timestamp Der Zeitstempel als Value Object
|
||||
* @return DateTimeImmutable
|
||||
*/
|
||||
public function fromTimestamp(int $timestamp): DateTimeImmutable;
|
||||
public function fromTimestamp(Timestamp $timestamp): DateTimeImmutable;
|
||||
|
||||
/**
|
||||
* Erzeugt ein DateTimeImmutable-Objekt aus einem String im angegebenen Format.
|
||||
@@ -41,19 +43,8 @@ interface Clock
|
||||
|
||||
public function tomorrow(): DateTimeImmutable;
|
||||
|
||||
|
||||
/**
|
||||
* Gibt den aktuellen UNIX-Zeitstempel zurück.
|
||||
*
|
||||
* @return int
|
||||
* Gibt den aktuellen Zeitstempel als Timestamp Value Object zurück.
|
||||
*/
|
||||
public function time(): int;
|
||||
|
||||
/**
|
||||
* Gibt den aktuellen Zeitstempel mit Mikrosekunden zurück.
|
||||
*
|
||||
* @param bool $asFloat Wenn true, wird ein float zurückgegeben, sonst ein Array
|
||||
* @return float|array{float, int}
|
||||
*/
|
||||
public function microtime(bool $asFloat = false): float|array;
|
||||
public function time(): Timestamp;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ final readonly class ClockInitializer
|
||||
{
|
||||
public function __construct(
|
||||
private AppConfig $config
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
|
||||
#[Initializer]
|
||||
public function __invoke(): Clock
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\DateTime\Exceptions\InvalidDateTimeException;
|
||||
|
||||
@@ -80,6 +80,7 @@ final class DateTime
|
||||
if ($e instanceof InvalidDateTimeException) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
throw new InvalidDateTimeException($dateTime, $format, $e);
|
||||
}
|
||||
}
|
||||
@@ -155,7 +156,7 @@ final class DateTime
|
||||
*/
|
||||
public static function getDefaultTimezone(): DateTimeZone
|
||||
{
|
||||
return self::$defaultTimezone ?? new DateTimeZone('Europa/Berlin');
|
||||
return self::$defaultTimezone ?? new DateTimeZone('Europe/Berlin');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use DateInvalidTimeZoneException;
|
||||
@@ -8,7 +10,7 @@ use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use DateTimeZone;
|
||||
|
||||
class DateTimeFormatter
|
||||
final readonly class DateTimeFormatter
|
||||
{
|
||||
/**
|
||||
* Standard-Zeitzone für Formatierungen
|
||||
|
||||
@@ -4,9 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use App\Framework\Exception\ExceptionContext;
|
||||
use App\Framework\Exception\FrameworkException;
|
||||
|
||||
class InvalidDateTimeException extends Exception
|
||||
class InvalidDateTimeException extends FrameworkException
|
||||
{
|
||||
public function __construct(string $dateTime, ?string $format = null, ?\Throwable $previous = null)
|
||||
{
|
||||
@@ -14,6 +15,12 @@ class InvalidDateTimeException extends Exception
|
||||
? sprintf('Konnte DateTime nicht aus "%s" mit Format "%s" erstellen', $dateTime, $format)
|
||||
: sprintf('Ungültiges DateTime-Format: "%s"', $dateTime);
|
||||
|
||||
parent::__construct($message, 0, $previous);
|
||||
$context = ExceptionContext::forOperation('datetime.parse', 'datetime')
|
||||
->withData([
|
||||
'input_datetime' => $dateTime,
|
||||
'format' => $format,
|
||||
]);
|
||||
|
||||
parent::__construct($message, $context, 0, $previous);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use App\Framework\Exception\ExceptionContext;
|
||||
use App\Framework\Exception\FrameworkException;
|
||||
|
||||
class InvalidTimezoneException extends Exception
|
||||
class InvalidTimezoneException extends FrameworkException
|
||||
{
|
||||
public function __construct(string $timezone, ?\Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf('Ungültige Zeitzone: "%s"', $timezone),
|
||||
0,
|
||||
$previous
|
||||
);
|
||||
$message = sprintf('Ungültige Zeitzone: "%s"', $timezone);
|
||||
|
||||
$context = ExceptionContext::forOperation('timezone.validate', 'datetime')
|
||||
->withData(['timezone' => $timezone]);
|
||||
|
||||
parent::__construct($message, $context, 0, $previous);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Timestamp;
|
||||
use App\Framework\DateTime\Exceptions\InvalidDateTimeException;
|
||||
use App\Framework\DateTime\Exceptions\InvalidTimezoneException;
|
||||
use DateInvalidOperationException;
|
||||
@@ -11,6 +14,7 @@ use DateTimeZone;
|
||||
final class FrozenClock implements Clock
|
||||
{
|
||||
private DateTimeImmutable $frozenTime;
|
||||
|
||||
private DateTimeZone $timezone;
|
||||
|
||||
/**
|
||||
@@ -50,9 +54,9 @@ final class FrozenClock implements Clock
|
||||
* {@inheritDoc}
|
||||
* @throws InvalidTimezoneException
|
||||
*/
|
||||
public function fromTimestamp(int $timestamp): DateTimeImmutable
|
||||
public function fromTimestamp(Timestamp $timestamp): DateTimeImmutable
|
||||
{
|
||||
return DateTime::fromTimestamp($timestamp, $this->timezone);
|
||||
return DateTime::fromTimestamp($timestamp->toTimestamp(), $this->timezone);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,6 +130,7 @@ final class FrozenClock implements Clock
|
||||
{
|
||||
$dateInterval = DateTime::createInterval($interval);
|
||||
$this->frozenTime = $this->frozenTime->add($dateInterval);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -140,23 +145,12 @@ final class FrozenClock implements Clock
|
||||
{
|
||||
$dateInterval = DateTime::createInterval($interval);
|
||||
$this->frozenTime = $this->frozenTime->sub($dateInterval);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function time(): int
|
||||
public function time(): Timestamp
|
||||
{
|
||||
return $this->now()->getTimestamp();
|
||||
}
|
||||
|
||||
public function microtime(bool $asFloat = false): float|array
|
||||
{
|
||||
$timestamp = $this->now()->getTimestamp();
|
||||
$microseconds = 0; // In FrozenClock haben wir keine Mikrosekunden-Präzision
|
||||
|
||||
if ($asFloat) {
|
||||
return (float)$timestamp;
|
||||
}
|
||||
|
||||
return [(float)$timestamp, $microseconds];
|
||||
return Timestamp::fromDateTime($this->frozenTime);
|
||||
}
|
||||
}
|
||||
|
||||
42
src/Framework/DateTime/HighResolutionClock.php
Normal file
42
src/Framework/DateTime/HighResolutionClock.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
|
||||
/**
|
||||
* Interface for high-resolution timing operations using hrtime() with Value Objects
|
||||
*
|
||||
* This interface provides monotonic, high-precision timing capabilities
|
||||
* that are perfect for performance measurements and are unaffected by
|
||||
* system clock changes. All methods return or accept Value Objects for type safety.
|
||||
*/
|
||||
interface HighResolutionClock
|
||||
{
|
||||
/**
|
||||
* Get high-resolution time as Duration
|
||||
* Uses hrtime() for monotonic, high-precision timing
|
||||
*
|
||||
* @return Duration High-resolution Duration since arbitrary point
|
||||
*/
|
||||
public function hrtime(): Duration;
|
||||
|
||||
/**
|
||||
* Measure duration of a callable execution
|
||||
*
|
||||
* @param callable $callback Function to measure
|
||||
* @return array{result: mixed, duration: Duration} Result and duration
|
||||
*/
|
||||
public function measureDuration(callable $callback): array;
|
||||
|
||||
/**
|
||||
* High-resolution benchmark helper
|
||||
*
|
||||
* @param callable $callback Function to benchmark
|
||||
* @param int $iterations Number of iterations
|
||||
* @return array{total: Duration, average: Duration, min: Duration, max: Duration}
|
||||
*/
|
||||
public function benchmark(callable $callback, int $iterations = 1): array;
|
||||
}
|
||||
16
src/Framework/DateTime/HighResolutionClockInitializer.php
Normal file
16
src/Framework/DateTime/HighResolutionClockInitializer.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\DI\Initializer;
|
||||
|
||||
final readonly class HighResolutionClockInitializer
|
||||
{
|
||||
#[Initializer]
|
||||
public function __invoke(): HighResolutionClock
|
||||
{
|
||||
return new SystemHighResolutionClock();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Timestamp;
|
||||
use App\Framework\DateTime\Exceptions\InvalidDateTimeException;
|
||||
use App\Framework\DateTime\Exceptions\InvalidTimezoneException;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
|
||||
use function microtime;
|
||||
use function time;
|
||||
|
||||
final readonly class SystemClock implements Clock
|
||||
{
|
||||
@@ -41,9 +44,9 @@ final readonly class SystemClock implements Clock
|
||||
* {@inheritDoc}
|
||||
* @throws InvalidTimezoneException|InvalidDateTimeException
|
||||
*/
|
||||
public function fromTimestamp(int $timestamp): DateTimeImmutable
|
||||
public function fromTimestamp(Timestamp $timestamp): DateTimeImmutable
|
||||
{
|
||||
return DateTime::fromTimestamp($timestamp, $this->timezone);
|
||||
return DateTime::fromTimestamp($timestamp->toTimestamp(), $this->timezone);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,13 +91,8 @@ final readonly class SystemClock implements Clock
|
||||
return DateTime::fromString('yesterday', $this->timezone);
|
||||
}
|
||||
|
||||
public function time(): int
|
||||
public function time(): Timestamp
|
||||
{
|
||||
return time();
|
||||
}
|
||||
|
||||
public function microtime(bool $asFloat = false): float|array
|
||||
{
|
||||
return microtime($asFloat);
|
||||
return Timestamp::fromFloat(microtime(true));
|
||||
}
|
||||
}
|
||||
|
||||
87
src/Framework/DateTime/SystemHighResolutionClock.php
Normal file
87
src/Framework/DateTime/SystemHighResolutionClock.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
|
||||
/**
|
||||
* System implementation of HighResolutionClock using hrtime() for monotonic timing
|
||||
*
|
||||
* This implementation provides high-precision timing capabilities that are
|
||||
* unaffected by system clock changes, making it ideal for performance measurements.
|
||||
*/
|
||||
final readonly class SystemHighResolutionClock implements HighResolutionClock
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function hrtime(): Duration
|
||||
{
|
||||
return Duration::fromNanoseconds(hrtime(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function measureDuration(callable $callback): array
|
||||
{
|
||||
$start = $this->hrtime();
|
||||
$result = $callback();
|
||||
$end = $this->hrtime();
|
||||
|
||||
$duration = $end->subtract($start);
|
||||
|
||||
return [
|
||||
'result' => $result,
|
||||
'duration' => $duration,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function benchmark(callable $callback, int $iterations = 1): array
|
||||
{
|
||||
if ($iterations < 1) {
|
||||
throw new \InvalidArgumentException('Iterations must be at least 1');
|
||||
}
|
||||
|
||||
$durations = [];
|
||||
$totalDuration = Duration::zero();
|
||||
|
||||
for ($i = 0; $i < $iterations; $i++) {
|
||||
$start = $this->hrtime();
|
||||
$callback();
|
||||
$end = $this->hrtime();
|
||||
|
||||
$duration = $end->subtract($start);
|
||||
$durations[] = $duration;
|
||||
$totalDuration = $totalDuration->add($duration);
|
||||
}
|
||||
|
||||
$averageDuration = Duration::fromNanoseconds(
|
||||
(int) round($totalDuration->toNanoseconds() / $iterations)
|
||||
);
|
||||
|
||||
$minDuration = $durations[0];
|
||||
$maxDuration = $durations[0];
|
||||
|
||||
foreach ($durations as $duration) {
|
||||
if ($duration->toNanoseconds() < $minDuration->toNanoseconds()) {
|
||||
$minDuration = $duration;
|
||||
}
|
||||
if ($duration->toNanoseconds() > $maxDuration->toNanoseconds()) {
|
||||
$maxDuration = $duration;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'total' => $totalDuration,
|
||||
'average' => $averageDuration,
|
||||
'min' => $minDuration,
|
||||
'max' => $maxDuration,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use function sleep;
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
|
||||
use function usleep;
|
||||
|
||||
final readonly class SystemTimer implements Timer
|
||||
{
|
||||
|
||||
public function sleep(int $seconds): void
|
||||
{
|
||||
sleep($seconds);
|
||||
}
|
||||
|
||||
public function usleep(int $microseconds): void
|
||||
public function sleep(Duration $duration): void
|
||||
{
|
||||
// Convert to microseconds for maximum precision
|
||||
$microseconds = (int) round($duration->toMicroseconds());
|
||||
usleep($microseconds);
|
||||
}
|
||||
|
||||
public function msleep(int $milliseconds): void
|
||||
{
|
||||
usleep($milliseconds * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
|
||||
interface Timer
|
||||
{
|
||||
/**
|
||||
* Pausiert die Ausführung für die angegebene Anzahl von Sekunden.
|
||||
* Pausiert die Ausführung für die angegebene Duration.
|
||||
*
|
||||
* @param int $seconds Anzahl der Sekunden
|
||||
* @param Duration $duration Die Pausendauer als Duration Value Object
|
||||
*/
|
||||
public function sleep(int $seconds): void;
|
||||
|
||||
/**
|
||||
* Pausiert die Ausführung für die angegebene Anzahl von Mikrosekunden.
|
||||
*
|
||||
* @param int $microseconds Anzahl der Mikrosekunden
|
||||
*/
|
||||
public function usleep(int $microseconds): void;
|
||||
|
||||
/**
|
||||
* Pausiert die Ausführung für die angegebene Anzahl von Millisekunden.
|
||||
*
|
||||
* @param int $milliseconds Anzahl der Millisekunden
|
||||
*/
|
||||
public function msleep(int $milliseconds): void;
|
||||
public function sleep(Duration $duration): void;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\DateTime;
|
||||
|
||||
enum Timezone: string
|
||||
|
||||
Reference in New Issue
Block a user