Error Handling with Result
Error Handling with Result<T>
Master the Result<T> pattern for explicit error handling without exceptions.
Overview
All SystemMetrics methods return Result<T> objects instead of throwing exceptions. This forces explicit error handling at compile time and prevents uncaught exceptions in production.
use Cbox\SystemMetrics\SystemMetrics;
$result = SystemMetrics::cpu(); // Returns Result<CpuSnapshot>
Basic Pattern
Check Before Using
$result = SystemMetrics::cpu();
if ($result->isSuccess()) {
$cpu = $result->getValue();
echo "CPU cores: {$cpu->coreCount()}\n";
} else {
$error = $result->getError();
echo "Error: {$error->getMessage()}\n";
}
Use Default Value
$cpu = SystemMetrics::cpu()->getValueOr(null);
if ($cpu === null) {
echo "Could not read CPU metrics\n";
} else {
echo "CPU cores: {$cpu->coreCount()}\n";
}
Functional Style
Callbacks
SystemMetrics::memory()
->onSuccess(function($mem) {
echo "Memory: {$mem->totalBytes} bytes\n";
})
->onFailure(function($error) {
error_log("Memory read failed: " . $error->getMessage());
});
Transformations
$result = SystemMetrics::cpu()->map(function($cpu) {
return [
'cores' => $cpu->coreCount(),
'busy_percentage' => ($cpu->total->busy() / $cpu->total->total()) * 100,
];
});
if ($result->isSuccess()) {
$data = $result->getValue(); // Array with 'cores' and 'busy_percentage'
}
Error Types
FileNotFoundException
File doesn't exist on the filesystem:
$result = SystemMetrics::cpu();
if ($result->isFailure()) {
$error = $result->getError();
if ($error instanceof FileNotFoundException) {
echo "/proc/stat not found - not on Linux?\n";
}
}
InsufficientPermissionsException
Lack permission to read file or execute command:
$result = SystemMetrics->memory();
if ($result->isFailure()) {
$error = $result->getError();
if ($error instanceof InsufficientPermissionsException) {
echo "Cannot read /proc/meminfo - permission denied\n";
}
}
ParseException
File format is unexpected or corrupted:
$result = SystemMetrics::cpu();
if ($result->isFailure()) {
$error = $result->getError();
if ($error instanceof ParseException) {
echo "/proc/stat has unexpected format\n";
}
}
UnsupportedOperatingSystemException
Operating system is not supported:
$result = SystemMetrics::cpu();
if ($result->isFailure()) {
$error = $result->getError();
if ($error instanceof UnsupportedOperatingSystemException) {
echo "Windows is not supported\n";
}
}
SystemMetricsException
Generic error (command failed, etc.):
$result = SystemMetrics::memory();
if ($result->isFailure()) {
$error = $result->getError();
if ($error instanceof SystemMetricsException) {
echo "System command failed: {$error->getMessage()}\n";
}
}
Complete Example
use Cbox\SystemMetrics\SystemMetrics;
use Cbox\SystemMetrics\Exceptions\{
FileNotFoundException,
InsufficientPermissionsException,
ParseException,
UnsupportedOperatingSystemException,
SystemMetricsException
};
$result = SystemMetrics::cpu();
if ($result->isSuccess()) {
$cpu = $result->getValue();
echo "CPU cores: {$cpu->coreCount()}\n";
} else {
$error = $result->getError();
match (true) {
$error instanceof FileNotFoundException =>
echo "❌ Required file not found: {$error->getMessage()}\n",
$error instanceof InsufficientPermissionsException =>
echo "❌ Permission denied: {$error->getMessage()}\n",
$error instanceof ParseException =>
echo "❌ Parse error: {$error->getMessage()}\n",
$error instanceof UnsupportedOperatingSystemException =>
echo "❌ Unsupported OS: {$error->getMessage()}\n",
default =>
echo "❌ Error: {$error->getMessage()}\n",
};
}
Best Practices
Always Check Results
// ✅ Good - explicit error handling
$result = SystemMetrics::cpu();
if ($result->isSuccess()) {
$cpu = $result->getValue();
// Use $cpu safely
}
// ❌ Bad - can throw if result is failure
$cpu = SystemMetrics::cpu()->getValue();
Provide Fallbacks
// ✅ Good - provides default
$cpu = SystemMetrics::cpu()->getValueOr(null);
// ✅ Good - handles failure
$memory = SystemMetrics::memory();
if ($memory->isFailure()) {
// Use estimated values or skip this feature
}
Log Failures
SystemMetrics::cpu()
->onFailure(function($error) {
error_log("Failed to read CPU: " . $error->getMessage());
error_log("Stack trace: " . $error->getTraceAsString());
});
Testing with Stubs
For testing, you can create Result objects:
use Cbox\SystemMetrics\DTO\Result;
// Success result
$result = Result::success($fakeCpuSnapshot);
// Failure result
$result = Result::failure(new FileNotFoundException('/proc/stat'));
Why Not Exceptions?
Traditional approach (exceptions):
- Can forget to catch, leading to uncaught exceptions in production
- Silent failures if caught too broadly
- No compile-time checking
Result<T> approach:
- Explicit handling required
- Failures are visible in type system
- Cannot accidentally ignore errors
- Functional programming patterns available
Related Documentation
- API Reference - All return types
- Custom Implementations - Creating custom sources