component ?? 'unknown'; // Increment total count $this->incrementMetric('total'); // Increment by class $this->incrementMetric('class:' . $exceptionClass); // Increment by component $this->incrementMetric('component:' . $component); // Record execution time if available if ($executionTimeMs !== null) { $this->recordExecutionTime($executionTimeMs); } } /** * Get current metrics * * @return ExceptionMetrics Current metrics */ public function getMetrics(): ExceptionMetrics { $totalCount = $this->getMetric('total'); $byClass = $this->getMetricsByPrefix('class:'); $byComponent = $this->getMetricsByPrefix('component:'); $avgExecutionTime = $this->getAverageExecutionTime(); return new ExceptionMetrics( totalCount: $totalCount, byClass: $byClass, byComponent: $byComponent, averageExecutionTimeMs: $avgExecutionTime ); } /** * Increment metric */ private function incrementMetric(string $metricName): void { $cacheKey = CacheKey::fromString(self::CACHE_PREFIX . $metricName); $current = $this->getMetricValue($cacheKey); $newValue = $current + 1; $cacheItem = CacheItem::fromKey( $cacheKey, $newValue, Duration::fromSeconds(self::METRICS_TTL) ); $this->cache->set($cacheItem); } /** * Get metric value */ private function getMetric(string $metricName): int { $cacheKey = CacheKey::fromString(self::CACHE_PREFIX . $metricName); return $this->getMetricValue($cacheKey); } /** * Get metric value from cache */ private function getMetricValue(CacheKey $cacheKey): int { $result = $this->cache->get($cacheKey); $item = $result->getItem($cacheKey); if (! $item->isHit) { return 0; } $value = $item->value; return is_int($value) ? $value : 0; } /** * Get metrics by prefix */ private function getMetricsByPrefix(string $prefix): array { // Simplified implementation - in production, would use cache prefix scanning return []; } /** * Record execution time */ private function recordExecutionTime(float $executionTimeMs): void { $cacheKey = CacheKey::fromString(self::CACHE_PREFIX . 'execution_times'); $result = $this->cache->get($cacheKey); $item = $result->getItem($cacheKey); $times = $item->isHit && is_array($item->value) ? $item->value : []; $times[] = $executionTimeMs; // Keep only last 1000 execution times if (count($times) > 1000) { $times = array_slice($times, -1000); } $cacheItem = CacheItem::fromKey( $cacheKey, $times, Duration::fromSeconds(self::METRICS_TTL) ); $this->cache->set($cacheItem); } /** * Get average execution time */ private function getAverageExecutionTime(): float { $cacheKey = CacheKey::fromString(self::CACHE_PREFIX . 'execution_times'); $result = $this->cache->get($cacheKey); $item = $result->getItem($cacheKey); if (! $item->isHit || ! is_array($item->value)) { return 0.0; } $times = $item->value; if (empty($times)) { return 0.0; } return array_sum($times) / count($times); } }