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:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,218 @@
# Error Handling & Debugging
This guide covers error handling patterns and debugging strategies in the framework.
## Exception Handling
All custom exceptions in the framework must extend `FrameworkException` to ensure consistent error handling, logging, and recovery mechanisms.
### The FrameworkException System
The framework provides a sophisticated exception system with:
- **ExceptionContext**: Rich context information for debugging
- **ErrorCode**: Categorized error codes with recovery hints
- **RetryAfter**: Support for recoverable operations
- **Fluent Interface**: Easy context building
### Creating Custom Exceptions
```php
namespace App\Domain\User\Exceptions;
use App\Framework\Exception\FrameworkException;
use App\Framework\Exception\ErrorCode;
use App\Framework\Exception\ExceptionContext;
final class UserNotFoundException extends FrameworkException
{
public static function byId(UserId $id): self
{
return self::create(
ErrorCode::ENTITY_NOT_FOUND,
"User with ID '{$id->toString()}' not found"
)->withData([
'user_id' => $id->toString(),
'search_type' => 'by_id'
]);
}
public static function byEmail(Email $email): self
{
$context = ExceptionContext::forOperation('user.lookup', 'UserRepository')
->withData(['email' => $email->getMasked()]);
return self::fromContext(
"User with email not found",
$context,
ErrorCode::ENTITY_NOT_FOUND
);
}
}
```
### Using ErrorCode Enum
```php
// The framework provides predefined error codes:
ErrorCode::DB_CONNECTION_FAILED // Database errors
ErrorCode::AUTH_TOKEN_EXPIRED // Authentication errors
ErrorCode::VAL_BUSINESS_RULE_VIOLATION // Validation errors
ErrorCode::HTTP_RATE_LIMIT_EXCEEDED // HTTP errors
ErrorCode::SEC_CSRF_TOKEN_INVALID // Security errors
// Using error codes in exceptions:
throw FrameworkException::create(
ErrorCode::DB_QUERY_FAILED,
"Failed to execute user query"
)->withContext(
ExceptionContext::forOperation('user.find', 'UserRepository')
->withData(['query' => 'SELECT * FROM users WHERE id = ?'])
->withDebug(['bind_params' => [$userId]])
);
```
### Exception Context Building
```php
// Method 1: Using factory methods
$exception = FrameworkException::forOperation(
'payment.process',
'PaymentService',
'Payment processing failed',
ErrorCode::PAYMENT_GATEWAY_ERROR
)->withData([
'amount' => $amount->toArray(),
'gateway' => 'stripe',
'customer_id' => $customerId
])->withMetadata([
'attempt' => 1,
'idempotency_key' => $idempotencyKey
]);
// Method 2: Building context separately
$context = ExceptionContext::empty()
->withOperation('order.validate', 'OrderService')
->withData([
'order_id' => $orderId,
'total' => $total->toDecimal()
])
->withDebug([
'validation_rules' => ['min_amount', 'max_items'],
'failed_rule' => 'min_amount'
]);
throw FrameworkException::fromContext(
'Order validation failed',
$context,
ErrorCode::VAL_BUSINESS_RULE_VIOLATION
);
```
### Recoverable Exceptions
```php
// Creating recoverable exceptions with retry hints
final class RateLimitException extends FrameworkException
{
public static function exceeded(int $retryAfter): self
{
return self::create(
ErrorCode::HTTP_RATE_LIMIT_EXCEEDED,
'API rate limit exceeded'
)->withRetryAfter($retryAfter)
->withData(['retry_after_seconds' => $retryAfter]);
}
}
// Using in code
try {
$response = $apiClient->request($endpoint);
} catch (RateLimitException $e) {
if ($e->isRecoverable()) {
$waitTime = $e->getRetryAfter();
// Schedule retry after $waitTime seconds
}
throw $e;
}
```
### Exception Categories
```php
// Check exception category for handling strategies
try {
$result = $operation->execute();
} catch (FrameworkException $e) {
if ($e->isCategory('AUTH')) {
// Handle authentication errors
return $this->redirectToLogin();
}
if ($e->isCategory('VAL')) {
// Handle validation errors
return $this->validationErrorResponse($e);
}
if ($e->isErrorCode(ErrorCode::DB_CONNECTION_FAILED)) {
// Handle specific database connection errors
$this->notifyOps($e);
}
throw $e;
}
```
### Simple Exceptions for Quick Use
```php
// When you don't need the full context system
throw FrameworkException::simple('Quick error message');
// With previous exception
} catch (\PDOException $e) {
throw FrameworkException::simple(
'Database operation failed',
$e,
500
);
}
```
### Exception Data Sanitization
The framework automatically sanitizes sensitive data in exceptions:
```php
// Sensitive keys are automatically redacted
$exception->withData([
'username' => 'john@example.com',
'password' => 'secret123', // Will be logged as '[REDACTED]'
'api_key' => 'sk_live_...' // Will be logged as '[REDACTED]'
]);
```
### Best Practices
1. **Always extend FrameworkException** for custom exceptions
2. **Use ErrorCode enum** for categorizable errors
3. **Provide rich context** with operation, component, and data
4. **Use factory methods** for consistent exception creation
5. **Sanitize sensitive data** (automatic for common keys)
6. **Make exceptions domain-specific** (UserNotFoundException vs generic NotFoundException)
7. **Include recovery hints** for recoverable errors
## Logging Best Practices
TODO: Document logging patterns and levels
## Debug Strategies
TODO: Document debugging approaches and tools
## Error Recovery Patterns
TODO: Document error recovery and graceful degradation
## Common Error Scenarios
TODO: List common errors and solutions