- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
521 lines
12 KiB
Markdown
521 lines
12 KiB
Markdown
# Error Reporting & Analytics
|
|
|
|
Das Error Reporting System bietet strukturierte Fehlerberichterstattung und erweiterte Analytics für das Framework. Es erfasst, analysiert und visualisiert Fehler mit umfassendem Kontext für bessere Debugging- und Monitoring-Möglichkeiten.
|
|
|
|
## Überblick
|
|
|
|
Das System implementiert folgende Funktionen:
|
|
|
|
- **Strukturierte Fehlerberichte** - Umfassende Kontext-Erfassung
|
|
- **Analytics Engine** - Trend-Analyse und Anomalie-Erkennung
|
|
- **Predictive Insights** - Vorhersagen und Empfehlungen
|
|
- **Context Processors** - Automatische Anreicherung mit Request/User-Kontext
|
|
- **Storage Interface** - Flexible Speicher-Implementierungen
|
|
- **Console Commands** - Management und Monitoring Tools
|
|
|
|
## Basic Usage
|
|
|
|
### Error Reporter
|
|
|
|
```php
|
|
use App\Framework\ErrorReporting\ErrorReporter;
|
|
|
|
$reporter = $container->get(ErrorReporter::class);
|
|
|
|
// Report an exception
|
|
$reportId = $reporter->reportThrowable($exception);
|
|
|
|
// Report manual error
|
|
$reportId = $reporter->reportError('error', 'Something went wrong', [
|
|
'user_action' => 'delete_file',
|
|
'file_id' => 123
|
|
]);
|
|
```
|
|
|
|
### Mit Request Context
|
|
|
|
```php
|
|
$contextualReporter = $reporter->withRequestContext(
|
|
method: 'POST',
|
|
route: '/api/users',
|
|
requestId: $requestId,
|
|
userAgent: $userAgent,
|
|
ipAddress: $clientIp
|
|
);
|
|
|
|
$reportId = $contextualReporter->reportThrowable($exception);
|
|
```
|
|
|
|
### Mit User Context
|
|
|
|
```php
|
|
$userReporter = $reporter->withUserContext(
|
|
userId: $user->getId(),
|
|
sessionId: $session->getId()
|
|
);
|
|
|
|
$reportId = $userReporter->reportError('warning', 'User action failed');
|
|
```
|
|
|
|
## Error Report Structure
|
|
|
|
```php
|
|
$report = ErrorReport::fromThrowable($exception)
|
|
->withUser($userId, $sessionId)
|
|
->withRequest($method, $route, $requestId, $userAgent, $ipAddress)
|
|
->withPerformance($executionTime, $memoryUsage)
|
|
->withTags(['api', 'payment'])
|
|
->withBreadcrumbs($breadcrumbs)
|
|
->withCustomData(['order_id' => 12345]);
|
|
```
|
|
|
|
### Report Properties
|
|
|
|
- **Basic Info**: ID, timestamp, level, message, exception class
|
|
- **Location**: File, line, stack trace
|
|
- **User Context**: User ID, session ID
|
|
- **Request Context**: Route, method, IP, user agent, request data
|
|
- **Performance**: Execution time, memory usage
|
|
- **Metadata**: Tags, breadcrumbs, custom data, environment info
|
|
- **Analytics**: Fingerprint, severity level
|
|
|
|
## Analytics Engine
|
|
|
|
### Anomalie-Erkennung
|
|
|
|
```php
|
|
use App\Framework\ErrorReporting\Analytics\ErrorAnalyticsEngine;
|
|
|
|
$analytics = $container->get(ErrorAnalyticsEngine::class);
|
|
|
|
$from = new DateTimeImmutable('-24 hours');
|
|
$to = new DateTimeImmutable();
|
|
|
|
// Detect anomalies and spikes
|
|
$anomalies = $analytics->detectAnomalies($from, $to);
|
|
|
|
foreach ($anomalies as $anomaly) {
|
|
echo "Anomaly detected: {$anomaly['type']} at {$anomaly['period']}\n";
|
|
echo "Count: {$anomaly['count']} (expected: {$anomaly['expected']})\n";
|
|
echo "Z-Score: {$anomaly['z_score']}\n";
|
|
}
|
|
```
|
|
|
|
### Error Velocity
|
|
|
|
```php
|
|
// Calculate rate of change
|
|
$velocity = $analytics->calculateErrorVelocity($from, $to);
|
|
|
|
$latest = end($velocity);
|
|
echo "Latest trend: {$latest['direction']} ({$latest['velocity_percent']}%)\n";
|
|
```
|
|
|
|
### Pattern Analysis
|
|
|
|
```php
|
|
$patterns = $analytics->identifyPatterns($from, $to);
|
|
|
|
// Route correlations
|
|
foreach ($patterns['route_correlations'] as $correlation) {
|
|
echo "Route {$correlation['route']}: {$correlation['total_errors']} errors\n";
|
|
echo "Clustered periods: {$correlation['clustered_periods']}\n";
|
|
}
|
|
|
|
// Time patterns
|
|
$timePatterns = $patterns['time_patterns'];
|
|
echo "Peak hour: {$timePatterns['peak_hour']}\n";
|
|
echo "Peak day: {$timePatterns['peak_day']}\n";
|
|
```
|
|
|
|
### Predictive Insights
|
|
|
|
```php
|
|
$predictions = $analytics->generatePredictiveInsights($from, $to);
|
|
|
|
$trend = $predictions['trend_prediction'];
|
|
echo "Trend: {$trend['trend']} (slope: {$trend['slope']})\n";
|
|
|
|
foreach ($trend['predictions'] as $prediction) {
|
|
echo "Period +{$prediction['period']}: ~{$prediction['predicted_count']} errors\n";
|
|
}
|
|
|
|
$risk = $predictions['risk_assessment'];
|
|
echo "Risk level: {$risk['level']} (factor: {$risk['risk_factor']})\n";
|
|
```
|
|
|
|
### Health Report
|
|
|
|
```php
|
|
$healthReport = $analytics->generateHealthReport($from, $to);
|
|
|
|
echo "Health Score: {$healthReport['health_score']}/100\n";
|
|
|
|
// Impact analysis
|
|
$impact = $healthReport['impact'];
|
|
echo "Affected users: {$impact['user_impact']['affected_users']}\n";
|
|
echo "Critical errors: {$impact['business_impact']['critical_errors']}\n";
|
|
|
|
// Recommendations
|
|
foreach ($healthReport['predictions']['recommendations'] as $rec) {
|
|
echo "[{$rec['priority']}] {$rec['message']}\n";
|
|
}
|
|
```
|
|
|
|
## Search & Filtering
|
|
|
|
```php
|
|
use App\Framework\ErrorReporting\ErrorReportCriteria;
|
|
|
|
// Recent critical errors
|
|
$criteria = ErrorReportCriteria::critical();
|
|
$reports = $reporter->findReports($criteria);
|
|
|
|
// Errors by user
|
|
$criteria = ErrorReportCriteria::byUser('user123');
|
|
$reports = $reporter->findReports($criteria);
|
|
|
|
// Complex search
|
|
$criteria = ErrorReportCriteria::recent(48) // Last 48 hours
|
|
->withLevels(['error', 'critical'])
|
|
->withEnvironment('production')
|
|
->withPagination(50, 0);
|
|
|
|
$reports = $reporter->findReports($criteria);
|
|
```
|
|
|
|
### Search Criteria Options
|
|
|
|
```php
|
|
$criteria = new ErrorReportCriteria(
|
|
from: $fromDate,
|
|
to: $toDate,
|
|
levels: ['error', 'critical'],
|
|
exceptions: ['DatabaseException', 'PaymentException'],
|
|
routes: ['/api/payment', '/api/orders'],
|
|
methods: ['POST', 'PUT'],
|
|
userId: 'user123',
|
|
environment: 'production',
|
|
tags: ['payment', 'critical'],
|
|
search: 'connection timeout',
|
|
fingerprint: 'abc123',
|
|
minSeverity: 2,
|
|
maxSeverity: 4,
|
|
limit: 100,
|
|
offset: 0,
|
|
orderBy: 'timestamp',
|
|
orderDir: 'DESC'
|
|
);
|
|
```
|
|
|
|
## Context Processors
|
|
|
|
### Request Context Processor
|
|
|
|
Automatische Anreicherung mit HTTP Request Informationen:
|
|
|
|
- Method, Route, User-Agent, IP-Adresse
|
|
- Request Data (GET, POST, JSON) - sanitized
|
|
- Execution Time, Memory Usage
|
|
- Tags (API, AJAX, Method)
|
|
|
|
### User Context Processor
|
|
|
|
Automatische Anreicherung mit User Informationen:
|
|
|
|
- User ID aus Session
|
|
- Session ID
|
|
- User Breadcrumbs
|
|
- Tags (authenticated/anonymous)
|
|
|
|
```php
|
|
use App\Framework\ErrorReporting\Processors\UserContextProcessor;
|
|
|
|
// Add breadcrumb from application code
|
|
UserContextProcessor::addBreadcrumb(
|
|
message: 'User clicked delete button',
|
|
category: 'user_action',
|
|
level: 'info',
|
|
data: ['file_id' => 123]
|
|
);
|
|
```
|
|
|
|
## HTTP Middleware
|
|
|
|
Automatische Fehlerberichterstattung für HTTP Requests:
|
|
|
|
```php
|
|
// Automatically registered via initializer
|
|
$app->addMiddleware(ErrorReportingMiddleware::class);
|
|
```
|
|
|
|
Das Middleware:
|
|
- Fängt alle ungefangenen Exceptions ab
|
|
- Fügt Request-Kontext automatisch hinzu
|
|
- Sanitized Request-Daten
|
|
- Bestimmt Client IP korrekt (X-Forwarded-For, etc.)
|
|
|
|
## Console Commands
|
|
|
|
### Statistiken anzeigen
|
|
|
|
```bash
|
|
# Last 24 hours (default)
|
|
php console.php errors:stats
|
|
|
|
# Last 48 hours
|
|
php console.php errors:stats 48
|
|
```
|
|
|
|
Zeigt:
|
|
- Total/Unique Errors
|
|
- Critical Error Count
|
|
- Error Rate & Health Score
|
|
- Errors by Level
|
|
- Top Exceptions & Routes
|
|
- Insights & Recommendations
|
|
|
|
### Advanced Analytics
|
|
|
|
```bash
|
|
# Advanced analytics report
|
|
php console.php errors:analytics 24
|
|
```
|
|
|
|
Zeigt:
|
|
- Anomaly Detection
|
|
- Error Velocity
|
|
- Pattern Analysis
|
|
- Predictive Insights
|
|
|
|
### Health Report
|
|
|
|
```bash
|
|
# Comprehensive health report
|
|
php console.php errors:health 24
|
|
```
|
|
|
|
Zeigt:
|
|
- Overall Health Score
|
|
- Key Metrics
|
|
- Impact Analysis
|
|
- Recommendations
|
|
|
|
### Search Errors
|
|
|
|
```bash
|
|
# Search by term
|
|
php console.php errors:search "database connection"
|
|
```
|
|
|
|
### Show Error Details
|
|
|
|
```bash
|
|
# Show detailed error report
|
|
php console.php errors:show <report-id>
|
|
```
|
|
|
|
### Cleanup
|
|
|
|
```bash
|
|
# Delete errors older than 30 days (default)
|
|
php console.php errors:cleanup
|
|
|
|
# Delete errors older than 7 days
|
|
php console.php errors:cleanup 7
|
|
```
|
|
|
|
## Environment Configuration
|
|
|
|
```env
|
|
# Enable/disable error reporting
|
|
ERROR_REPORTING_ENABLED=true
|
|
|
|
# Enable async processing via queue
|
|
ERROR_REPORTING_ASYNC=true
|
|
|
|
# Filter levels (comma-separated)
|
|
ERROR_REPORTING_FILTER_LEVELS=error,critical,alert,emergency
|
|
```
|
|
|
|
## Database Schema
|
|
|
|
Das System benötigt die `error_reports` Tabelle:
|
|
|
|
```bash
|
|
php console.php db:migrate
|
|
```
|
|
|
|
Die Migration erstellt eine optimierte Tabelle mit:
|
|
- Primary Key: String ID (32 chars)
|
|
- Indexes für häufige Queries
|
|
- JSON Felder für flexible Daten
|
|
- Analytics-Felder (fingerprint, severity_level)
|
|
|
|
## Storage Interface
|
|
|
|
Custom Storage Implementierungen möglich:
|
|
|
|
```php
|
|
use App\Framework\ErrorReporting\Storage\ErrorReportStorageInterface;
|
|
|
|
class RedisErrorReportStorage implements ErrorReportStorageInterface
|
|
{
|
|
public function store(ErrorReport $report): void
|
|
{
|
|
// Custom implementation
|
|
}
|
|
|
|
// ... other methods
|
|
}
|
|
|
|
// In initializer
|
|
$container->bind(ErrorReportStorageInterface::class, RedisErrorReportStorage::class);
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Structured Error Messages
|
|
|
|
```php
|
|
// Good - structured context
|
|
$reporter->reportError('error', 'Payment processing failed', [
|
|
'payment_id' => $paymentId,
|
|
'amount' => $amount,
|
|
'currency' => $currency,
|
|
'gateway_response' => $gatewayResponse
|
|
]);
|
|
|
|
// Avoid - unstructured message
|
|
$reporter->reportError('error', "Payment $paymentId failed for $amount $currency");
|
|
```
|
|
|
|
### 2. Appropriate Log Levels
|
|
|
|
```php
|
|
// Critical system failures
|
|
$reporter->reportThrowable($exception, 'critical');
|
|
|
|
// Business logic errors
|
|
$reporter->reportThrowable($exception, 'error');
|
|
|
|
// Recoverable issues
|
|
$reporter->reportError('warning', 'Deprecated API used');
|
|
|
|
// Development info
|
|
$reporter->reportError('info', 'Cache miss occurred');
|
|
```
|
|
|
|
### 3. Sensitive Data Handling
|
|
|
|
```php
|
|
// Data is automatically sanitized by processors
|
|
// But be explicit about sensitive data
|
|
$reporter->reportError('error', 'Authentication failed', [
|
|
'username' => $username,
|
|
'ip_address' => $ip,
|
|
// Don't include: password, tokens, etc.
|
|
]);
|
|
```
|
|
|
|
### 4. Custom Tags for Filtering
|
|
|
|
```php
|
|
$report = ErrorReport::fromThrowable($exception)
|
|
->withTags(['payment', 'external_api', 'critical']);
|
|
```
|
|
|
|
### 5. Breadcrumbs for Context
|
|
|
|
```php
|
|
// Add breadcrumbs throughout user journey
|
|
UserContextProcessor::addBreadcrumb('User logged in');
|
|
UserContextProcessor::addBreadcrumb('Started checkout process');
|
|
UserContextProcessor::addBreadcrumb('Selected payment method', 'action', 'info', [
|
|
'method' => 'credit_card'
|
|
]);
|
|
|
|
// Error report will include full journey
|
|
```
|
|
|
|
## Performance Considerations
|
|
|
|
1. **Async Processing** - Enable für Production (`ERROR_REPORTING_ASYNC=true`)
|
|
2. **Data Sanitization** - Automatic für Request Data
|
|
3. **Storage Optimization** - Indexes für häufige Queries
|
|
4. **Cleanup Strategy** - Regular cleanup alter Reports
|
|
5. **Memory Usage** - Limited Context Data Size
|
|
|
|
## Security Considerations
|
|
|
|
1. **Data Sanitization** - Sensitive Data wird automatisch entfernt
|
|
2. **Access Control** - Console Commands benötigen entsprechende Rechte
|
|
3. **Storage Security** - Database Access Controls
|
|
4. **IP Address Handling** - Respects Privacy Regulations
|
|
5. **Session Security** - Nur Session IDs, keine Session Daten
|
|
|
|
## Integration Examples
|
|
|
|
### Mit Custom Exception Handler
|
|
|
|
```php
|
|
class CustomExceptionHandler
|
|
{
|
|
public function __construct(
|
|
private ErrorReporter $reporter
|
|
) {}
|
|
|
|
public function handle(Throwable $exception): void
|
|
{
|
|
// Report the error
|
|
$this->reporter->reportThrowable($exception);
|
|
|
|
// Continue with normal error handling
|
|
$this->originalHandler->handle($exception);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Mit Business Logic
|
|
|
|
```php
|
|
class PaymentService
|
|
{
|
|
public function processPayment(Payment $payment): PaymentResult
|
|
{
|
|
try {
|
|
return $this->gateway->process($payment);
|
|
} catch (PaymentException $e) {
|
|
// Report with business context
|
|
$this->reporter->reportThrowable($e, 'error', [
|
|
'payment_id' => $payment->getId(),
|
|
'amount' => $payment->getAmount(),
|
|
'gateway' => $this->gateway->getName(),
|
|
]);
|
|
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Mit Background Jobs
|
|
|
|
```php
|
|
class EmailJob
|
|
{
|
|
public function handle(): void
|
|
{
|
|
try {
|
|
$this->sendEmails();
|
|
} catch (Throwable $e) {
|
|
$this->reporter->reportThrowable($e, 'error', [
|
|
'job' => 'email_sending',
|
|
'batch_size' => count($this->emails),
|
|
]);
|
|
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|
|
``` |