Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
308
src/Framework/ErrorBoundaries/Metrics/BoundaryMetrics.php
Normal file
308
src/Framework/ErrorBoundaries/Metrics/BoundaryMetrics.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?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(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user