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:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -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;
}

View File

@@ -12,7 +12,8 @@ final readonly class ClockInitializer
{
public function __construct(
private AppConfig $config
) {}
) {
}
#[Initializer]
public function __invoke(): Clock

View File

@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace App\Framework\DateTime;
use App\Framework\DateTime\Exceptions\InvalidDateTimeException;

View File

@@ -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');
}
/**

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View 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;
}

View 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();
}
}

View File

@@ -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));
}
}

View 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,
];
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace App\Framework\DateTime;
enum Timezone: string