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:
222
src/Framework/StateManagement/CacheBasedStateManager.php
Normal file
222
src/Framework/StateManagement/CacheBasedStateManager.php
Normal file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\StateManagement;
|
||||
|
||||
use App\Framework\Cache\Cache;
|
||||
use App\Framework\Cache\CacheKey;
|
||||
use App\Framework\Core\ValueObjects\Byte;
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use App\Framework\Core\ValueObjects\Timestamp;
|
||||
use App\Framework\Logging\Logger;
|
||||
|
||||
/**
|
||||
* Cache-based implementation of state manager
|
||||
*
|
||||
* @template T of SerializableState
|
||||
* @implements StateManager<T>
|
||||
*/
|
||||
final class CacheBasedStateManager implements StateManager
|
||||
{
|
||||
private int $hitCount = 0;
|
||||
|
||||
private int $missCount = 0;
|
||||
|
||||
private int $setCount = 0;
|
||||
|
||||
private int $removeCount = 0;
|
||||
|
||||
private int $updateCount = 0;
|
||||
|
||||
private Duration $totalSetTime;
|
||||
|
||||
private Duration $totalGetTime;
|
||||
|
||||
public function __construct(
|
||||
private readonly Cache $cache,
|
||||
private readonly string $keyPrefix,
|
||||
private readonly string $stateClass,
|
||||
private readonly ?Duration $defaultTtl = null,
|
||||
private readonly ?Logger $logger = null,
|
||||
private readonly string $namespace = 'default',
|
||||
) {
|
||||
$this->totalSetTime = Duration::zero();
|
||||
$this->totalGetTime = Duration::zero();
|
||||
}
|
||||
|
||||
public function getState(string $key): mixed
|
||||
{
|
||||
$startTime = Timestamp::now();
|
||||
|
||||
try {
|
||||
$cacheKey = $this->getCacheKey($key);
|
||||
$cacheItem = $this->cache->get($cacheKey);
|
||||
|
||||
if (! $cacheItem->isHit) {
|
||||
$this->missCount++;
|
||||
$this->log('debug', "State miss for key: {$key}");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $cacheItem->value;
|
||||
if (! is_array($data)) {
|
||||
$this->missCount++;
|
||||
$this->log('warning', "Invalid state data for key: {$key}");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var T $state */
|
||||
$state = call_user_func([$this->stateClass, 'fromArray'], $data);
|
||||
$this->hitCount++;
|
||||
$this->log('debug', "State hit for key: {$key}");
|
||||
|
||||
return $state;
|
||||
} finally {
|
||||
$elapsed = Timestamp::now()->diff($startTime);
|
||||
$this->totalGetTime = $this->totalGetTime->add($elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
public function setState(string $key, mixed $state, ?Duration $ttl = null): void
|
||||
{
|
||||
$startTime = Timestamp::now();
|
||||
|
||||
try {
|
||||
if (! $state instanceof SerializableState) {
|
||||
throw new \InvalidArgumentException("State must implement SerializableState interface");
|
||||
}
|
||||
|
||||
$cacheKey = $this->getCacheKey($key);
|
||||
$effectiveTtl = $ttl ?? $this->defaultTtl ?? Duration::fromHours(1);
|
||||
|
||||
$this->cache->set($cacheKey, $state->toArray(), $effectiveTtl);
|
||||
$this->setCount++;
|
||||
$this->log('debug', "State set for key: {$key}", ['ttl' => $effectiveTtl->toSeconds()]);
|
||||
} finally {
|
||||
$elapsed = Timestamp::now()->diff($startTime);
|
||||
$this->totalSetTime = $this->totalSetTime->add($elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
public function hasState(string $key): bool
|
||||
{
|
||||
$cacheKey = $this->getCacheKey($key);
|
||||
$cacheItem = $this->cache->get($cacheKey);
|
||||
|
||||
return $cacheItem->isHit;
|
||||
}
|
||||
|
||||
public function removeState(string $key): void
|
||||
{
|
||||
$cacheKey = $this->getCacheKey($key);
|
||||
$this->cache->forget($cacheKey);
|
||||
$this->removeCount++;
|
||||
$this->log('debug', "State removed for key: {$key}");
|
||||
}
|
||||
|
||||
public function updateState(string $key, callable $updater, ?Duration $ttl = null): mixed
|
||||
{
|
||||
$this->updateCount++;
|
||||
|
||||
// Get current state
|
||||
$currentState = $this->getState($key);
|
||||
|
||||
// Apply update function
|
||||
$newState = $updater($currentState);
|
||||
|
||||
// Save updated state
|
||||
$this->setState($key, $newState, $ttl);
|
||||
|
||||
$this->log('debug', "State updated for key: {$key}");
|
||||
|
||||
return $newState;
|
||||
}
|
||||
|
||||
public function getAllStates(): array
|
||||
{
|
||||
// Note: This would require cache enumeration support
|
||||
// For now, return empty array - could be enhanced with cache tag support
|
||||
$this->log('warning', "getAllStates() not supported by cache-based implementation");
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function clearAll(): void
|
||||
{
|
||||
// Note: This would require cache enumeration or tag support
|
||||
// For now, we'll just log - could be enhanced with cache prefix clearing
|
||||
$this->log('warning', "clearAll() not fully supported by cache-based implementation");
|
||||
}
|
||||
|
||||
public function getStatistics(): StateManagerStatistics
|
||||
{
|
||||
$totalGets = $this->hitCount + $this->missCount;
|
||||
$averageGetTime = $totalGets > 0
|
||||
? Duration::fromMilliseconds($this->totalGetTime->toMilliseconds() / $totalGets)
|
||||
: Duration::zero();
|
||||
|
||||
$averageSetTime = $this->setCount > 0
|
||||
? Duration::fromMilliseconds($this->totalSetTime->toMilliseconds() / $this->setCount)
|
||||
: Duration::zero();
|
||||
|
||||
return new StateManagerStatistics(
|
||||
totalKeys: 0, // Would require cache enumeration
|
||||
hitCount: $this->hitCount,
|
||||
missCount: $this->missCount,
|
||||
setCount: $this->setCount,
|
||||
removeCount: $this->removeCount,
|
||||
updateCount: $this->updateCount,
|
||||
averageSetTime: $averageSetTime,
|
||||
averageGetTime: $averageGetTime,
|
||||
expiredKeys: 0, // Would require cache inspection
|
||||
memoryUsage: Byte::fromBytes(0), // Would require cache size information
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create state manager for specific state type
|
||||
*
|
||||
* @template U of SerializableState
|
||||
* @param class-string<U> $stateClass
|
||||
* @return CacheBasedStateManager<U>
|
||||
*/
|
||||
public static function for(
|
||||
Cache $cache,
|
||||
string $keyPrefix,
|
||||
string $stateClass,
|
||||
?Duration $defaultTtl = null,
|
||||
?Logger $logger = null,
|
||||
string $namespace = 'default',
|
||||
): self {
|
||||
return new self($cache, $keyPrefix, $stateClass, $defaultTtl, $logger, $namespace);
|
||||
}
|
||||
|
||||
private function getCacheKey(string $key): CacheKey
|
||||
{
|
||||
$fullKey = "{$this->keyPrefix}:{$this->namespace}:{$key}";
|
||||
|
||||
return CacheKey::from($fullKey);
|
||||
}
|
||||
|
||||
private function log(string $level, string $message, array $context = []): void
|
||||
{
|
||||
if ($this->logger === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context['namespace'] = $this->namespace;
|
||||
$context['key_prefix'] = $this->keyPrefix;
|
||||
$context['state_class'] = $this->stateClass;
|
||||
|
||||
match ($level) {
|
||||
'debug' => $this->logger->debug("[StateManager] {$message}", $context),
|
||||
'info' => $this->logger->info("[StateManager] {$message}", $context),
|
||||
'warning' => $this->logger->warning("[StateManager] {$message}", $context),
|
||||
'error' => $this->logger->error("[StateManager] {$message}", $context),
|
||||
default => $this->logger->info("[StateManager] {$message}", $context),
|
||||
};
|
||||
}
|
||||
}
|
||||
215
src/Framework/StateManagement/InMemoryStateManager.php
Normal file
215
src/Framework/StateManagement/InMemoryStateManager.php
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\StateManagement;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Byte;
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use App\Framework\Core\ValueObjects\Timestamp;
|
||||
|
||||
/**
|
||||
* In-memory implementation of state manager (for testing and simple use cases)
|
||||
*
|
||||
* @template T of SerializableState
|
||||
* @implements StateManager<T>
|
||||
*/
|
||||
final class InMemoryStateManager implements StateManager
|
||||
{
|
||||
private array $states = [];
|
||||
|
||||
private array $expirationTimes = [];
|
||||
|
||||
private int $hitCount = 0;
|
||||
|
||||
private int $missCount = 0;
|
||||
|
||||
private int $setCount = 0;
|
||||
|
||||
private int $removeCount = 0;
|
||||
|
||||
private int $updateCount = 0;
|
||||
|
||||
private Duration $totalSetTime;
|
||||
|
||||
private Duration $totalGetTime;
|
||||
|
||||
public function __construct(
|
||||
private readonly string $stateClass,
|
||||
) {
|
||||
$this->totalSetTime = Duration::zero();
|
||||
$this->totalGetTime = Duration::zero();
|
||||
}
|
||||
|
||||
public function getState(string $key): mixed
|
||||
{
|
||||
$startTime = Timestamp::now();
|
||||
|
||||
try {
|
||||
// Check if key exists and is not expired
|
||||
if (! $this->isValidKey($key)) {
|
||||
$this->missCount++;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $this->states[$key];
|
||||
|
||||
/** @var T $state */
|
||||
$state = call_user_func([$this->stateClass, 'fromArray'], $data);
|
||||
$this->hitCount++;
|
||||
|
||||
return $state;
|
||||
} finally {
|
||||
$elapsed = Timestamp::now()->diff($startTime);
|
||||
$this->totalGetTime = $this->totalGetTime->add($elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
public function setState(string $key, mixed $state, ?Duration $ttl = null): void
|
||||
{
|
||||
$startTime = Timestamp::now();
|
||||
|
||||
try {
|
||||
if (! $state instanceof SerializableState) {
|
||||
throw new \InvalidArgumentException("State must implement SerializableState interface");
|
||||
}
|
||||
|
||||
$this->states[$key] = $state->toArray();
|
||||
|
||||
// Set expiration time if TTL provided
|
||||
if ($ttl !== null && ! $ttl->isZero()) {
|
||||
$this->expirationTimes[$key] = Timestamp::now()->add($ttl)->toFloat();
|
||||
} else {
|
||||
unset($this->expirationTimes[$key]);
|
||||
}
|
||||
|
||||
$this->setCount++;
|
||||
} finally {
|
||||
$elapsed = Timestamp::now()->diff($startTime);
|
||||
$this->totalSetTime = $this->totalSetTime->add($elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
public function hasState(string $key): bool
|
||||
{
|
||||
return $this->isValidKey($key);
|
||||
}
|
||||
|
||||
public function removeState(string $key): void
|
||||
{
|
||||
unset($this->states[$key], $this->expirationTimes[$key]);
|
||||
$this->removeCount++;
|
||||
}
|
||||
|
||||
public function updateState(string $key, callable $updater, ?Duration $ttl = null): mixed
|
||||
{
|
||||
$this->updateCount++;
|
||||
|
||||
// Get current state
|
||||
$currentState = $this->getState($key);
|
||||
|
||||
// Apply update function
|
||||
$newState = $updater($currentState);
|
||||
|
||||
// Save updated state
|
||||
$this->setState($key, $newState, $ttl);
|
||||
|
||||
return $newState;
|
||||
}
|
||||
|
||||
public function getAllStates(): array
|
||||
{
|
||||
$validStates = [];
|
||||
|
||||
foreach ($this->states as $key => $data) {
|
||||
if ($this->isValidKey($key)) {
|
||||
/** @var T $state */
|
||||
$state = call_user_func([$this->stateClass, 'fromArray'], $data);
|
||||
$validStates[$key] = $state;
|
||||
}
|
||||
}
|
||||
|
||||
return $validStates;
|
||||
}
|
||||
|
||||
public function clearAll(): void
|
||||
{
|
||||
$this->states = [];
|
||||
$this->expirationTimes = [];
|
||||
}
|
||||
|
||||
public function getStatistics(): StateManagerStatistics
|
||||
{
|
||||
$this->cleanupExpiredKeys(); // Clean up before calculating stats
|
||||
|
||||
$totalGets = $this->hitCount + $this->missCount;
|
||||
$averageGetTime = $totalGets > 0
|
||||
? Duration::fromMilliseconds($this->totalGetTime->toMilliseconds() / $totalGets)
|
||||
: Duration::zero();
|
||||
|
||||
$averageSetTime = $this->setCount > 0
|
||||
? Duration::fromMilliseconds($this->totalSetTime->toMilliseconds() / $this->setCount)
|
||||
: Duration::zero();
|
||||
|
||||
// Estimate memory usage
|
||||
$memoryUsage = Byte::fromBytes(
|
||||
strlen(serialize($this->states)) + strlen(serialize($this->expirationTimes))
|
||||
);
|
||||
|
||||
return new StateManagerStatistics(
|
||||
totalKeys: count($this->states),
|
||||
hitCount: $this->hitCount,
|
||||
missCount: $this->missCount,
|
||||
setCount: $this->setCount,
|
||||
removeCount: $this->removeCount,
|
||||
updateCount: $this->updateCount,
|
||||
averageSetTime: $averageSetTime,
|
||||
averageGetTime: $averageGetTime,
|
||||
expiredKeys: 0, // We clean up expired keys immediately
|
||||
memoryUsage: $memoryUsage,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create state manager for specific state type
|
||||
*
|
||||
* @template U of SerializableState
|
||||
* @param class-string<U> $stateClass
|
||||
* @return InMemoryStateManager<U>
|
||||
*/
|
||||
public static function for(string $stateClass): self
|
||||
{
|
||||
return new self($stateClass);
|
||||
}
|
||||
|
||||
private function isValidKey(string $key): bool
|
||||
{
|
||||
if (! isset($this->states[$key])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check expiration
|
||||
if (isset($this->expirationTimes[$key])) {
|
||||
$now = Timestamp::now()->toFloat();
|
||||
if ($now > $this->expirationTimes[$key]) {
|
||||
$this->removeState($key);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function cleanupExpiredKeys(): void
|
||||
{
|
||||
$now = Timestamp::now()->toFloat();
|
||||
|
||||
foreach ($this->expirationTimes as $key => $expirationTime) {
|
||||
if ($now > $expirationTime) {
|
||||
$this->removeState($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/Framework/StateManagement/SerializableState.php
Normal file
21
src/Framework/StateManagement/SerializableState.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\StateManagement;
|
||||
|
||||
/**
|
||||
* Interface for states that can be serialized for persistence
|
||||
*/
|
||||
interface SerializableState
|
||||
{
|
||||
/**
|
||||
* Convert state to array for serialization
|
||||
*/
|
||||
public function toArray(): array;
|
||||
|
||||
/**
|
||||
* Create state from array (deserialization)
|
||||
*/
|
||||
public static function fromArray(array $data): static;
|
||||
}
|
||||
70
src/Framework/StateManagement/StateManager.php
Normal file
70
src/Framework/StateManagement/StateManager.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\StateManagement;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
|
||||
/**
|
||||
* Generic interface for state management
|
||||
*
|
||||
* @template T
|
||||
*/
|
||||
interface StateManager
|
||||
{
|
||||
/**
|
||||
* Get state for given key
|
||||
*
|
||||
* @param string $key
|
||||
* @return T|null
|
||||
*/
|
||||
public function getState(string $key): mixed;
|
||||
|
||||
/**
|
||||
* Set state for given key
|
||||
*
|
||||
* @param string $key
|
||||
* @param T $state
|
||||
* @param Duration|null $ttl
|
||||
* @return void
|
||||
*/
|
||||
public function setState(string $key, mixed $state, ?Duration $ttl = null): void;
|
||||
|
||||
/**
|
||||
* Check if state exists for given key
|
||||
*/
|
||||
public function hasState(string $key): bool;
|
||||
|
||||
/**
|
||||
* Remove state for given key
|
||||
*/
|
||||
public function removeState(string $key): void;
|
||||
|
||||
/**
|
||||
* Update state atomically using callback
|
||||
*
|
||||
* @param string $key
|
||||
* @param callable(T|null): T $updater
|
||||
* @param Duration|null $ttl
|
||||
* @return T
|
||||
*/
|
||||
public function updateState(string $key, callable $updater, ?Duration $ttl = null): mixed;
|
||||
|
||||
/**
|
||||
* Get all states (if supported by implementation)
|
||||
*
|
||||
* @return array<string, T>
|
||||
*/
|
||||
public function getAllStates(): array;
|
||||
|
||||
/**
|
||||
* Clear all states
|
||||
*/
|
||||
public function clearAll(): void;
|
||||
|
||||
/**
|
||||
* Get state statistics
|
||||
*/
|
||||
public function getStatistics(): StateManagerStatistics;
|
||||
}
|
||||
98
src/Framework/StateManagement/StateManagerFactory.php
Normal file
98
src/Framework/StateManagement/StateManagerFactory.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\StateManagement;
|
||||
|
||||
use App\Framework\Cache\Cache;
|
||||
use App\Framework\CircuitBreaker\CircuitBreakerMetrics;
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use App\Framework\ErrorBoundaries\CircuitBreaker\BoundaryCircuitBreakerState;
|
||||
use App\Framework\Logging\Logger;
|
||||
use App\Framework\RateLimit\TokenBucket;
|
||||
|
||||
/**
|
||||
* Factory for creating state managers
|
||||
*/
|
||||
final readonly class StateManagerFactory
|
||||
{
|
||||
public function __construct(
|
||||
private Cache $cache,
|
||||
private ?Logger $logger = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create cache-based state manager
|
||||
*
|
||||
* @template T of SerializableState
|
||||
* @param class-string<T> $stateClass
|
||||
* @return CacheBasedStateManager<T>
|
||||
*/
|
||||
public function createCacheBased(
|
||||
string $keyPrefix,
|
||||
string $stateClass,
|
||||
?Duration $defaultTtl = null,
|
||||
string $namespace = 'default',
|
||||
): CacheBasedStateManager {
|
||||
return CacheBasedStateManager::for(
|
||||
cache: $this->cache,
|
||||
keyPrefix: $keyPrefix,
|
||||
stateClass: $stateClass,
|
||||
defaultTtl: $defaultTtl,
|
||||
logger: $this->logger,
|
||||
namespace: $namespace,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create in-memory state manager (for testing)
|
||||
*
|
||||
* @template T of SerializableState
|
||||
* @param class-string<T> $stateClass
|
||||
* @return InMemoryStateManager<T>
|
||||
*/
|
||||
public function createInMemory(string $stateClass): InMemoryStateManager
|
||||
{
|
||||
return InMemoryStateManager::for($stateClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create state manager for CircuitBreaker states
|
||||
*/
|
||||
public function createForCircuitBreaker(string $namespace = 'default'): CacheBasedStateManager
|
||||
{
|
||||
return $this->createCacheBased(
|
||||
keyPrefix: 'circuit_breaker_state',
|
||||
stateClass: CircuitBreakerMetrics::class,
|
||||
defaultTtl: Duration::fromHours(1),
|
||||
namespace: $namespace,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create state manager for ErrorBoundary states
|
||||
*/
|
||||
public function createForErrorBoundary(string $namespace = 'default'): CacheBasedStateManager
|
||||
{
|
||||
return $this->createCacheBased(
|
||||
keyPrefix: 'error_boundary_state',
|
||||
stateClass: BoundaryCircuitBreakerState::class,
|
||||
defaultTtl: Duration::fromHours(1),
|
||||
namespace: $namespace,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create state manager for RateLimiter (future use)
|
||||
*/
|
||||
public function createForRateLimiter(string $namespace = 'default'): CacheBasedStateManager
|
||||
{
|
||||
return $this->createCacheBased(
|
||||
keyPrefix: 'rate_limiter_state',
|
||||
stateClass: TokenBucket::class, // Assuming this will implement SerializableState
|
||||
defaultTtl: Duration::fromHours(1),
|
||||
namespace: $namespace,
|
||||
);
|
||||
}
|
||||
}
|
||||
86
src/Framework/StateManagement/StateManagerStatistics.php
Normal file
86
src/Framework/StateManagement/StateManagerStatistics.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\StateManagement;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Byte;
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use App\Framework\Core\ValueObjects\Percentage;
|
||||
|
||||
/**
|
||||
* Statistics for state manager operations
|
||||
*/
|
||||
final readonly class StateManagerStatistics
|
||||
{
|
||||
public function __construct(
|
||||
public int $totalKeys = 0,
|
||||
public int $hitCount = 0,
|
||||
public int $missCount = 0,
|
||||
public int $setCount = 0,
|
||||
public int $removeCount = 0,
|
||||
public int $updateCount = 0,
|
||||
public Duration $averageSetTime = new Duration(0.0),
|
||||
public Duration $averageGetTime = new Duration(0.0),
|
||||
public int $expiredKeys = 0,
|
||||
public Byte $memoryUsage = new Byte(0),
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate hit rate
|
||||
*/
|
||||
public function getHitRate(): Percentage
|
||||
{
|
||||
$total = $this->hitCount + $this->missCount;
|
||||
if ($total === 0) {
|
||||
return Percentage::fromFloat(0.0);
|
||||
}
|
||||
|
||||
return Percentage::fromFloat($this->hitCount / $total);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate miss rate
|
||||
*/
|
||||
public function getMissRate(): Percentage
|
||||
{
|
||||
$hitRate = $this->getHitRate();
|
||||
|
||||
return Percentage::fromFloat(1.0 - $hitRate->toFloat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total operations
|
||||
*/
|
||||
public function getTotalOperations(): int
|
||||
{
|
||||
return $this->hitCount + $this->missCount + $this->setCount + $this->removeCount + $this->updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to array for serialization
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'total_keys' => $this->totalKeys,
|
||||
'hit_count' => $this->hitCount,
|
||||
'miss_count' => $this->missCount,
|
||||
'set_count' => $this->setCount,
|
||||
'remove_count' => $this->removeCount,
|
||||
'update_count' => $this->updateCount,
|
||||
'hit_rate' => $this->getHitRate()->toFloat(),
|
||||
'hit_rate_percentage' => $this->getHitRate()->toString(),
|
||||
'miss_rate' => $this->getMissRate()->toFloat(),
|
||||
'miss_rate_percentage' => $this->getMissRate()->toString(),
|
||||
'total_operations' => $this->getTotalOperations(),
|
||||
'average_set_time_ms' => $this->averageSetTime->toMilliseconds(),
|
||||
'average_get_time_ms' => $this->averageGetTime->toMilliseconds(),
|
||||
'expired_keys' => $this->expiredKeys,
|
||||
'memory_usage_bytes' => $this->memoryUsage->toBytes(),
|
||||
'memory_usage_mb' => $this->memoryUsage->toMegabytes(),
|
||||
'memory_usage_human' => $this->memoryUsage->toHumanReadable(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user