fix(Discovery): Add comprehensive debug logging for router initialization

- Add initializer count logging in DiscoveryServiceBootstrapper
- Add route structure analysis in RouterSetup
- Add request parameter logging in HttpRouter
- Update PHP production config for better OPcache handling
- Fix various config and error handling improvements
This commit is contained in:
2025-10-27 22:23:18 +01:00
parent e326e3d6c6
commit 70e45fb56e
56 changed files with 1519 additions and 355 deletions

View File

@@ -51,8 +51,13 @@ final readonly class ErrorHandler
?SecurityEventHandler $securityHandler = null
) {
$this->isDebugMode = $isDebugMode ?? $this->getDebugModeFromEnvironment();
$this->logger = new ErrorLogger($logger);
$this->securityHandler = $securityHandler ?? SecurityEventHandler::createDefault($logger);
// Get Logger and AppConfig from container if not provided
$logger = $logger ?? $container->get(Logger::class);
$appConfig = $container->get(\App\Framework\Config\AppConfig::class);
$this->logger = new ErrorLogger($logger, $appConfig);
$this->securityHandler = $securityHandler ?? SecurityEventHandler::createDefault($logger, $appConfig);
}
public function register(): void
@@ -456,9 +461,12 @@ final readonly class ErrorHandler
}
}
// Get AppConfig from container
$appConfig = $this->container->get(\App\Framework\Config\AppConfig::class);
$htmlRenderer = $templateRenderer ?
new ErrorTemplateRenderer($templateRenderer) :
new ErrorTemplateRenderer(new DummyTemplateRenderer());
new ErrorTemplateRenderer($templateRenderer, $appConfig) :
new ErrorTemplateRenderer(new DummyTemplateRenderer(), $appConfig);
$apiRenderer = new ApiErrorRenderer();

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Framework\ErrorHandling;
use App\Framework\Config\AppConfig;
use App\Framework\Exception\Core\ErrorSeverity;
use App\Framework\Exception\ErrorHandlerContext;
use App\Framework\Logging\Logger;
@@ -16,7 +17,8 @@ use App\Framework\Logging\ValueObjects\LogContext;
final readonly class ErrorLogger
{
public function __construct(
private ?Logger $logger = null
private Logger $logger,
private AppConfig $appConfig
) {
}
@@ -42,13 +44,8 @@ final readonly class ErrorLogger
'additionalData' => $context->additionalData,
];
if ($this->logger !== null) {
$logLevel = $this->mapErrorSeverityToLogLevel($context->level);
$this->logger->log($logLevel, $message, $contextData);
} else {
// Fallback auf error_log
$this->logToErrorLog($context);
}
$logLevel = $this->mapErrorSeverityToLogLevel($context->level);
$this->logger->log($logLevel, $message, $contextData);
}
/**
@@ -73,23 +70,18 @@ final readonly class ErrorLogger
);
if ($this->logger !== null) {
$logLevel = $this->determineLogLevel($context);
$logLevel = $this->determineLogLevel($context);
// Erstelle LogContext mit strukturierten Daten
$logContext = LogContext::withData($logData)
->addTags('error_handler', 'framework');
// Erstelle LogContext mit strukturierten Daten
$logContext = LogContext::withData($logData)
->addTags('error_handler', 'framework');
// Füge Metadaten-Tags hinzu
if ($context->exception->metadata['security_event'] ?? false) {
$logContext = $logContext->addTags('security');
}
$this->logger->log($logLevel, $message, $logContext);
} else {
// Fallback auf error_log
$this->logHandlerContextToErrorLog($context);
// Füge Metadaten-Tags hinzu
if ($context->exception->metadata['security_event'] ?? false) {
$logContext = $logContext->addTags('security');
}
$this->logger->log($logLevel, $message, $logContext);
}
/**
@@ -97,18 +89,13 @@ final readonly class ErrorLogger
*/
private function logSecurityEvent(ErrorHandlerContext $context): void
{
$securityLog = $context->toSecurityEventFormat($_ENV['APP_NAME'] ?? 'app');
$securityLog = $context->toSecurityEventFormat($this->appConfig->name);
if ($this->logger !== null) {
// Verwende LogContext für strukturiertes Security Event Logging
$logContext = LogContext::withData($securityLog)
->addTags('security_event', 'owasp');
// Verwende LogContext für strukturiertes Security Event Logging
$logContext = LogContext::withData($securityLog)
->addTags('security_event', 'owasp');
$this->logger->log(LogLevel::WARNING, 'Security Event Detected', $logContext);
} else {
// Fallback nur als letzte Option
error_log('SECURITY_EVENT: ' . json_encode($securityLog, JSON_UNESCAPED_SLASHES));
}
$this->logger->log(LogLevel::WARNING, 'Security Event Detected', $logContext);
}
/**
@@ -164,51 +151,6 @@ final readonly class ErrorLogger
};
}
/**
* Fallback-Methode für ErrorHandlerContext ohne Framework Logger
*/
private function logHandlerContextToErrorLog(ErrorHandlerContext $context): void
{
$message = sprintf(
'[%s] [%s] %s: %s',
date('Y-m-d H:i:s'),
$context->exception->metadata['error_level'] ?? 'ERROR',
$context->exception->component ?? 'Application',
$this->extractExceptionMessage($context)
);
error_log($message);
// Security Events auch separat loggen
if ($context->exception->metadata['security_event'] ?? false) {
$securityLog = $context->toSecurityEventJson($_ENV['APP_NAME'] ?? 'app');
error_log('SECURITY_EVENT: ' . $securityLog);
}
}
/**
* Fallback-Methode für Logging ohne Framework Logger (Legacy)
*/
private function logToErrorLog(ErrorContext $context): void
{
$exception = $context->exception;
$message = sprintf(
'[%s] [%s] %s: %s in %s:%d',
date('Y-m-d H:i:s'),
$context->level->name,
get_class($exception),
$exception->getMessage(),
$exception->getFile(),
$exception->getLine()
);
error_log($message);
// Bei kritischen Fehlern auch den Stacktrace loggen
if ($context->level === ErrorSeverity::CRITICAL) {
error_log("Stack trace: \n" . $exception->getTraceAsString());
}
}
/**
* Mappt ErrorSeverity auf Framework LogLevel

View File

@@ -16,7 +16,7 @@ use Throwable;
final readonly class SecurityEventHandler
{
public function __construct(
private SecurityEventLogger $securityLogger,
private ?SecurityEventLogger $securityLogger,
private ?SecurityAlertManager $alertManager = null
) {
}
@@ -28,6 +28,11 @@ final readonly class SecurityEventHandler
SecurityException $exception,
?MiddlewareContext $context = null
): void {
// Skip if no logger available
if ($this->securityLogger === null) {
return;
}
try {
// Erstelle ErrorHandlerContext für OWASP-Format
$errorHandlerContext = $this->createErrorHandlerContext($exception, $context);
@@ -71,7 +76,7 @@ final readonly class SecurityEventHandler
): void {
if ($this->alertManager) {
$this->alertManager->sendAlert($exception, $context);
} else {
} elseif ($this->securityLogger !== null) {
// Fallback: Logge als kritisches Event
$this->securityLogger->logCriticalAlert($exception, $context);
}
@@ -135,9 +140,16 @@ final readonly class SecurityEventHandler
/**
* Factory-Methode mit Standard-Konfiguration
*/
public static function createDefault(?Logger $logger = null): self
public static function createDefault(?Logger $logger = null, ?\App\Framework\Config\AppConfig $appConfig = null): self
{
$securityLogger = new SecurityEventLogger($logger);
// If AppConfig not provided, we can't create SecurityEventLogger properly
// This is a temporary solution - ideally AppConfig should always be provided
if ($logger === null || $appConfig === null) {
// Return a minimal handler without SecurityEventLogger
return new self(null, null);
}
$securityLogger = new SecurityEventLogger($logger, $appConfig);
$alertManager = null; // Kann später konfiguriert werden
return new self($securityLogger, $alertManager);

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Framework\ErrorHandling;
use App\Framework\Config\AppConfig;
use App\Framework\Exception\ErrorHandlerContext;
use App\Framework\Exception\SecurityException;
use App\Framework\Exception\SecurityLogLevel;
@@ -16,8 +17,8 @@ use App\Framework\Logging\LogLevel;
final readonly class SecurityEventLogger
{
public function __construct(
private ?Logger $logger = null,
private string $applicationId = 'app'
private Logger $logger,
private AppConfig $appConfig
) {
}
@@ -33,26 +34,21 @@ final readonly class SecurityEventLogger
// OWASP-konformes Log generieren
$owaspLog = $this->createOWASPLog($exception, $context);
if ($this->logger) {
// Strukturiertes Logging über Framework Logger
$frameworkLogLevel = $this->mapSecurityLevelToFrameworkLevel($securityEvent->getLogLevel());
// Strukturiertes Logging über Framework Logger
$frameworkLogLevel = $this->mapSecurityLevelToFrameworkLevel($securityEvent->getLogLevel());
$this->logger->log(
$frameworkLogLevel,
$securityEvent->getDescription(),
[
'security_event' => $securityEvent->getEventIdentifier(),
'security_category' => $securityEvent->getCategory(),
'requires_alert' => $securityEvent->requiresAlert(),
'owasp_format' => $owaspLog,
'event_data' => $securityEvent->toArray(),
'context_data' => $context->forLogging(),
]
);
} else {
// Fallback auf error_log
$this->logToErrorLog($owaspLog);
}
$this->logger->log(
$frameworkLogLevel,
$securityEvent->getDescription(),
[
'security_event' => $securityEvent->getEventIdentifier(),
'security_category' => $securityEvent->getCategory(),
'requires_alert' => $securityEvent->requiresAlert(),
'owasp_format' => $owaspLog,
'event_data' => $securityEvent->toArray(),
'context_data' => $context->forLogging(),
]
);
}
/**
@@ -64,15 +60,11 @@ final readonly class SecurityEventLogger
): void {
$alertData = $this->createAlertData($exception, $context);
if ($this->logger) {
$this->logger->log(
LogLevel::CRITICAL,
'SECURITY_ALERT: ' . $exception->getSecurityEvent()->getEventIdentifier(),
$alertData
);
} else {
error_log('SECURITY_ALERT: ' . json_encode($alertData));
}
$this->logger->log(
LogLevel::CRITICAL,
'SECURITY_ALERT: ' . $exception->getSecurityEvent()->getEventIdentifier(),
$alertData
);
}
/**
@@ -86,7 +78,7 @@ final readonly class SecurityEventLogger
return [
'datetime' => date('c'),
'appid' => $this->applicationId,
'appid' => $this->appConfig->name,
'event' => $securityEvent->getEventIdentifier(),
'level' => $securityEvent->getLogLevel()->value,
'description' => $securityEvent->getDescription(),
@@ -98,8 +90,6 @@ final readonly class SecurityEventLogger
'port' => $context->request->port,
'request_uri' => $context->request->requestUri,
'request_method' => $context->request->requestMethod,
'region' => $_ENV['AWS_REGION'] ?? 'unknown',
'geo' => $_ENV['GEO_LOCATION'] ?? 'unknown',
'category' => $securityEvent->getCategory(),
'requires_alert' => $securityEvent->requiresAlert(),
];
@@ -127,15 +117,6 @@ final readonly class SecurityEventLogger
];
}
/**
* Fallback-Logging über error_log
*/
private function logToErrorLog(array $owaspLog): void
{
$logMessage = 'SECURITY_EVENT: ' . json_encode($owaspLog, JSON_UNESCAPED_SLASHES);
error_log($logMessage);
}
/**
* Mappt SecurityLogLevel auf Framework LogLevel
*/
@@ -150,15 +131,4 @@ final readonly class SecurityEventLogger
SecurityLogLevel::FATAL => LogLevel::CRITICAL,
};
}
/**
* Factory-Methode für Standard-Konfiguration
*/
public static function create(?Logger $logger = null): self
{
return new self(
$logger,
$_ENV['APP_NAME'] ?? $_ENV['APP_ID'] ?? 'app'
);
}
}

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Framework\ErrorHandling\View;
use App\Framework\Config\AppConfig;
use App\Framework\Core\ValueObjects\Byte;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\ErrorHandling\StackTrace;
@@ -23,6 +24,7 @@ final readonly class ErrorTemplateRenderer implements ErrorViewRendererInterface
{
public function __construct(
private TemplateRenderer $renderer,
private AppConfig $appConfig,
private string $debugTemplate = 'enhanced-debug',
private string $productionTemplate = 'production'
) {
@@ -65,7 +67,7 @@ final readonly class ErrorTemplateRenderer implements ErrorViewRendererInterface
'userAgent' => (string) ($context->request->userAgent ?? 'Unknown'),
'traceCount' => 0, // Will be updated below if trace is available
// Environment information
'environment' => $_ENV['APP_ENV'] ?? 'development',
'environment' => $this->appConfig->type->value,
'debugMode' => $isDebug ? 'Enabled' : 'Disabled',
'phpVersion' => PHP_VERSION,
'frameworkVersion' => '1.0.0-dev',