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,19 +1,28 @@
<?php
declare(strict_types=1);
namespace App\Framework\Core;
use App\Framework\Cache\Cache;
use App\Framework\Cache\CacheKey;
use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\Discovery\FileVisitor;
use App\Framework\Discovery\ReflectionAwareVisitor;
use App\Framework\Filesystem\FilePath;
use App\Framework\Reflection\WrappedReflectionClass;
/**
* Visitor zum Verarbeiten von Attributen in Klassen
*/
final class AttributeMappingVisitor implements FileVisitor
final class AttributeMappingVisitor implements FileVisitor, ReflectionAwareVisitor
{
private array $attributeMappers = [];
private array $mappedAttributes = [];
private array $mapperByClass = [];
private array $processingStats = [];
/**
@@ -45,7 +54,7 @@ final class AttributeMappingVisitor implements FileVisitor
'classes_with_attributes' => 0,
'total_attributes' => 0,
'processed_attributes' => 0,
'skipped_reflectors' => 0
'skipped_reflectors' => 0,
];
}
@@ -57,31 +66,32 @@ final class AttributeMappingVisitor implements FileVisitor
'classes_with_attributes' => 0,
'total_attributes' => 0,
'processed_attributes' => 0,
'skipped_reflectors' => 0
'skipped_reflectors' => 0,
];
}
public function onIncrementalScanComplete(): void
{
// Logging der Verarbeitungsstatistiken für inkrementellen Scan
error_log("Inkrementelle Attribut-Verarbeitung abgeschlossen: " . json_encode($this->processingStats));
// Processing stats removed for production
}
public function visitClass(string $className, string $filePath): void
public function visitClass(ClassName $className, FilePath $filePath): void
{
if (!class_exists($className)) {
return;
}
// This method is kept for backward compatibility but should not be used
// when ReflectionProvider is available. The UnifiedDiscoveryService will
// prefer visitClassWithReflection() when possible.
}
public function visitClassWithReflection(ClassName $className, FilePath $filePath, WrappedReflectionClass $reflection): void
{
$this->processingStats['total_classes']++;
$hasAttributes = false;
try {
$reflection = new \ReflectionClass($className);
// Schnelle Vorprüfung: Hat die Klasse überhaupt relevante Attribute?
$relevantAttributes = $this->hasRelevantAttributes($reflection);
if (!$relevantAttributes) {
$relevantAttributes = $this->hasRelevantAttributesWrapped($reflection);
if (! $relevantAttributes) {
return;
}
@@ -89,26 +99,256 @@ final class AttributeMappingVisitor implements FileVisitor
$this->processingStats['classes_with_attributes']++;
// Verarbeite alle Attribute auf Klassenebene
$this->processAttributes($reflection->getAttributes(), $reflection);
$this->processAttributesWrapped($reflection->getAttributes(), $reflection);
// Verarbeite alle Methoden
foreach ($reflection->getMethods() as $method) {
$methods = $reflection->getMethods();
foreach ($methods as $method) {
// Schnelle Vorprüfung für jede Methode
if ($this->hasRelevantAttributes($method)) {
$this->processAttributes($method->getAttributes(), $method);
if ($this->hasRelevantAttributesWrappedMethod($method)) {
$this->processAttributesWrappedMethod($method->getAttributes(), $method);
}
}
// Verarbeite alle Eigenschaften
foreach ($reflection->getProperties() as $property) {
$properties = $reflection->getProperties();
foreach ($properties as $property) {
// Schnelle Vorprüfung für jede Eigenschaft
if ($this->hasRelevantAttributes($property)) {
$this->processAttributes($property->getAttributes(), $property);
if ($this->hasRelevantAttributesWrappedProperty($property)) {
$this->processAttributesWrappedProperty($property->getAttributes(), $property);
}
}
} catch (\Throwable $e) {
// Fehler beim Verarbeiten der Klasse protokollieren
error_log("Fehler bei der Attributverarbeitung von {$className}: " . $e->getMessage());
// Silent failure - skip this class and continue
}
}
/**
* Schnelle Vorprüfung, ob eine WrappedReflectionClass relevante Attribute hat
*/
private function hasRelevantAttributesWrapped(WrappedReflectionClass $reflection): bool
{
$attributes = $reflection->getAttributes();
$this->processingStats['total_attributes'] += $attributes->count();
if ($attributes->isEmpty()) {
return false;
}
foreach ($attributes as $attribute) {
$attributeClass = $attribute->getName();
if (isset($this->mapperByClass[$attributeClass])) {
$mapper = $this->mapperByClass[$attributeClass];
// For wrapped reflection, we need to create native reflection for mapper compatibility
try {
$nativeReflection = new \ReflectionClass($reflection->getName());
if ($mapper->canProcess($nativeReflection)) {
return true;
} else {
$this->processingStats['skipped_reflectors']++;
}
} catch (\Throwable) {
$this->processingStats['skipped_reflectors']++;
}
}
}
return false;
}
/**
* Schnelle Vorprüfung für WrappedReflectionMethod
*/
private function hasRelevantAttributesWrappedMethod($method): bool
{
$attributes = $method->getAttributes();
$this->processingStats['total_attributes'] += $attributes->count();
if ($attributes->isEmpty()) {
return false;
}
foreach ($attributes as $attribute) {
$attributeClass = $attribute->getName();
if (isset($this->mapperByClass[$attributeClass])) {
$mapper = $this->mapperByClass[$attributeClass];
// For wrapped reflection, we need to create native reflection for mapper compatibility
try {
$nativeClass = new \ReflectionClass($method->getDeclaringClass()->getName());
$nativeMethod = $nativeClass->getMethod($method->getName());
if ($mapper->canProcess($nativeMethod)) {
return true;
} else {
$this->processingStats['skipped_reflectors']++;
}
} catch (\Throwable) {
$this->processingStats['skipped_reflectors']++;
}
}
}
return false;
}
/**
* Schnelle Vorprüfung für WrappedReflectionProperty
*/
private function hasRelevantAttributesWrappedProperty($property): bool
{
$attributes = $property->getAttributes();
$this->processingStats['total_attributes'] += $attributes->count();
if ($attributes->isEmpty()) {
return false;
}
foreach ($attributes as $attribute) {
$attributeClass = $attribute->getName();
if (isset($this->mapperByClass[$attributeClass])) {
$mapper = $this->mapperByClass[$attributeClass];
// For wrapped reflection, we need to create native reflection for mapper compatibility
try {
$nativeClass = new \ReflectionClass($property->getDeclaringClass()->getName());
$nativeProperty = $nativeClass->getProperty($property->getName());
if ($mapper->canProcess($nativeProperty)) {
return true;
} else {
$this->processingStats['skipped_reflectors']++;
}
} catch (\Throwable) {
$this->processingStats['skipped_reflectors']++;
}
}
}
return false;
}
/**
* Verarbeitet Attribute einer WrappedReflectionClass
*/
private function processAttributesWrapped($attributes, WrappedReflectionClass $reflection): void
{
foreach ($attributes as $attribute) {
$attributeClass = $attribute->getName();
if (isset($this->mapperByClass[$attributeClass])) {
$mapper = $this->mapperByClass[$attributeClass];
try {
$nativeReflection = new \ReflectionClass($reflection->getName());
if ($mapper->canProcess($nativeReflection)) {
$attributeInstance = $attribute->newInstance();
$mapper->map($attributeInstance, $nativeReflection);
$this->processingStats['processed_attributes']++;
if (! isset($this->mappedAttributes[$attributeClass])) {
$this->mappedAttributes[$attributeClass] = [];
}
$reflectorKey = [
'type' => 'class',
'name' => $reflection->getName(),
];
$this->mappedAttributes[$attributeClass][] = [
'attribute' => $attributeInstance,
'reflector' => $reflectorKey,
'metadata' => $mapper->getAttributeMetadata(),
];
}
} catch (\Throwable $e) {
// Silent failure - skip this attribute and continue
}
}
}
}
/**
* Verarbeitet Attribute einer WrappedReflectionMethod
*/
private function processAttributesWrappedMethod($attributes, $method): void
{
foreach ($attributes as $attribute) {
$attributeClass = $attribute->getName();
if (isset($this->mapperByClass[$attributeClass])) {
$mapper = $this->mapperByClass[$attributeClass];
try {
$nativeClass = new \ReflectionClass($method->getDeclaringClass()->getName());
$nativeMethod = $nativeClass->getMethod($method->getName());
if ($mapper->canProcess($nativeMethod)) {
$attributeInstance = $attribute->newInstance();
$mapper->map($attributeInstance, $nativeMethod);
$this->processingStats['processed_attributes']++;
if (! isset($this->mappedAttributes[$attributeClass])) {
$this->mappedAttributes[$attributeClass] = [];
}
$reflectorKey = [
'type' => 'method',
'class' => $method->getDeclaringClass()->getName(),
'name' => $method->getName(),
];
$this->mappedAttributes[$attributeClass][] = [
'attribute' => $attributeInstance,
'reflector' => $reflectorKey,
'metadata' => $mapper->getAttributeMetadata(),
];
}
} catch (\Throwable $e) {
// Silent failure - skip this attribute and continue
}
}
}
}
/**
* Verarbeitet Attribute einer WrappedReflectionProperty
*/
private function processAttributesWrappedProperty($attributes, $property): void
{
foreach ($attributes as $attribute) {
$attributeClass = $attribute->getName();
if (isset($this->mapperByClass[$attributeClass])) {
$mapper = $this->mapperByClass[$attributeClass];
try {
$nativeClass = new \ReflectionClass($property->getDeclaringClass()->getName());
$nativeProperty = $nativeClass->getProperty($property->getName());
if ($mapper->canProcess($nativeProperty)) {
$attributeInstance = $attribute->newInstance();
$mapper->map($attributeInstance, $nativeProperty);
$this->processingStats['processed_attributes']++;
if (! isset($this->mappedAttributes[$attributeClass])) {
$this->mappedAttributes[$attributeClass] = [];
}
$reflectorKey = [
'type' => 'property',
'class' => $property->getDeclaringClass()->getName(),
'name' => $property->getName(),
];
$this->mappedAttributes[$attributeClass][] = [
'attribute' => $attributeInstance,
'reflector' => $reflectorKey,
'metadata' => $mapper->getAttributeMetadata(),
];
}
} catch (\Throwable $e) {
// Silent failure - skip this attribute and continue
}
}
}
}
@@ -158,7 +398,7 @@ final class AttributeMappingVisitor implements FileVisitor
$this->processingStats['processed_attributes']++;
// Speichere für Caching
if (!isset($this->mappedAttributes[$attributeClass])) {
if (! isset($this->mappedAttributes[$attributeClass])) {
$this->mappedAttributes[$attributeClass] = [];
}
@@ -168,10 +408,10 @@ final class AttributeMappingVisitor implements FileVisitor
$this->mappedAttributes[$attributeClass][] = [
'attribute' => $attributeInstance,
'reflector' => $reflectorKey,
'metadata' => $mapper->getAttributeMetadata()
'metadata' => $mapper->getAttributeMetadata(),
];
} catch (\Throwable $e) {
error_log("Fehler beim Verarbeiten des Attributs {$attributeClass}: " . $e->getMessage());
// Silent failure - skip this attribute and continue
}
}
}
@@ -186,45 +426,45 @@ final class AttributeMappingVisitor implements FileVisitor
if ($reflector instanceof \ReflectionClass) {
return [
'type' => 'class',
'name' => $reflector->getName()
'name' => $reflector->getName(),
];
} elseif ($reflector instanceof \ReflectionMethod) {
return [
'type' => 'method',
'class' => $reflector->getDeclaringClass()->getName(),
'name' => $reflector->getName()
'name' => $reflector->getName(),
];
} elseif ($reflector instanceof \ReflectionProperty) {
return [
'type' => 'property',
'class' => $reflector->getDeclaringClass()->getName(),
'name' => $reflector->getName()
'name' => $reflector->getName(),
];
}
return [
'type' => 'unknown',
'name' => method_exists($reflector, 'getName') ? $reflector->getName() : 'unknown'
'name' => method_exists($reflector, 'getName') ? $reflector->getName() : 'unknown',
];
}
public function onScanComplete(): void
{
// Logging der Verarbeitungsstatistiken
error_log("Attribut-Verarbeitung abgeschlossen: " . json_encode($this->processingStats));
// Processing completed - stats removed for production
}
public function loadFromCache(Cache $cache): void
{
$cacheItem = $cache->get($this->getCacheKey());
$cacheItem = $cache->get(CacheKey::fromString($this->getCacheKey()));
if ($cacheItem->isHit) {
$this->mappedAttributes = $cacheItem->value;
}
}
public function getCacheKey(): string
public function getCacheKey(): CacheKey
{
return 'attribute_mappings';
return CacheKey::fromString('attribute_mappings');
}
public function getCacheableData(): mixed