- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
309 lines
12 KiB
PHP
309 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\ErrorBoundaries\Metrics;
|
|
|
|
use App\Framework\Core\ValueObjects\Duration;
|
|
use App\Framework\Core\ValueObjects\Percentage;
|
|
use App\Framework\Core\ValueObjects\Timestamp;
|
|
|
|
/**
|
|
* Metrics for error boundary operations
|
|
*/
|
|
final readonly class BoundaryMetrics
|
|
{
|
|
public function __construct(
|
|
public string $boundaryName,
|
|
public int $totalExecutions = 0,
|
|
public int $successfulExecutions = 0,
|
|
public int $failedExecutions = 0,
|
|
public int $fallbackExecutions = 0,
|
|
public int $timeoutExecutions = 0,
|
|
public int $circuitBreakerTrips = 0,
|
|
public Duration $totalExecutionTime = new Duration(0.0),
|
|
public Duration $averageExecutionTime = new Duration(0.0),
|
|
public Duration $maxExecutionTime = new Duration(0.0),
|
|
public Duration $minExecutionTime = new Duration(0.0),
|
|
public ?Timestamp $lastSuccessTime = null,
|
|
public ?Timestamp $lastFailureTime = null,
|
|
public ?Timestamp $lastFallbackTime = null,
|
|
public ?Timestamp $createdAt = null,
|
|
public ?Timestamp $updatedAt = null,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Calculate success rate
|
|
*/
|
|
public function getSuccessRate(): Percentage
|
|
{
|
|
if ($this->totalExecutions === 0) {
|
|
return Percentage::fromFloat(0.0);
|
|
}
|
|
|
|
return Percentage::fromFloat($this->successfulExecutions / $this->totalExecutions);
|
|
}
|
|
|
|
/**
|
|
* Calculate failure rate
|
|
*/
|
|
public function getFailureRate(): Percentage
|
|
{
|
|
if ($this->totalExecutions === 0) {
|
|
return Percentage::fromFloat(0.0);
|
|
}
|
|
|
|
return Percentage::fromFloat($this->failedExecutions / $this->totalExecutions);
|
|
}
|
|
|
|
/**
|
|
* Calculate fallback rate
|
|
*/
|
|
public function getFallbackRate(): Percentage
|
|
{
|
|
if ($this->totalExecutions === 0) {
|
|
return Percentage::fromFloat(0.0);
|
|
}
|
|
|
|
return Percentage::fromFloat($this->fallbackExecutions / $this->totalExecutions);
|
|
}
|
|
|
|
/**
|
|
* Calculate timeout rate
|
|
*/
|
|
public function getTimeoutRate(): Percentage
|
|
{
|
|
if ($this->totalExecutions === 0) {
|
|
return Percentage::fromFloat(0.0);
|
|
}
|
|
|
|
return Percentage::fromFloat($this->timeoutExecutions / $this->totalExecutions);
|
|
}
|
|
|
|
/**
|
|
* Check if boundary is healthy (success rate > 90%)
|
|
*/
|
|
public function isHealthy(): bool
|
|
{
|
|
return $this->getSuccessRate()->toFloat() > 0.9;
|
|
}
|
|
|
|
/**
|
|
* Check if circuit breaker is frequently tripping
|
|
*/
|
|
public function hasFrequentCircuitBreakerTrips(): bool
|
|
{
|
|
if ($this->totalExecutions === 0) {
|
|
return false;
|
|
}
|
|
|
|
$tripRate = $this->circuitBreakerTrips / $this->totalExecutions;
|
|
|
|
return $tripRate > 0.1; // More than 10% of executions result in circuit breaker trips
|
|
}
|
|
|
|
/**
|
|
* Get health status
|
|
*/
|
|
public function getHealthStatus(): BoundaryHealthStatus
|
|
{
|
|
if ($this->isHealthy() && ! $this->hasFrequentCircuitBreakerTrips()) {
|
|
return BoundaryHealthStatus::HEALTHY;
|
|
}
|
|
|
|
if ($this->getSuccessRate()->toFloat() > 0.7) {
|
|
return BoundaryHealthStatus::WARNING;
|
|
}
|
|
|
|
return BoundaryHealthStatus::CRITICAL;
|
|
}
|
|
|
|
/**
|
|
* Record successful execution
|
|
*/
|
|
public function recordSuccess(Duration $executionTime): self
|
|
{
|
|
$newTotalTime = $this->totalExecutionTime->add($executionTime);
|
|
$newTotalExecutions = $this->totalExecutions + 1;
|
|
$newAverageTime = Duration::fromMilliseconds(
|
|
$newTotalTime->toMilliseconds() / $newTotalExecutions
|
|
);
|
|
|
|
return new self(
|
|
boundaryName: $this->boundaryName,
|
|
totalExecutions: $newTotalExecutions,
|
|
successfulExecutions: $this->successfulExecutions + 1,
|
|
failedExecutions: $this->failedExecutions,
|
|
fallbackExecutions: $this->fallbackExecutions,
|
|
timeoutExecutions: $this->timeoutExecutions,
|
|
circuitBreakerTrips: $this->circuitBreakerTrips,
|
|
totalExecutionTime: $newTotalTime,
|
|
averageExecutionTime: $newAverageTime,
|
|
maxExecutionTime: $executionTime->isGreaterThan($this->maxExecutionTime)
|
|
? $executionTime
|
|
: $this->maxExecutionTime,
|
|
minExecutionTime: $this->minExecutionTime->isZero() || $executionTime->isLessThan($this->minExecutionTime)
|
|
? $executionTime
|
|
: $this->minExecutionTime,
|
|
lastSuccessTime: Timestamp::now(),
|
|
lastFailureTime: $this->lastFailureTime,
|
|
lastFallbackTime: $this->lastFallbackTime,
|
|
createdAt: $this->createdAt ?? Timestamp::now(),
|
|
updatedAt: Timestamp::now(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Record failed execution
|
|
*/
|
|
public function recordFailure(Duration $executionTime): self
|
|
{
|
|
$newTotalTime = $this->totalExecutionTime->add($executionTime);
|
|
$newTotalExecutions = $this->totalExecutions + 1;
|
|
$newAverageTime = Duration::fromMilliseconds(
|
|
$newTotalTime->toMilliseconds() / $newTotalExecutions
|
|
);
|
|
|
|
return new self(
|
|
boundaryName: $this->boundaryName,
|
|
totalExecutions: $newTotalExecutions,
|
|
successfulExecutions: $this->successfulExecutions,
|
|
failedExecutions: $this->failedExecutions + 1,
|
|
fallbackExecutions: $this->fallbackExecutions,
|
|
timeoutExecutions: $this->timeoutExecutions,
|
|
circuitBreakerTrips: $this->circuitBreakerTrips,
|
|
totalExecutionTime: $newTotalTime,
|
|
averageExecutionTime: $newAverageTime,
|
|
maxExecutionTime: $executionTime->isGreaterThan($this->maxExecutionTime)
|
|
? $executionTime
|
|
: $this->maxExecutionTime,
|
|
minExecutionTime: $this->minExecutionTime->isZero() || $executionTime->isLessThan($this->minExecutionTime)
|
|
? $executionTime
|
|
: $this->minExecutionTime,
|
|
lastSuccessTime: $this->lastSuccessTime,
|
|
lastFailureTime: Timestamp::now(),
|
|
lastFallbackTime: $this->lastFallbackTime,
|
|
createdAt: $this->createdAt ?? Timestamp::now(),
|
|
updatedAt: Timestamp::now(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Record fallback execution
|
|
*/
|
|
public function recordFallback(): self
|
|
{
|
|
return new self(
|
|
boundaryName: $this->boundaryName,
|
|
totalExecutions: $this->totalExecutions + 1,
|
|
successfulExecutions: $this->successfulExecutions,
|
|
failedExecutions: $this->failedExecutions,
|
|
fallbackExecutions: $this->fallbackExecutions + 1,
|
|
timeoutExecutions: $this->timeoutExecutions,
|
|
circuitBreakerTrips: $this->circuitBreakerTrips,
|
|
totalExecutionTime: $this->totalExecutionTime,
|
|
averageExecutionTime: $this->averageExecutionTime,
|
|
maxExecutionTime: $this->maxExecutionTime,
|
|
minExecutionTime: $this->minExecutionTime,
|
|
lastSuccessTime: $this->lastSuccessTime,
|
|
lastFailureTime: $this->lastFailureTime,
|
|
lastFallbackTime: Timestamp::now(),
|
|
createdAt: $this->createdAt ?? Timestamp::now(),
|
|
updatedAt: Timestamp::now(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Record timeout execution
|
|
*/
|
|
public function recordTimeout(Duration $executionTime): self
|
|
{
|
|
$newTotalTime = $this->totalExecutionTime->add($executionTime);
|
|
$newTotalExecutions = $this->totalExecutions + 1;
|
|
$newAverageTime = Duration::fromMilliseconds(
|
|
$newTotalTime->toMilliseconds() / $newTotalExecutions
|
|
);
|
|
|
|
return new self(
|
|
boundaryName: $this->boundaryName,
|
|
totalExecutions: $newTotalExecutions,
|
|
successfulExecutions: $this->successfulExecutions,
|
|
failedExecutions: $this->failedExecutions,
|
|
fallbackExecutions: $this->fallbackExecutions,
|
|
timeoutExecutions: $this->timeoutExecutions + 1,
|
|
circuitBreakerTrips: $this->circuitBreakerTrips,
|
|
totalExecutionTime: $newTotalTime,
|
|
averageExecutionTime: $newAverageTime,
|
|
maxExecutionTime: $executionTime->isGreaterThan($this->maxExecutionTime)
|
|
? $executionTime
|
|
: $this->maxExecutionTime,
|
|
minExecutionTime: $this->minExecutionTime->isZero() || $executionTime->isLessThan($this->minExecutionTime)
|
|
? $executionTime
|
|
: $this->minExecutionTime,
|
|
lastSuccessTime: $this->lastSuccessTime,
|
|
lastFailureTime: $this->lastFailureTime,
|
|
lastFallbackTime: $this->lastFallbackTime,
|
|
createdAt: $this->createdAt ?? Timestamp::now(),
|
|
updatedAt: Timestamp::now(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Record circuit breaker trip
|
|
*/
|
|
public function recordCircuitBreakerTrip(): self
|
|
{
|
|
return new self(
|
|
boundaryName: $this->boundaryName,
|
|
totalExecutions: $this->totalExecutions,
|
|
successfulExecutions: $this->successfulExecutions,
|
|
failedExecutions: $this->failedExecutions,
|
|
fallbackExecutions: $this->fallbackExecutions,
|
|
timeoutExecutions: $this->timeoutExecutions,
|
|
circuitBreakerTrips: $this->circuitBreakerTrips + 1,
|
|
totalExecutionTime: $this->totalExecutionTime,
|
|
averageExecutionTime: $this->averageExecutionTime,
|
|
maxExecutionTime: $this->maxExecutionTime,
|
|
minExecutionTime: $this->minExecutionTime,
|
|
lastSuccessTime: $this->lastSuccessTime,
|
|
lastFailureTime: $this->lastFailureTime,
|
|
lastFallbackTime: $this->lastFallbackTime,
|
|
createdAt: $this->createdAt ?? Timestamp::now(),
|
|
updatedAt: Timestamp::now(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Convert to array for serialization
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'boundary_name' => $this->boundaryName,
|
|
'total_executions' => $this->totalExecutions,
|
|
'successful_executions' => $this->successfulExecutions,
|
|
'failed_executions' => $this->failedExecutions,
|
|
'fallback_executions' => $this->fallbackExecutions,
|
|
'timeout_executions' => $this->timeoutExecutions,
|
|
'circuit_breaker_trips' => $this->circuitBreakerTrips,
|
|
'success_rate' => $this->getSuccessRate()->toFloat(),
|
|
'failure_rate' => $this->getFailureRate()->toFloat(),
|
|
'fallback_rate' => $this->getFallbackRate()->toFloat(),
|
|
'timeout_rate' => $this->getTimeoutRate()->toFloat(),
|
|
'total_execution_time_ms' => $this->totalExecutionTime->toMilliseconds(),
|
|
'average_execution_time_ms' => $this->averageExecutionTime->toMilliseconds(),
|
|
'max_execution_time_ms' => $this->maxExecutionTime->toMilliseconds(),
|
|
'min_execution_time_ms' => $this->minExecutionTime->toMilliseconds(),
|
|
'last_success_time' => $this->lastSuccessTime?->toIsoString(),
|
|
'last_failure_time' => $this->lastFailureTime?->toIsoString(),
|
|
'last_fallback_time' => $this->lastFallbackTime?->toIsoString(),
|
|
'health_status' => $this->getHealthStatus()->value,
|
|
'is_healthy' => $this->isHealthy(),
|
|
'has_frequent_circuit_trips' => $this->hasFrequentCircuitBreakerTrips(),
|
|
'created_at' => $this->createdAt?->toIsoString(),
|
|
'updated_at' => $this->updatedAt?->toIsoString(),
|
|
];
|
|
}
|
|
}
|