docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,267 @@
<?php
declare(strict_types=1);
namespace Tests\Feature\Framework\Logging;
use App\Framework\Core\PathProvider;
use App\Framework\Logging\DefaultLogger;
use App\Framework\Logging\Handlers\MultiFileHandler;
use App\Framework\Logging\LogConfig;
use App\Framework\Logging\LogLevel;
use App\Framework\Logging\ProcessorManager;
use PHPUnit\Framework\TestCase;
final class ChannelLoggingIntegrationTest extends TestCase
{
private string $testLogDir;
private DefaultLogger $logger;
private LogConfig $logConfig;
protected function setUp(): void
{
// Temporäres Test-Verzeichnis erstellen
$this->testLogDir = sys_get_temp_dir() . '/integration_logs_' . uniqid();
mkdir($this->testLogDir, 0755, true);
// PathProvider Mock
$pathProvider = $this->createMock(PathProvider::class);
$pathProvider->method('resolvePath')->willReturnCallback(function (string $path) {
return $this->testLogDir . '/' . $path;
});
// LogConfig Mock
$this->logConfig = $this->createMock(LogConfig::class);
$this->logConfig->method('getLogPath')->willReturnCallback(function (string $type) {
return match ($type) {
'security' => $this->testLogDir . '/security/security.log',
'cache' => $this->testLogDir . '/debug/cache.log',
'database' => $this->testLogDir . '/debug/database.log',
'framework' => $this->testLogDir . '/debug/framework.log',
'error' => $this->testLogDir . '/app/error.log',
default => $this->testLogDir . '/app/app.log'
};
});
// MultiFileHandler
$multiFileHandler = new MultiFileHandler(
$this->logConfig,
$pathProvider,
LogLevel::DEBUG,
'[{timestamp}] [{level_name}] [{channel}] {message}'
);
// DefaultLogger mit echtem MultiFileHandler
$this->logger = new DefaultLogger(
minLevel: LogLevel::DEBUG,
handlers: [$multiFileHandler],
processorManager: new ProcessorManager()
);
}
protected function tearDown(): void
{
// Cleanup: Test-Verzeichnis löschen
if (is_dir($this->testLogDir)) {
$this->deleteDirectory($this->testLogDir);
}
}
private function deleteDirectory(string $dir): void
{
if (! is_dir($dir)) {
return;
}
$files = array_diff(scandir($dir), ['.', '..']);
foreach ($files as $file) {
$path = $dir . '/' . $file;
is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
}
rmdir($dir);
}
public function test_complete_channel_system_integration(): void
{
// Verschiedene Channel-Logs erstellen
$this->logger->security->warning('Failed login attempt', ['email' => 'test@example.com', 'ip' => '192.168.1.1']);
$this->logger->cache->debug('Cache miss', ['key' => 'user_123']);
$this->logger->database->error('Query timeout', ['query' => 'SELECT * FROM users', 'duration' => 30.5]);
$this->logger->framework->info('Route registered', ['route' => '/api/users', 'method' => 'GET']);
$this->logger->error->critical('System failure', ['component' => 'payment', 'error_code' => 'PAY_001']);
// Alle Log-Dateien sollten erstellt worden sein
expect(file_exists($this->testLogDir . '/security/security.log'))->toBeTrue();
expect(file_exists($this->testLogDir . '/debug/cache.log'))->toBeTrue();
expect(file_exists($this->testLogDir . '/debug/database.log'))->toBeTrue();
expect(file_exists($this->testLogDir . '/debug/framework.log'))->toBeTrue();
expect(file_exists($this->testLogDir . '/app/error.log'))->toBeTrue();
// Security Log Inhalt prüfen
$securityContent = file_get_contents($this->testLogDir . '/security/security.log');
expect($securityContent)->toContain('[WARNING] [security] Failed login attempt');
expect($securityContent)->toContain('"email":"test@example.com"');
expect($securityContent)->toContain('"ip":"192.168.1.1"');
// Cache Log Inhalt prüfen
$cacheContent = file_get_contents($this->testLogDir . '/debug/cache.log');
expect($cacheContent)->toContain('[DEBUG] [cache] Cache miss');
expect($cacheContent)->toContain('"key":"user_123"');
// Database Log Inhalt prüfen
$databaseContent = file_get_contents($this->testLogDir . '/debug/database.log');
expect($databaseContent)->toContain('[ERROR] [database] Query timeout');
expect($databaseContent)->toContain('"query":"SELECT * FROM users"');
expect($databaseContent)->toContain('"duration":30.5');
// Framework Log Inhalt prüfen
$frameworkContent = file_get_contents($this->testLogDir . '/debug/framework.log');
expect($frameworkContent)->toContain('[INFO] [framework] Route registered');
expect($frameworkContent)->toContain('"route":"\/api\/users"');
expect($frameworkContent)->toContain('"method":"GET"');
// Error Log Inhalt prüfen
$errorContent = file_get_contents($this->testLogDir . '/app/error.log');
expect($errorContent)->toContain('[CRITICAL] [error] System failure');
expect($errorContent)->toContain('"component":"payment"');
expect($errorContent)->toContain('"error_code":"PAY_001"');
}
public function test_mixed_standard_and_channel_logging(): void
{
// Mix aus Standard-Logging und Channel-Logging
$this->logger->info('Standard application log');
$this->logger->security->error('Security incident');
$this->logger->warning('Another standard log');
$this->logger->cache->info('Cache operation');
// Standard-Logs sollten nicht in den spezifischen Channel-Dateien landen
expect(file_exists($this->testLogDir . '/security/security.log'))->toBeTrue();
expect(file_exists($this->testLogDir . '/debug/cache.log'))->toBeTrue();
// Security Log sollte nur Security-spezifische Einträge haben
$securityContent = file_get_contents($this->testLogDir . '/security/security.log');
expect($securityContent)->toContain('Security incident');
expect($securityContent)->not->toContain('Standard application log');
expect($securityContent)->not->toContain('Another standard log');
// Cache Log sollte nur Cache-spezifische Einträge haben
$cacheContent = file_get_contents($this->testLogDir . '/debug/cache.log');
expect($cacheContent)->toContain('Cache operation');
expect($cacheContent)->not->toContain('Standard application log');
expect($cacheContent)->not->toContain('Security incident');
}
public function test_multiple_entries_same_channel(): void
{
// Mehrere Einträge in den gleichen Channel
$this->logger->security->info('User login', ['user_id' => 123]);
$this->logger->security->warning('Suspicious activity', ['user_id' => 123, 'actions' => ['login', 'password_change']]);
$this->logger->security->error('Account locked', ['user_id' => 123, 'reason' => 'too_many_attempts']);
$securityFile = $this->testLogDir . '/security/security.log';
expect(file_exists($securityFile))->toBeTrue();
$content = file_get_contents($securityFile);
$lines = explode("\n", trim($content));
// Drei Zeilen sollten vorhanden sein
expect($lines)->toHaveCount(3);
expect($content)->toContain('[INFO] [security] User login');
expect($content)->toContain('[WARNING] [security] Suspicious activity');
expect($content)->toContain('[ERROR] [security] Account locked');
// Alle Einträge sollten user_id 123 enthalten
expect($content)->toContain('"user_id":123');
}
public function test_channel_system_with_different_log_levels(): void
{
// Verschiedene Log-Level in verschiedenen Channels
$this->logger->cache->debug('Debug cache operation');
$this->logger->security->info('Info security event');
$this->logger->database->warning('Warning database issue');
$this->logger->framework->error('Error in framework');
$this->logger->error->critical('Critical system error');
// Alle Dateien sollten existieren
$files = [
'cache' => $this->testLogDir . '/debug/cache.log',
'security' => $this->testLogDir . '/security/security.log',
'database' => $this->testLogDir . '/debug/database.log',
'framework' => $this->testLogDir . '/debug/framework.log',
'error' => $this->testLogDir . '/app/error.log',
];
foreach ($files as $channel => $file) {
expect(file_exists($file))->toBeTrue("File for {$channel} channel should exist");
}
// Level sollten korrekt sein
expect(file_get_contents($files['cache']))->toContain('[DEBUG]');
expect(file_get_contents($files['security']))->toContain('[INFO]');
expect(file_get_contents($files['database']))->toContain('[WARNING]');
expect(file_get_contents($files['framework']))->toContain('[ERROR]');
expect(file_get_contents($files['error']))->toContain('[CRITICAL]');
}
public function test_realistic_application_scenario(): void
{
// Simuliere eine realistische Anwendungsszenario
// User Authentication Flow
$this->logger->security->info('Authentication attempt started', ['email' => 'user@example.com']);
$this->logger->cache->debug('Checking user cache', ['cache_key' => 'user_user@example.com']);
$this->logger->cache->debug('Cache miss - loading from database');
$this->logger->database->debug('User query executed', ['query' => 'SELECT * FROM users WHERE email = ?']);
$this->logger->security->info('User authenticated successfully', ['user_id' => 42]);
$this->logger->cache->info('User cached', ['cache_key' => 'user_42', 'ttl' => 3600]);
// API Request Processing
$this->logger->framework->debug('Route matched', ['route' => '/api/orders', 'method' => 'GET']);
$this->logger->database->debug('Orders query', ['user_id' => 42, 'limit' => 10]);
$this->logger->cache->debug('Cache hit', ['cache_key' => 'orders_42_page_1']);
// Error Scenario
$this->logger->database->error('Database connection lost', ['host' => 'db.example.com', 'port' => 3306]);
$this->logger->error->critical('Service degraded', ['affected_services' => ['orders', 'payments']]);
$this->logger->security->warning('Potential attack detected', ['ip' => '1.2.3.4', 'pattern' => 'sql_injection']);
// Überprüfe dass alle Logs korrekt in ihre Kanäle geschrieben wurden
$securityLog = file_get_contents($this->testLogDir . '/security/security.log');
$cacheLog = file_get_contents($this->testLogDir . '/debug/cache.log');
$databaseLog = file_get_contents($this->testLogDir . '/debug/database.log');
$frameworkLog = file_get_contents($this->testLogDir . '/debug/framework.log');
$errorLog = file_get_contents($this->testLogDir . '/app/error.log');
// Security-Ereignisse
expect($securityLog)->toContain('Authentication attempt started');
expect($securityLog)->toContain('User authenticated successfully');
expect($securityLog)->toContain('Potential attack detected');
// Cache-Operationen
expect($cacheLog)->toContain('Checking user cache');
expect($cacheLog)->toContain('Cache miss');
expect($cacheLog)->toContain('User cached');
expect($cacheLog)->toContain('Cache hit');
// Database-Operationen
expect($databaseLog)->toContain('User query executed');
expect($databaseLog)->toContain('Orders query');
expect($databaseLog)->toContain('Database connection lost');
// Framework-Ereignisse
expect($frameworkLog)->toContain('Route matched');
// Error-Ereignisse
expect($errorLog)->toContain('Service degraded');
// Cross-channel Isolation prüfen
expect($securityLog)->not->toContain('Cache miss');
expect($cacheLog)->not->toContain('Authentication attempt');
expect($databaseLog)->not->toContain('Route matched');
}
}