*/ private array $statsByService = []; /** @var array */ private array $statsByRequestName = []; private int $totalRequests = 0; private int $totalSuccesses = 0; private int $totalFailures = 0; private float $totalDurationMs = 0.0; /** @var array */ private array $retryCountByService = []; /** @var array */ private array $circuitBreakerOpenCountByService = []; public function recordRequest( string $service, string $requestName, float $durationMs, bool $success, int $retryAttempts = 0, bool $circuitBreakerTriggered = false ): void { // Total stats $this->totalRequests++; if ($success) { $this->totalSuccesses++; } else { $this->totalFailures++; } $this->totalDurationMs += $durationMs; // Per-service stats if (!isset($this->statsByService[$service])) { $this->statsByService[$service] = [ 'requests' => 0, 'successes' => 0, 'failures' => 0, 'total_duration_ms' => 0.0, 'avg_duration_ms' => 0.0, ]; } $this->statsByService[$service]['requests']++; if ($success) { $this->statsByService[$service]['successes']++; } else { $this->statsByService[$service]['failures']++; } $this->statsByService[$service]['total_duration_ms'] += $durationMs; $this->statsByService[$service]['avg_duration_ms'] = $this->statsByService[$service]['total_duration_ms'] / $this->statsByService[$service]['requests']; // Per-request-name stats if (!isset($this->statsByRequestName[$requestName])) { $this->statsByRequestName[$requestName] = [ 'requests' => 0, 'successes' => 0, 'failures' => 0, 'total_duration_ms' => 0.0, 'avg_duration_ms' => 0.0, ]; } $this->statsByRequestName[$requestName]['requests']++; if ($success) { $this->statsByRequestName[$requestName]['successes']++; } else { $this->statsByRequestName[$requestName]['failures']++; } $this->statsByRequestName[$requestName]['total_duration_ms'] += $durationMs; $this->statsByRequestName[$requestName]['avg_duration_ms'] = $this->statsByRequestName[$requestName]['total_duration_ms'] / $this->statsByRequestName[$requestName]['requests']; // Retry tracking if ($retryAttempts > 0) { if (!isset($this->retryCountByService[$service])) { $this->retryCountByService[$service] = 0; } $this->retryCountByService[$service] += $retryAttempts; } // Circuit breaker tracking if ($circuitBreakerTriggered) { if (!isset($this->circuitBreakerOpenCountByService[$service])) { $this->circuitBreakerOpenCountByService[$service] = 0; } $this->circuitBreakerOpenCountByService[$service]++; } } public function getStats(): array { return [ 'total' => [ 'requests' => $this->totalRequests, 'successes' => $this->totalSuccesses, 'failures' => $this->totalFailures, 'success_rate' => $this->getSuccessRate(), 'avg_duration_ms' => $this->getAverageDuration(), ], 'by_service' => $this->statsByService, 'by_request_name' => $this->statsByRequestName, 'retry_counts' => $this->retryCountByService, 'circuit_breaker_opens' => $this->circuitBreakerOpenCountByService, ]; } public function getSuccessRate(): float { if ($this->totalRequests === 0) { return 0.0; } return $this->totalSuccesses / $this->totalRequests; } public function getAverageDuration(): float { if ($this->totalRequests === 0) { return 0.0; } return $this->totalDurationMs / $this->totalRequests; } public function getServiceStats(string $service): ?array { return $this->statsByService[$service] ?? null; } public function getRequestNameStats(string $requestName): ?array { return $this->statsByRequestName[$requestName] ?? null; } /** * Collect metrics for Prometheus export */ public function collectMetrics(MetricsCollection $collection): void { // Total request counter $collection->counter( 'api_gateway_requests_total', (float) $this->totalRequests, 'Total number of API gateway requests' ); // Success counter $collection->counter( 'api_gateway_requests_success_total', (float) $this->totalSuccesses, 'Total number of successful API gateway requests' ); // Failure counter $collection->counter( 'api_gateway_requests_failure_total', (float) $this->totalFailures, 'Total number of failed API gateway requests' ); // Success rate gauge $collection->gauge( 'api_gateway_success_rate', $this->getSuccessRate(), 'Success rate of API gateway requests (0.0 to 1.0)' ); // Average duration gauge $collection->gauge( 'api_gateway_request_duration_ms', $this->getAverageDuration(), 'Average duration of API gateway requests in milliseconds' ); // Per-service metrics foreach ($this->statsByService as $service => $stats) { $labels = ['service' => $service]; $collection->counter( 'api_gateway_requests_total', (float) $stats['requests'], 'Total requests per service', $labels ); $collection->counter( 'api_gateway_requests_success_total', (float) $stats['successes'], 'Successful requests per service', $labels ); $collection->counter( 'api_gateway_requests_failure_total', (float) $stats['failures'], 'Failed requests per service', $labels ); $collection->gauge( 'api_gateway_request_duration_ms', $stats['avg_duration_ms'], 'Average request duration per service in milliseconds', $labels ); // Success rate per service $successRate = $stats['requests'] > 0 ? $stats['successes'] / $stats['requests'] : 0.0; $collection->gauge( 'api_gateway_success_rate', $successRate, 'Success rate per service', $labels ); } // Per-request-name metrics foreach ($this->statsByRequestName as $requestName => $stats) { $labels = ['request_name' => $requestName]; $collection->counter( 'api_gateway_requests_total', (float) $stats['requests'], 'Total requests per request name', $labels ); $collection->counter( 'api_gateway_requests_success_total', (float) $stats['successes'], 'Successful requests per request name', $labels ); $collection->counter( 'api_gateway_requests_failure_total', (float) $stats['failures'], 'Failed requests per request name', $labels ); $collection->gauge( 'api_gateway_request_duration_ms', $stats['avg_duration_ms'], 'Average request duration per request name in milliseconds', $labels ); } // Retry metrics per service foreach ($this->retryCountByService as $service => $retryCount) { $collection->counter( 'api_gateway_retries_total', (float) $retryCount, 'Total number of retry attempts per service', ['service' => $service] ); } // Circuit breaker metrics per service foreach ($this->circuitBreakerOpenCountByService as $service => $openCount) { $collection->counter( 'api_gateway_circuit_breaker_open_total', (float) $openCount, 'Total number of circuit breaker opens per service', ['service' => $service] ); } } public function reset(): void { $this->statsByService = []; $this->statsByRequestName = []; $this->totalRequests = 0; $this->totalSuccesses = 0; $this->totalFailures = 0; $this->totalDurationMs = 0.0; $this->retryCountByService = []; $this->circuitBreakerOpenCountByService = []; } }