}> Active timings */ private array $timings = []; /** * @var array Collected metrics */ private array $metrics = []; /** * @var float Start time of the request */ private float $requestStartTime; /** * @var int Start memory usage of the request */ private int $requestStartMemory; /** * @var bool Whether performance tracking is enabled */ private bool $enabled = true; /** * @param UnifiedTelemetryService $telemetryService Telemetry service to adapt * @param PerformanceCollectorInterface $originalCollector Original collector for fallback */ public function __construct( private readonly UnifiedTelemetryService $telemetryService, private readonly PerformanceCollectorInterface $originalCollector ) { $this->requestStartTime = $originalCollector->getTotalRequestTime(); $this->requestStartMemory = $originalCollector->getTotalRequestMemory(); } /** * Start timing an operation */ public function startTiming(string $key, PerformanceCategory $category, array $context = []): void { if (! $this->enabled) { return; } // Record in original collector $this->originalCollector->startTiming($key, $category, $context); // Record in telemetry service $this->telemetryService->startOperation( $key, $category->value, $context ); // Record locally for endTiming $this->timings[$key] = [ 'start' => microtime(true), 'category' => $category, 'context' => $context, ]; } /** * End timing an operation */ public function endTiming(string $key): void { if (! $this->enabled || ! isset($this->timings[$key])) { return; } // End in original collector $this->originalCollector->endTiming($key); // End in telemetry service $this->telemetryService->endOperation($key); // Calculate duration and record as metric $duration = (microtime(true) - $this->timings[$key]['start']) * 1000; $this->recordMetric( "{$key}_duration", $this->timings[$key]['category'], $duration, array_merge($this->timings[$key]['context'], ['unit' => 'ms']) ); // Remove from active timings unset($this->timings[$key]); } /** * Measure a callable's execution time and memory usage */ public function measure(string $key, PerformanceCategory $category, callable $callback, array $context = []): mixed { if (! $this->enabled) { return $callback(); } // Use telemetry service's trace method return $this->telemetryService->trace( $key, $category->value, $callback, $context ); } /** * Record a metric value */ public function recordMetric(string $key, PerformanceCategory $category, float $value, array $context = []): void { if (! $this->enabled) { return; } // Record in original collector $this->originalCollector->recordMetric($key, $category, $value, $context); // Record in telemetry service $unit = $context['unit'] ?? ''; $this->telemetryService->recordMetric( $key, $value, $unit, array_merge($context, ['category' => $category->value]) ); // Store locally $this->metrics[$key] = PerformanceMetric::create($key, $category, $context) ->withValue($value); } /** * Increment a counter */ public function increment(string $key, PerformanceCategory $category, int $amount = 1, array $context = []): void { if (! $this->enabled) { return; } // Increment in original collector $this->originalCollector->increment($key, $category, $amount, $context); // Get current value or default to 0 $currentValue = 0; if (isset($this->metrics[$key])) { $currentValue = $this->metrics[$key]->getValue(); } // Record new value $this->recordMetric( $key, $category, $currentValue + $amount, array_merge($context, ['type' => 'counter']) ); } /** * Get all metrics, optionally filtered by category * * @return array */ public function getMetrics(?PerformanceCategory $category = null): array { // Get metrics from original collector $originalMetrics = $this->originalCollector->getMetrics($category); // Filter local metrics by category if needed if ($category !== null) { $filteredMetrics = []; foreach ($this->metrics as $key => $metric) { if ($metric->getCategory() === $category) { $filteredMetrics[$key] = $metric; } } return array_merge($originalMetrics, $filteredMetrics); } return array_merge($originalMetrics, $this->metrics); } /** * Get a specific metric by key */ public function getMetric(string $key): ?PerformanceMetric { if (isset($this->metrics[$key])) { return $this->metrics[$key]; } return $this->originalCollector->getMetric($key); } /** * Get total request time in milliseconds */ public function getTotalRequestTime(): float { return (microtime(true) - $this->requestStartTime) * 1000; } /** * Get total request memory usage in bytes */ public function getTotalRequestMemory(): int { return memory_get_usage() - $this->requestStartMemory; } /** * Get peak memory usage in bytes */ public function getPeakMemory(): int { return memory_get_peak_usage(); } /** * Reset all collected metrics */ public function reset(): void { $this->metrics = []; $this->timings = []; $this->originalCollector->reset(); } /** * Check if performance tracking is enabled */ public function isEnabled(): bool { return $this->enabled; } /** * Enable or disable performance tracking */ public function setEnabled(bool $enabled): void { $this->enabled = $enabled; $this->originalCollector->setEnabled($enabled); } }