totalExecutions === 0) { return Percentage::fromFloat(0.0); } return Percentage::fromFloat($this->totalSuccesses / $this->totalExecutions); } /** * Get fallback rate as percentage */ public function getFallbackRate(): Percentage { if ($this->totalExecutions === 0) { return Percentage::fromFloat(0.0); } return Percentage::fromFloat($this->totalFallbacks / $this->totalExecutions); } /** * Get error rate as percentage */ public function getErrorRate(): Percentage { if ($this->totalExecutions === 0) { return Percentage::fromFloat(0.0); } return Percentage::fromFloat($this->totalErrors / $this->totalExecutions); } /** * Check if boundary is healthy */ public function isHealthy(): bool { return $this->getFallbackRate()->toFloat() < 0.1 && // Less than 10% fallback rate $this->getErrorRate()->toFloat() < 0.05; // Less than 5% error rate } /** * Check if boundary is degraded */ public function isDegraded(): bool { return ($this->getFallbackRate()->toFloat() >= 0.1 && $this->getFallbackRate()->toFloat() < 0.25) || ($this->getErrorRate()->toFloat() >= 0.05 && $this->getErrorRate()->toFloat() < 0.15); } /** * Check if boundary is failed */ public function isFailed(): bool { return $this->getFallbackRate()->toFloat() >= 0.25 || // More than 25% fallback rate $this->getErrorRate()->toFloat() >= 0.15; // More than 15% error rate } /** * Get health status string */ public function getHealthStatus(): string { if ($this->isFailed()) { return 'failed'; } if ($this->isDegraded()) { return 'degraded'; } return 'healthy'; } /** * Get time since last execution */ public function getTimeSinceLastExecution(Timestamp $currentTime): Duration { return $this->lastExecution->diff($currentTime); } /** * Get most common error type */ public function getMostCommonErrorType(): ?string { if (empty($this->errorTypes)) { return null; } $maxCount = 0; $mostCommon = null; foreach ($this->errorTypes as $errorType => $count) { if ($count > $maxCount) { $maxCount = $count; $mostCommon = $errorType; } } return $mostCommon; } /** * Get error type distribution */ public function getErrorTypeDistribution(): array { if (empty($this->errorTypes) || $this->totalErrors === 0) { return []; } $distribution = []; foreach ($this->errorTypes as $errorType => $count) { $distribution[$errorType] = [ 'count' => $count, 'percentage' => ($count / $this->totalErrors) * 100, ]; } // Sort by count descending uasort($distribution, fn ($a, $b) => $b['count'] <=> $a['count']); return $distribution; } /** * Convert to array for serialization */ public function toArray(): array { return [ 'boundary_name' => $this->boundaryName, 'total_executions' => $this->totalExecutions, 'total_successes' => $this->totalSuccesses, 'total_fallbacks' => $this->totalFallbacks, 'total_errors' => $this->totalErrors, 'success_rate' => $this->getSuccessRate()->toFloat(), 'fallback_rate' => $this->getFallbackRate()->toFloat(), 'error_rate' => $this->getErrorRate()->toFloat(), 'average_execution_time_ms' => $this->averageExecutionTime->toMilliseconds(), 'peak_execution_time_ms' => $this->peakExecutionTime->toMilliseconds(), 'last_execution' => $this->lastExecution->toIsoString(), 'consecutive_failures' => $this->consecutiveFailures, 'error_types' => $this->errorTypes, 'most_common_error_type' => $this->getMostCommonErrorType(), 'error_type_distribution' => $this->getErrorTypeDistribution(), 'health_status' => $this->getHealthStatus(), 'is_healthy' => $this->isHealthy(), 'is_degraded' => $this->isDegraded(), 'is_failed' => $this->isFailed(), ]; } /** * Create from array */ public static function fromArray(array $data): self { return new self( boundaryName: $data['boundary_name'], totalExecutions: $data['total_executions'], totalSuccesses: $data['total_successes'], totalFallbacks: $data['total_fallbacks'], totalErrors: $data['total_errors'], averageExecutionTime: Duration::fromMilliseconds($data['average_execution_time_ms']), peakExecutionTime: Duration::fromMilliseconds($data['peak_execution_time_ms']), lastExecution: Timestamp::fromFloat(strtotime($data['last_execution'])), consecutiveFailures: $data['consecutive_failures'], errorTypes: $data['error_types'] ?? [], ); } }