createMock(LogHandler::class); // Config: 100% ERROR, 0% INFO $config = SamplingConfig::custom([ 'ERROR' => 1.0, 'INFO' => 0.0, ]); $handler = new SamplingLogHandler($inner, $config); // ERROR sollte durchkommen $inner->expects($this->once())->method('handle'); $handler->handle($this->createLogRecord('error', LogLevel::ERROR)); // INFO sollte gedroppt werden $handler->handle($this->createLogRecord('info', LogLevel::INFO)); $this->assertEquals(1, $handler->getAcceptedCount()); $this->assertEquals(1, $handler->getDroppedCount()); } public function test_never_samples_critical_levels(): void { $inner = $this->createMock(LogHandler::class); $config = SamplingConfig::production(); $handler = new SamplingLogHandler($inner, $config); $criticalLevels = [ LogLevel::ERROR, LogLevel::CRITICAL, LogLevel::ALERT, LogLevel::EMERGENCY, ]; $inner->expects($this->exactly(count($criticalLevels))) ->method('handle'); foreach ($criticalLevels as $level) { $handler->handle($this->createLogRecord('test', $level)); } $this->assertEquals(count($criticalLevels), $handler->getAcceptedCount()); $this->assertEquals(0, $handler->getDroppedCount()); } public function test_tracks_dropped_by_level(): void { $inner = $this->createMock(LogHandler::class); $config = SamplingConfig::custom(['INFO' => 0.0]); $handler = new SamplingLogHandler($inner, $config); for ($i = 0; $i < 10; $i++) { $handler->handle($this->createLogRecord('info', LogLevel::INFO)); } $dropped = $handler->getDroppedByLevel(); $this->assertArrayHasKey('INFO', $dropped); $this->assertEquals(10, $dropped['INFO']); } public function test_calculates_drop_rate(): void { $inner = $this->createMock(LogHandler::class); $config = SamplingConfig::custom(['INFO' => 0.5]); $handler = new SamplingLogHandler($inner, $config); // Simulate: sollte ca. 50% droppen // Für deterministische Tests mocken wir mt_rand nicht, // aber prüfen nur dass Drop-Rate berechnet wird $this->assertEquals(0.0, $handler->getDropRate()); // Noch keine Logs } public function test_health_check(): void { $inner = $this->createMock(LogHandler::class); $handler = new SamplingLogHandler($inner, SamplingConfig::production()); $health = $handler->check(); $this->assertEquals(\App\Framework\Health\HealthStatus::HEALTHY, $health->status); $this->assertArrayHasKey('accepted', $health->details); $this->assertArrayHasKey('dropped', $health->details); } private function createLogRecord( string $message = 'test', LogLevel $level = LogLevel::INFO ): LogRecord { return new LogRecord( level: $level, message: $message, channel: 'test', context: LogContext::empty(), timestamp: new \DateTimeImmutable() ); } }