From 911bb9ff8c13e8e7ae0f1dfd6fd0f21d73d54be1 Mon Sep 17 00:00:00 2001 From: Victor Leite Date: Wed, 4 Jun 2025 15:00:38 -0300 Subject: [PATCH] Update code blocks on the README file --- README.md | 282 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 157 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 5d3de44..bdeb6ea 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ class UserController extends Controller { // Core usage - automatic class path resolution Monitor::from($this)->info('User logged in', ['user_id' => 123]); - + // Produces: [App:Http:Controllers:UserController] User logged in // With automatic enrichment: trace ID, timing, memory usage } @@ -109,11 +109,15 @@ class PaymentService public function processPayment($amount) { // Monitor a critical operation using $this for automatic resolution - return Monitor::ccp($this, function () use ($amount) { - // Your critical code here - return $this->chargeCard($amount); - }, ['amount' => $amount, 'currency' => 'USD']); - + return Monitor::ccp( + name: $this, + callback: function () use ($amount) { + // Your critical code here + return $this->chargeCard($amount); + }, + context: ['amount' => $amount, 'currency' => 'USD'] + ); + // Automatically logs: // - CCP start: [PaymentService] Starting operation // - CCP success: [PaymentService] Operation completed (125ms) @@ -133,30 +137,33 @@ class PaymentService { public function processPayment($amount, $userId) { - return Monitor::ccp('payment_processing', function () use ($amount) { - return $this->chargeCard($amount); - }, - // Context data - ['amount' => $amount, 'user_id' => $userId, 'currency' => 'USD'], - // Failure escalation callback - function ($exception, $context) { - // Send immediate alerts to operations team - NotificationService::alertOps('Critical payment failure', [ - 'exception' => $exception->getMessage(), - 'user_id' => $context['user_id'], - 'amount' => $context['amount'], - 'trace_id' => $context['trace_id'] - ]); - - // Open circuit breaker to prevent cascade failures - CircuitBreaker::open('payment_service', '5 minutes'); - - // Mark service as degraded in health checks - HealthCheck::markDegraded('payment', 'Payment processing failure'); - - // Trigger fallback mechanism - $this->activatePaymentFallback(); - }); + return Monitor::ccp( + name: 'payment_processing', + callback: function () use ($amount) { + return $this->chargeCard($amount); + }, + // Context data + context: ['amount' => $amount, 'user_id' => $userId, 'currency' => 'USD'], + // Failure escalation callback + onFail: function ($exception, $context) { + // Send immediate alerts to operations team + NotificationService::alertOps('Critical payment failure', [ + 'exception' => $exception->getMessage(), + 'user_id' => $context['user_id'], + 'amount' => $context['amount'], + 'trace_id' => $context['trace_id'] + ]); + + // Open circuit breaker to prevent cascade failures + CircuitBreaker::open('payment_service', '5 minutes'); + + // Mark service as degraded in health checks + HealthCheck::markDegraded('payment', 'Payment processing failure'); + + // Trigger fallback mechanism + $this->activatePaymentFallback(); + }, + ); } } ``` @@ -165,64 +172,85 @@ class PaymentService ```php // Database connection CCP with fallback -Monitor::ccp('database_write', function () use ($data) { - return DB::table('orders')->insert($data); -}, ['table' => 'orders'], function ($exception, $context) { - // Switch to read replica or cache - Cache::put("failed_write_{$context['trace_id']}", $data, 3600); - QueueService::dispatch(new RetryDatabaseWrite($data)); -}); +Monitor::ccp( + name: 'database_write', + callback: function () use ($data) { + return DB::table('orders')->insert($data); + }, + context: ['table' => 'orders'], + onFail: function ($exception, $context) { + // Switch to read replica or cache + Cache::put("failed_write_{$context['trace_id']}", $data, 3600); + QueueService::dispatch(new RetryDatabaseWrite($data)); + }, +); // External API CCP with circuit breaker -Monitor::ccp('external_api_call', function () use ($apiData) { - return $this->thirdPartyService->call($apiData); -}, ['service' => 'third_party'], function ($exception, $context) { - // Open circuit breaker - CircuitBreaker::open('third_party_service'); - - // Use cached response if available - if ($cached = Cache::get("api_fallback_{$apiData['key']}")) { - return $cached; - } - - // Alert monitoring systems - Monitoring::increment('api.third_party.failures'); -}); +Monitor::ccp( + name: 'external_api_call', + callback: function () use ($apiData) { + return $this->thirdPartyService->call($apiData); + }, + context: ['service' => 'third_party'], + onFail: function ($exception, $context) { + // Open circuit breaker + CircuitBreaker::open('third_party_service'); + + // Use cached response if available + if ($cached = Cache::get("api_fallback_{$apiData['key']}")) { + return $cached; + } + + // Alert monitoring systems + Monitoring::increment('api.third_party.failures'); + }, +); // Critical business process CCP -Monitor::ccp('order_fulfillment', function () use ($order) { - return $this->fulfillOrder($order); -}, ['order_id' => $order->id], function ($exception, $context) { - // Immediate executive notification for critical business impact - NotificationService::alertExecutives('Order fulfillment failure', $context); - - // Create incident ticket - IncidentManagement::createCriticalIncident([ - 'title' => 'Order Fulfillment Failure', - 'context' => $context, - 'priority' => 'P1' - ]); - - // Trigger manual review process - ManualReviewQueue::add($order, 'fulfillment_failure'); -}); +Monitor::ccp( + name: 'order_fulfillment', + callback: function () use ($order) { + return $this->fulfillOrder($order); + }, + context: ['order_id' => $order->id], + onFail: function ($exception, $context) { + // Immediate executive notification for critical business impact + NotificationService::alertExecutives('Order fulfillment failure', $context); + + // Create incident ticket + IncidentManagement::createCriticalIncident([ + 'title' => 'Order Fulfillment Failure', + 'context' => $context, + 'priority' => 'P1' + ]); + + // Trigger manual review process + ManualReviewQueue::add($order, 'fulfillment_failure'); + }, +); ``` **Callback Safety Features:** The `onFail` callback is executed safely: + - **Original exception preserved** - The callback doesn't interfere with the primary exception flow - **Callback exceptions handled** - If the callback itself fails, it's logged separately but doesn't mask the original failure - **Full context provided** - The callback receives both the exception and complete operation context ```php -Monitor::ccp('safe_callback_example', function () { - throw new RuntimeException('Primary failure'); -}, [], function ($exception, $context) { - // Even if this callback fails, the original RuntimeException is still thrown - throw new Exception('Callback failed'); - // This would be logged as FAILURE_CALLBACK_ERROR but won't affect the primary flow -}); +Monitor::ccp( + name: 'safe_callback_example', + callback: function () { + throw new RuntimeException('Primary failure'); + }, + context: [], + onFail: function ($exception, $context) { + // Even if this callback fails, the original RuntimeException is still thrown + throw new Exception('Callback failed'); + // This would be logged as FAILURE_CALLBACK_ERROR but won't affect the primary flow + }, +); ``` ### Distributed Tracing @@ -236,13 +264,13 @@ class OrderController extends Controller { // Start a trace (typically in middleware or service provider) Monitor::trace()->start(); - + // All subsequent logging will include the same trace ID Monitor::from($this)->info('Processing order'); - + $this->paymentService->charge($amount); // PaymentService logs will have the same trace ID - + return response()->json(['success' => true]); } } @@ -268,12 +296,12 @@ class DataProcessor { // Time operations Monitor::time()->start(); - + // Your processing code here... $this->processData(); - + $elapsed = Monitor::time()->elapsed(); // Milliseconds - + Monitor::from($this)->info('Dataset processed', [ 'processing_time_ms' => $elapsed ]); @@ -298,7 +326,8 @@ Simplify long class names in logs with cascading replacements: ``` **Examples:** -- `App\Http\Controllers\Admin\UserController` → `Admin:UserController` + +- `App\Http\Controllers\Admin\UserController` → `Admin:UserController` - `App\Http\Controllers\HomeController` → `Web:HomeController` - `App\Services\Payment\StripeService` → `Payment:StripeService` - `App\Jobs\SendEmailJob` → `Job:SendEmailJob` @@ -314,11 +343,11 @@ The separator controls how namespace segments are converted: **Examples with different separators:** -| Class | Separator | Result | -|-------|-----------|--------| -| `App\Http\Controllers\UserController` | `:` | `App:Http:Controllers:UserController` | -| `App\Http\Controllers\UserController` | `.` | `App.Http.Controllers.UserController` | -| `App\Http\Controllers\UserController` | `-` | `App-Http-Controllers-UserController` | +| Class | Separator | Result | +| ------------------------------------- | --------- | ------------------------------------- | +| `App\Http\Controllers\UserController` | `:` | `App:Http:Controllers:UserController` | +| `App\Http\Controllers\UserController` | `.` | `App.Http.Controllers.UserController` | +| `App\Http\Controllers\UserController` | `-` | `App-Http-Controllers-UserController` | ### Origin Wrappers @@ -331,18 +360,19 @@ The wrapper affects the final visual appearance in logs: **All wrapper options:** -| Wrapper | Example Output | -|---------|----------------| -| `'none'` | `UserController message text` | -| `'square'` | `[UserController] message text` | -| `'curly'` | `{UserController} message text` | -| `'round'` | `(UserController) message text` | -| `'angle'` | ` message text` | -| `'double'` | `"UserController" message text` | -| `'single'` | `'UserController' message text` | +| Wrapper | Example Output | +| ------------- | ------------------------------- | +| `'none'` | `UserController message text` | +| `'square'` | `[UserController] message text` | +| `'curly'` | `{UserController} message text` | +| `'round'` | `(UserController) message text` | +| `'angle'` | ` message text` | +| `'double'` | `"UserController" message text` | +| `'single'` | `'UserController' message text` | | `'asterisks'` | `*UserController* message text` | **Combined Example:** + ```php // With these settings: 'origin_path_replacers' => ['App\\Http\\Controllers\\' => 'Web\\'], @@ -350,7 +380,7 @@ The wrapper affects the final visual appearance in logs: 'origin_path_wrapper' => 'square', // Class: App\Http\Controllers\UserController -// Step 1 (replacer): Web\UserController +// Step 1 (replacer): Web\UserController // Step 2 (separator): Web:UserController // Step 3 (wrapper): [Web:UserController] // Final log: "[Web:UserController] User login successful" @@ -448,7 +478,7 @@ The middleware requires manual registration to give you control over where it ru // bootstrap/app.php ->withMiddleware(function (Middleware $middleware) { $middleware->append(\Kirschbaum\Monitor\Http\Middleware\StartMonitorTrace::class); - + // Or prepend to run it early in the pipeline $middleware->prepend(\Kirschbaum\Monitor\Http\Middleware\StartMonitorTrace::class); }) @@ -463,7 +493,7 @@ For web-only or API-only registration: $middleware->web(append: [ \Kirschbaum\Monitor\Http\Middleware\StartMonitorTrace::class, ]); - + // API routes only $middleware->api(append: [ \Kirschbaum\Monitor\Http\Middleware\StartMonitorTrace::class, @@ -509,11 +539,11 @@ class UserService { // Primary pattern - pass $this for automatic resolution Monitor::from($this)->info('Creating user', ['email' => $userData['email']]); - + $user = User::create($userData); - + Monitor::from($this)->info('User created successfully', ['user_id' => $user->id]); - + return $user; } } @@ -523,7 +553,7 @@ class ApiController extends Controller public function __construct(private UserService $userService) { } - + public function store(Request $request) { // Controller usage with $this @@ -531,11 +561,11 @@ class ApiController extends Controller 'endpoint' => $request->path(), 'method' => $request->method() ]); - + $user = $this->userService->createUser($request->validated()); - + Monitor::from($this)->info('API request completed', ['user_id' => $user->id]); - + return response()->json($user); } } @@ -633,7 +663,7 @@ class ProcessPaymentJob extends BaseJob ]); // Your payment processing logic here... - + Monitor::from($this)->info('Payment job completed successfully'); } } @@ -648,20 +678,21 @@ class PaymentController extends Controller { // Start trace for the request Monitor::trace()->start(); - + Monitor::from($this)->info('Payment request received'); - + // Dispatch job - trace ID is automatically captured ProcessPaymentJob::dispatch($request->user()->id, $request->amount); - + Monitor::from($this)->info('Payment job dispatched'); - + return response()->json(['status' => 'processing']); } } ``` This pattern ensures that: + - **Trace continuity** - All logs from the job will have the same trace ID as the original request - **Error handling** - Jobs fail fast if dispatched without proper trace context - **Automatic injection** - The middleware automatically restores trace context when the job runs @@ -723,7 +754,7 @@ class ProcessDataCommand extends TraceAwareCommand protected function process(): int { $batchSize = (int) $this->option('batch'); - + Monitor::from($this)->info('Starting data processing', [ 'batch_size' => $batchSize ]); @@ -731,15 +762,15 @@ class ProcessDataCommand extends TraceAwareCommand try { // Your processing logic here $this->processDataInBatches($batchSize); - + Monitor::from($this)->info('Data processing completed successfully'); - + return Command::SUCCESS; } catch (\Exception $e) { Monitor::from($this)->error('Data processing failed', [ 'error' => $e->getMessage() ]); - + return Command::FAILURE; } } @@ -752,6 +783,7 @@ class ProcessDataCommand extends TraceAwareCommand ``` This architectural pattern provides: + - **Consistent trace initialization** - Every command automatically gets a trace ID - **Standardized logging** - Command start, arguments, and options are always logged - **Enforced structure** - The abstract `process()` method ensures developers implement the pattern correctly @@ -778,17 +810,17 @@ Monitor produces structured JSON logs with automatic enrichment: ```json { - "level": "info", - "event": "UserController:info", - "message": "[UserController] User login successful", - "trace_id": "9d2b4e8f-3a1c-4d5e-8f2a-1b3c4d5e6f7g", - "context": { - "user_id": 123, - "ip_address": "192.168.1.1" - }, - "timestamp": "2024-01-15T14:30:45.123Z", - "duration_ms": 1245.67, - "memory_mb": 45.23 + "level": "info", + "event": "UserController:info", + "message": "[UserController] User login successful", + "trace_id": "9d2b4e8f-3a1c-4d5e-8f2a-1b3c4d5e6f7g", + "context": { + "user_id": 123, + "ip_address": "192.168.1.1" + }, + "timestamp": "2024-01-15T14:30:45.123Z", + "duration_ms": 1245.67, + "memory_mb": 45.23 } ```