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,21 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Http;
|
||||
|
||||
use App\Framework\DI\Container;
|
||||
use App\Framework\Logging\DefaultLogger;
|
||||
use App\Framework\Logging\Logger;
|
||||
use Closure;
|
||||
|
||||
final readonly class HttpMiddlewareChain implements HttpMiddlewareNext
|
||||
final readonly class HttpMiddlewareChain implements HttpMiddlewareChainInterface
|
||||
{
|
||||
private MiddlewareInvoker $invoker;
|
||||
private DefaultLogger $logger;
|
||||
|
||||
private Logger $logger;
|
||||
|
||||
private RequestStateManager $stateManager;
|
||||
|
||||
public function __construct(
|
||||
private array $middlewares,
|
||||
private Closure $fallbackHandler,
|
||||
private Container $container
|
||||
) {
|
||||
$this->invoker = new MiddlewareInvoker($this->container);
|
||||
@@ -29,91 +30,101 @@ final readonly class HttpMiddlewareChain implements HttpMiddlewareNext
|
||||
|
||||
$this->stateManager = new MiddlewareStateManager()->forRequest($request);
|
||||
|
||||
// Middleware-Stack durchlaufen
|
||||
$resultContext = $this->processMiddlewareStack($context, 0);
|
||||
// Start der Middleware-Chain loggen
|
||||
error_log("🚀 MIDDLEWARE CHAIN START - URI: {$request->path}, Method: {$request->method->value}, Middleware-Count: " . count($this->middlewares));
|
||||
|
||||
// Am Ende die Response aus dem Kontext zurückgeben
|
||||
// Middleware-Stack durchlaufen
|
||||
$resultContext = $this->doProcessMiddlewareStack($context, 0);
|
||||
|
||||
// Ende der Middleware-Chain loggen
|
||||
if ($resultContext->hasResponse()) {
|
||||
error_log("✅ MIDDLEWARE CHAIN COMPLETE - Final Response Status: {$resultContext->response?->status->value}");
|
||||
|
||||
return $resultContext->response;
|
||||
}
|
||||
|
||||
// Warnung über fehlende Response
|
||||
$this->logger->warning('Keine Response nach Middleware-Chain - verwende Fallback-Handler', [
|
||||
'uri' => $resultContext->request->path,
|
||||
'method' => $resultContext->request->method->value,
|
||||
'middleware_count' => count($this->middlewares),
|
||||
]);
|
||||
// Wenn keine Response vorhanden ist, ist das ein Fehler in der Middleware-Konfiguration
|
||||
error_log("❌ MIDDLEWARE CHAIN FAILED - No response created after processing all middlewares");
|
||||
|
||||
// Fallback-Handler aufrufen
|
||||
$response = ($this->fallbackHandler)($resultContext->request);
|
||||
|
||||
if (!$response instanceof Response) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Fallback-Handler hat keine Response zurückgegeben, sondern %s',
|
||||
is_object($response) ? get_class($response) : gettype($response)
|
||||
));
|
||||
}
|
||||
|
||||
return $response;
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Keine Response nach Middleware-Chain erstellt. Stellen Sie sicher, dass eine DefaultResponseMiddleware konfiguriert ist. URI: %s, Method: %s, Middleware-Count: %d',
|
||||
$resultContext->request->path,
|
||||
$resultContext->request->method->value,
|
||||
count($this->middlewares)
|
||||
));
|
||||
}
|
||||
|
||||
private function processMiddlewareStack(MiddlewareContext $context, int $index): MiddlewareContext
|
||||
private function doProcessMiddlewareStack(MiddlewareContext $context, int $index): MiddlewareContext
|
||||
{
|
||||
// Wenn das Ende der Middleware-Kette erreicht ist
|
||||
if ($index >= count($this->middlewares)) {
|
||||
$this->logDebug("Ende der Middleware-Kette erreicht", $context, $index);
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
$middleware = $this->middlewares[$index];
|
||||
$middlewareName = $this->getMiddlewareName($middleware);
|
||||
|
||||
// Start der Middleware loggen
|
||||
error_log("🔄 MIDDLEWARE #{$index} START: {$middlewareName}");
|
||||
|
||||
// Status VOR der Middleware loggen
|
||||
$this->logDebug("VOR Middleware #{$index} ({$middlewareName})", $context, $index);
|
||||
|
||||
// Next-Funktion erstellen, die zur nächsten Middleware weiterleitet
|
||||
$next = function (MiddlewareContext $nextContext) use ($index, $middlewareName) {
|
||||
// Status beim Aufruf von $next() loggen
|
||||
$this->logDebug("NEXT aufgerufen in #{$index} ({$middlewareName})", $nextContext, $index);
|
||||
|
||||
// Zur nächsten Middleware weitergehen
|
||||
$resultContext = $this->processMiddlewareStack($nextContext, $index + 1);
|
||||
|
||||
// Status beim Rückgabewert von $next() loggen
|
||||
$this->logDebug("NEXT Rückgabe an #{$index} ({$middlewareName})", $resultContext, $index);
|
||||
|
||||
// Detaillierte Prüfung auf verlorene Response
|
||||
if ($nextContext->hasResponse() && !$resultContext->hasResponse()) {
|
||||
$this->logError("RESPONSE VERLOREN zwischen Middleware #{$index} ({$middlewareName}) und nachfolgenden Middlewares!");
|
||||
// Next-Handler erstellen, der zur nächsten Middleware weiterleitet
|
||||
$next = new readonly class ($this, $index, $middlewareName) implements Next {
|
||||
public function __construct(
|
||||
private HttpMiddlewareChain $chain,
|
||||
private int $index,
|
||||
private string $middlewareName
|
||||
) {
|
||||
}
|
||||
|
||||
return $resultContext;
|
||||
public function __invoke(MiddlewareContext $context): MiddlewareContext
|
||||
{
|
||||
// Status beim Aufruf von $next() loggen
|
||||
$this->chain->logDebug("NEXT aufgerufen in #{$this->index} ({$this->middlewareName})", $context, $this->index);
|
||||
|
||||
// Zur nächsten Middleware weitergehen
|
||||
$resultContext = $this->chain->processMiddlewareStack($context, $this->index + 1);
|
||||
|
||||
// Status beim Rückgabewert von $next() loggen
|
||||
$this->chain->logDebug("NEXT Rückgabe an #{$this->index} ({$this->middlewareName})", $resultContext, $this->index);
|
||||
|
||||
// Detaillierte Prüfung auf verlorene Response
|
||||
if ($context->hasResponse() && ! $resultContext->hasResponse()) {
|
||||
$this->chain->logError("RESPONSE VERLOREN zwischen Middleware #{$this->index} ({$this->middlewareName}) und nachfolgenden Middlewares!");
|
||||
}
|
||||
|
||||
return $resultContext;
|
||||
}
|
||||
};
|
||||
|
||||
// Response-Status VOR der Middleware merken
|
||||
$hadResponseBefore = $context->hasResponse();
|
||||
$responseBeforeStatus = $hadResponseBefore ? $context->response?->status->value : null;
|
||||
|
||||
// Middleware mit dem Invoker ausführen
|
||||
$resultContext = $this->invoker->invoke($middleware, $context, $next, $this->stateManager);
|
||||
|
||||
// Response-Status NACH der Middleware prüfen
|
||||
$hasResponseAfter = $resultContext->hasResponse();
|
||||
$responseAfterStatus = $hasResponseAfter ? $resultContext->response?->status->value : null;
|
||||
|
||||
// Detaillierte Response-Analyse
|
||||
$this->analyzeResponseChanges(
|
||||
$middlewareName,
|
||||
$index,
|
||||
$hadResponseBefore,
|
||||
$hasResponseAfter,
|
||||
$responseBeforeStatus,
|
||||
$responseAfterStatus
|
||||
);
|
||||
|
||||
// Status NACH der Middleware loggen
|
||||
$this->logDebug("NACH Middleware #{$index} ({$middlewareName})", $resultContext, $index);
|
||||
|
||||
/*
|
||||
// Prüfung ob diese Middleware eine Response hinzugefügt oder entfernt hat
|
||||
if (!$context->hasResponse() && $resultContext->hasResponse()) {
|
||||
$this->logInfo("✅ Response ERSTELLT von Middleware #{$index} ({$middlewareName})", [
|
||||
'middleware_name' => $middlewareName,
|
||||
'middleware_index' => $index,
|
||||
'response_status' => $resultContext->response?->status,
|
||||
]);
|
||||
} elseif ($context->hasResponse() && !$resultContext->hasResponse()) {
|
||||
$this->logError("❌ Response ENTFERNT von Middleware #{$index} ({$middlewareName})!", [
|
||||
'middleware_name' => $middlewareName,
|
||||
'middleware_index' => $index,
|
||||
'original_response_status' => $context->response?->status,
|
||||
]);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
return $resultContext;
|
||||
}
|
||||
|
||||
@@ -128,32 +139,67 @@ final readonly class HttpMiddlewareChain implements HttpMiddlewareNext
|
||||
|
||||
if (is_object($middleware)) {
|
||||
$className = get_class($middleware);
|
||||
|
||||
return substr($className, strrpos($className, '\\') + 1);
|
||||
}
|
||||
|
||||
return gettype($middleware);
|
||||
}
|
||||
|
||||
/**
|
||||
* Analysiert Response-Änderungen durch eine Middleware
|
||||
*/
|
||||
private function analyzeResponseChanges(
|
||||
string $middlewareName,
|
||||
int $index,
|
||||
bool $hadResponseBefore,
|
||||
bool $hasResponseAfter,
|
||||
?int $responseBeforeStatus,
|
||||
?int $responseAfterStatus
|
||||
): void {
|
||||
// Response wurde erstellt
|
||||
if (! $hadResponseBefore && $hasResponseAfter) {
|
||||
error_log("✅ RESPONSE CREATED by Middleware #{$index} ({$middlewareName}) - Status: {$responseAfterStatus}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Response wurde verloren
|
||||
if ($hadResponseBefore && ! $hasResponseAfter) {
|
||||
error_log("❌ RESPONSE LOST by Middleware #{$index} ({$middlewareName}) - Previous Status: {$responseBeforeStatus}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Response-Status wurde geändert
|
||||
if ($hadResponseBefore && $hasResponseAfter && $responseBeforeStatus !== $responseAfterStatus) {
|
||||
error_log("🔄 RESPONSE MODIFIED by Middleware #{$index} ({$middlewareName}) - Status: {$responseBeforeStatus} → {$responseAfterStatus}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Response blieb unverändert (normal)
|
||||
if ($hadResponseBefore && $hasResponseAfter && $responseBeforeStatus === $responseAfterStatus) {
|
||||
error_log("➡️ RESPONSE PASSED THROUGH Middleware #{$index} ({$middlewareName}) - Status: {$responseAfterStatus}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Keine Response vor und nach der Middleware (normal für frühe Middlewares)
|
||||
// @phpstan-ignore booleanNot.alwaysTrue
|
||||
if (! $hadResponseBefore && ! $hasResponseAfter) {
|
||||
error_log("⚪ NO RESPONSE before/after Middleware #{$index} ({$middlewareName})");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug-Logging mit Context-Informationen
|
||||
*/
|
||||
private function logDebug(string $message, MiddlewareContext $context, int $index): void
|
||||
public function logDebug(string $message, MiddlewareContext $context, int $index): void
|
||||
{
|
||||
$responseStatus = $context->hasResponse() ?
|
||||
"Response✅ (Status: " . ($context->response->statusCode ?? 'unknown') . ")" :
|
||||
"Response✅ (Status: " . ($context->response->status->value ?? 'unknown') . ")" :
|
||||
"Response❌";
|
||||
|
||||
/*
|
||||
$this->logger->debug('Middleware Chain: {message}', [
|
||||
'message' => $message,
|
||||
'response_status' => $responseStatus,
|
||||
'uri' => $context->request->uri ?? 'unknown',
|
||||
'method' => $context->request->method->value ?? 'unknown',
|
||||
'middleware_index' => $index,
|
||||
'has_response' => $context->hasResponse(),
|
||||
'response_code' => $context->response?->status->value,
|
||||
]);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,19 +209,27 @@ final readonly class HttpMiddlewareChain implements HttpMiddlewareNext
|
||||
{
|
||||
$this->logger->info('Middleware Chain: {message}', array_merge([
|
||||
'message' => $message,
|
||||
'component' => 'MiddlewareChain'
|
||||
'component' => 'MiddlewareChain',
|
||||
], $context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes processMiddlewareStack accessible to anonymous NextHandler class
|
||||
*/
|
||||
public function processMiddlewareStack(MiddlewareContext $context, int $index): MiddlewareContext
|
||||
{
|
||||
return $this->doProcessMiddlewareStack($context, $index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error-Logging für Probleme
|
||||
*/
|
||||
private function logError(string $message, array $context = []): void
|
||||
public function logError(string $message, array $context = []): void
|
||||
{
|
||||
$this->logger->error('Middleware Chain ERROR: {message}', array_merge([
|
||||
'message' => $message,
|
||||
'component' => 'MiddlewareChain',
|
||||
'stack_trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
|
||||
'stack_trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5),
|
||||
], $context));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user