# API Integration Debugging Example Learn how to use ChronoTrace to debug external API integrations, identify failures, optimize response times, and implement robust error handling. --- ## 🎯 Scenario: Payment Gateway Integration Issues Your payment processing system is experiencing intermittent failures and slow response times, causing checkout failures and poor user experience. ### The Problem - Payment API calls failing randomly (5-10% failure rate) - Slow payment processing (3-8 seconds) - Timeout errors during peak hours - Inconsistent error responses - Users getting charged but orders not completing --- ## 📋 Step 1: Enable API Monitoring Configure ChronoTrace to capture detailed HTTP events for payment integration: ```bash # Target payment-related routes CHRONOTRACE_MODE=targeted ``` ```php // config/chronotrace.php 'targeted_routes' => [ 'checkout/*', 'api/payments/*', 'api/orders/*/payment', 'webhooks/payment/*', ], 'http' => [ 'enabled' => true, 'include_request_body' => true, 'include_response_body' => true, 'max_body_size' => 128 * 1024, // 128KB for payment data 'timeout_threshold' => 5000, // Flag requests >5s ], ``` --- ## 🚀 Step 2: Capture Payment Failures Let's generate some payment transactions to capture both successful and failed scenarios: ```bash # Start recording payment API calls php artisan chronotrace:record --routes="*payment*" --duration=1h --sample-rate=1.0 # Monitor in real-time tail -f storage/logs/laravel.log | grep -i payment ``` --- ## 🔍 Step 3: Analyze Failed Payments List traces to identify payment failures: ```bash # Find failed payment attempts php artisan chronotrace:list --route="*payment*" --status=error --limit=10 # Example output showing various failure types: ┌────────────┬─────────────────────┬────────┬──────────┬─────────────────────────┬──────────┐ │ Trace ID │ Timestamp │ Method │ Status │ Route │ Duration │ ├────────────┼─────────────────────┼────────┼──────────┼─────────────────────────┼──────────┤ │ fail_001 │ 2024-08-06 14:30:15 │ POST │ 500 │ api/payments/process │ 30,000ms │ │ fail_002 │ 2024-08-06 14:32:42 │ POST │ 422 │ api/payments/process │ 156ms │ │ fail_003 │ 2024-08-06 14:35:18 │ POST │ 500 │ api/payments/process │ 8,456ms │ │ timeout1 │ 2024-08-06 14:37:25 │ POST │ 504 │ api/payments/process │ 30,000ms │ └────────────┴─────────────────────┴────────┴──────────┴─────────────────────────┴──────────┘ ``` --- ## 📊 Step 4: Deep Dive into Payment API Issues Let's analyze a timeout failure in detail: ```bash # Analyze timeout failure focusing on HTTP events php artisan chronotrace:replay timeout1 --filter=http ``` ### Timeout Failure Analysis ``` ┌─ REQUEST INFORMATION ────────────────────────────────────────┐ │ Trace ID: timeout1 │ │ Method: POST /api/payments/process │ │ Status: 504 Gateway Timeout │ │ Duration: 30,000ms │ │ Memory: 25MB │ │ User: customer_789 │ │ Order ID: ORD-2024-08-06-12345 │ └──────────────────────────────────────────────────────────────┘ ┌─ HTTP EVENTS (4 requests) ───────────────────────────────────┐ │ [+0ms] POST https://api.stripe.com/v1/payment_intents (30,000ms) ❌ TIMEOUT │ Request Headers: │ Authorization: Bearer sk_live_[REDACTED] │ Content-Type: application/x-www-form-urlencoded │ Idempotency-Key: idem_2024080614301512345 │ Request Body: │ amount=29999¤cy=usd&payment_method=pm_1234567890 │ &confirm=true&return_url=https://example.com/return │ Response: TIMEOUT_ERROR │ Connection: timeout after 30.000s │ │ [+30,100ms] POST https://api.stripe.com/v1/payment_intents (15,234ms) ⚠️ RETRY │ Request: Same as above (automatic retry) │ Response Status: 429 Too Many Requests │ Response Body: {"error": {"type": "rate_limit_error", │ "message": "Too many requests"}} │ │ [+45,500ms] GET https://api.stripe.com/v1/payment_intents/pi_1234567890 (2,345ms) │ Request: GET payment status after timeout │ Response Status: 200 OK │ Response Body: {"status": "succeeded", "amount": 29999, │ "charges": {"data": [{"paid": true}]}} │ ⚠️ Payment actually succeeded but we didn't know! │ │ [+48,000ms] POST https://webhook.site/test-endpoint (567ms) │ Request: Error notification webhook │ Response Status: 200 OK │ Note: Notifying about "failed" payment that actually succeeded └──────────────────────────────────────────────────────────────┘ ``` ### 🔴 Issues Identified 1. **Timeout Configuration**: 30-second timeout too long for user experience 2. **No Retry Strategy**: Automatic retry hitting rate limits 3. **Status Checking**: No proper status verification after timeout 4. **Double Charging Risk**: Payment succeeded but system thought it failed 5. **Poor Error Handling**: Generic timeout response to user --- ## 🛠️ Step 5: Fix API Integration Issues ### Issue 1: Implement Proper Timeout and Retry Strategy **Before (problematic code):** ```php // PaymentService.php - Poor timeout handling public function processPayment($paymentData) { $response = Http::timeout(30) // Too long! ->post('https://api.stripe.com/v1/payment_intents', $paymentData); if ($response->failed()) { throw new PaymentException('Payment failed'); } return $response->json(); } ``` **After (optimized code):** ```php // PaymentService.php - Proper timeout and retry strategy public function processPayment($paymentData) { return $this->withRetry(function () use ($paymentData) { return Http::timeout(10) // Shorter timeout ->retry(2, 1000, function ($exception, $request) { // Only retry on specific conditions return $exception instanceof ConnectException || $this->isRetryableError($exception); }) ->withHeaders([ 'Idempotency-Key' => $this->generateIdempotencyKey($paymentData), ]) ->post('https://api.stripe.com/v1/payment_intents', $paymentData); }); } private function withRetry($callback, $maxAttempts = 3) { $attempt = 1; while ($attempt <= $maxAttempts) { try { $response = $callback(); if ($response->successful()) { return $response->json(); } // Handle specific error cases if ($response->status() === 429) { // Rate limit - wait and retry sleep(pow(2, $attempt)); // Exponential backoff $attempt++; continue; } if ($this->isRetryableError($response)) { $attempt++; continue; } // Non-retryable error throw new PaymentException($response->json()['error']['message'] ?? 'Payment failed'); } catch (ConnectException $e) { if ($attempt === $maxAttempts) { return $this->handleTimeout($paymentData); } $attempt++; sleep(1); } } } ``` ### Issue 2: Implement Timeout Recovery ```php // Handle timeout scenarios properly private function handleTimeout($paymentData) { // Check if payment actually succeeded $paymentIntent = $this->checkPaymentStatus($paymentData['payment_intent_id']); if ($paymentIntent && $paymentIntent['status'] === 'succeeded') { Log::info('Payment succeeded despite timeout', [ 'payment_intent_id' => $paymentIntent['id'], 'amount' => $paymentIntent['amount'] ]); return $paymentIntent; } // Payment truly failed or is still processing throw new PaymentTimeoutException( 'Payment processing timeout. Please check your payment status.', ['payment_intent_id' => $paymentData['payment_intent_id']] ); } private function checkPaymentStatus($paymentIntentId) { try { $response = Http::timeout(5) ->get("https://api.stripe.com/v1/payment_intents/{$paymentIntentId}"); return $response->successful() ? $response->json() : null; } catch (Exception $e) { Log::error('Failed to check payment status', [ 'payment_intent_id' => $paymentIntentId, 'error' => $e->getMessage() ]); return null; } } ``` ### Issue 3: Add Circuit Breaker Pattern ```php // Prevent cascading failures class PaymentCircuitBreaker { private $failureThreshold = 5; private $timeoutSeconds = 60; public function execute($callback) { $failures = Cache::get('payment_failures', 0); $lastFailure = Cache::get('payment_last_failure'); // Circuit is open - fast fail if ($failures >= $this->failureThreshold) { if ($lastFailure && now()->diffInSeconds($lastFailure) < $this->timeoutSeconds) { throw new CircuitBreakerOpenException('Payment service temporarily unavailable'); } // Reset circuit breaker after timeout Cache::forget('payment_failures'); Cache::forget('payment_last_failure'); } try { $result = $callback(); // Success - reset failure count Cache::forget('payment_failures'); Cache::forget('payment_last_failure'); return $result; } catch (Exception $e) { // Increment failure count Cache::put('payment_failures', $failures + 1, 300); Cache::put('payment_last_failure', now(), 300); throw $e; } } } ``` ### Issue 4: Implement Async Payment Processing ```php // PaymentController.php - Async processing for better UX public function processPayment(Request $request) { $paymentData = $this->validatePaymentData($request); // Start async payment processing $job = ProcessPaymentJob::dispatch($paymentData) ->onQueue('payments') ->delay(now()->addSeconds(1)); return response()->json([ 'status' => 'processing', 'job_id' => $job->getJobId(), 'polling_url' => route('payment.status', ['job' => $job->getJobId()]), 'estimated_time' => 30 // seconds ]); } // ProcessPaymentJob.php class ProcessPaymentJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function handle(PaymentService $paymentService) { try { $result = $paymentService->processPayment($this->paymentData); // Broadcast success broadcast(new PaymentProcessedEvent($this->paymentData['order_id'], $result)); } catch (PaymentTimeoutException $e) { // Handle timeout - check status later CheckPaymentStatusJob::dispatch($this->paymentData)->delay(now()->addMinutes(2)); } catch (Exception $e) { // Handle failure broadcast(new PaymentFailedEvent($this->paymentData['order_id'], $e->getMessage())); throw $e; // Re-throw to trigger retry mechanism } } } ``` --- ## ✅ Step 6: Test the Improved Integration After implementing fixes, let's test the improved payment system: ```bash # Record new payment traces with fixes php artisan chronotrace:record --routes="*payment*" --duration=30m # Simulate various payment scenarios php artisan payment:test --scenarios=success,timeout,rate-limit,network-error ``` ### Improved Performance Results ```bash # Check improved payment processing php artisan chronotrace:list --route="*payment*" --since="30 minutes ago" # Results showing improvements: ┌────────────┬─────────────────────┬────────┬──────────┬─────────────────────────┬──────────┐ │ Trace ID │ Timestamp │ Method │ Status │ Route │ Duration │ ├────────────┼─────────────────────┼────────┼──────────┼─────────────────────────┼──────────┤ │ good_001 │ 2024-08-06 16:30:15 │ POST │ 200 │ api/payments/process │ 1,245ms │ │ good_002 │ 2024-08-06 16:32:42 │ POST │ 200 │ api/payments/process │ 2,156ms │ │ timeout2 │ 2024-08-06 16:35:18 │ POST │ 200 │ api/payments/process │ 10,567ms │ └────────────┴─────────────────────┴────────┴──────────┴─────────────────────────┴──────────┘ ``` ### Analyze Improved Timeout Handling ```bash php artisan chronotrace:replay timeout2 --filter=http ``` ``` ┌─ HTTP EVENTS (3 requests) ───────────────────────────────────┐ │ [+0ms] POST https://api.stripe.com/v1/payment_intents (10,000ms) ⚠️ TIMEOUT │ Request: Same payment data with proper idempotency │ Response: TIMEOUT_ERROR (expected with 10s timeout) │ │ [+10,100ms] GET https://api.stripe.com/v1/payment_intents/pi_1234567890 (234ms) ✅ │ Request: Status check after timeout │ Response Status: 200 OK │ Response: {"status": "succeeded", "amount": 29999} │ ✅ Payment verified as successful! │ │ [+10,400ms] POST https://webhook.site/success-endpoint (123ms) ✅ │ Request: Success notification │ Response Status: 200 OK │ ✅ Correct success handling despite initial timeout └──────────────────────────────────────────────────────────────┘ ``` ### 📈 Integration Improvements Summary | Metric | Before | After | Improvement | |--------|--------|-------|-------------| | **Failure Rate** | 10% | 2% | **80% reduction** | | **Average Response Time** | 5,500ms | 1,800ms | **67% faster** | | **Timeout Recovery** | 0% | 95% | **95% success rate** | | **User Experience** | Poor | Good | **Async processing** | | **Double Charges** | 15 cases | 0 cases | **100% eliminated** | --- ## 🎯 Advanced API Debugging Techniques ### 1. API Response Analysis ```bash # Analyze API response patterns php artisan chronotrace:replay trace_id --filter=http --format=json | jq '.http_events[] | {url, status, duration, response_size}' # Find slow API endpoints php artisan chronotrace:list --min-duration=2000 | \ xargs -I {} php artisan chronotrace:replay {} --filter=http --min-duration=1000 ``` ### 2. Error Pattern Recognition ```php // Analyze error patterns across traces class APIErrorAnalyzer { public function analyzeErrorPatterns($timeframe = '24 hours') { $traces = ChronoTrace::getTraces() ->where('created_at', '>=', now()->sub($timeframe)) ->where('status', '>=', 400); $errorPatterns = []; foreach ($traces as $trace) { $httpEvents = $trace->getHttpEvents(); foreach ($httpEvents as $event) { if ($event['status'] >= 400) { $pattern = [ 'endpoint' => $this->extractEndpoint($event['url']), 'status' => $event['status'], 'error_type' => $this->categorizeError($event), 'frequency' => 1 ]; $key = md5(json_encode($pattern)); if (isset($errorPatterns[$key])) { $errorPatterns[$key]['frequency']++; } else { $errorPatterns[$key] = $pattern; } } } } return collect($errorPatterns)->sortByDesc('frequency'); } } ``` ### 3. API Performance Monitoring ```php // Monitor API performance metrics class APIPerformanceMonitor { public function trackAPIMetrics($trace) { $httpEvents = $trace->getHttpEvents(); foreach ($httpEvents as $event) { $metrics = [ 'endpoint' => $this->normalizeEndpoint($event['url']), 'method' => $event['method'], 'status' => $event['status'], 'duration' => $event['duration'], 'request_size' => $event['request_size'] ?? 0, 'response_size' => $event['response_size'] ?? 0, 'timestamp' => $event['timestamp'], ]; // Store in time-series database InfluxDB::write('api_metrics', $metrics); // Check for performance alerts if ($event['duration'] > 5000) { $this->sendSlowAPIAlert($metrics); } if ($event['status'] >= 500) { $this->sendAPIErrorAlert($metrics); } } } } ``` --- ## 📋 API Integration Debugging Checklist ### Before Implementation - [ ] Define timeout strategies for each API - [ ] Plan retry logic and exponential backoff - [ ] Implement idempotency for critical operations - [ ] Design circuit breaker patterns - [ ] Plan async processing for slow APIs ### During Development - [ ] Test timeout scenarios - [ ] Verify retry behavior - [ ] Test error response handling - [ ] Validate status checking mechanisms - [ ] Test rate limit handling ### Production Monitoring - [ ] Monitor API response times - [ ] Track error rates by endpoint - [ ] Set up alerting for failures - [ ] Monitor circuit breaker states - [ ] Track timeout recovery success ### Ongoing Optimization - [ ] Analyze API usage patterns - [ ] Optimize frequently used endpoints - [ ] Review and adjust timeout values - [ ] Update retry strategies based on data - [ ] Implement caching where appropriate --- ## 🔧 Pro Tips for API Debugging ### 1. Use Request/Response Logging ```php // Log all API interactions Http::macro('withLogging', function () { return $this->beforeSending(function ($request) { Log::info('API Request', [ 'url' => $request->url(), 'method' => $request->method(), 'headers' => $request->headers(), 'body' => $request->body() ]); })->withMiddleware(function ($response) { Log::info('API Response', [ 'status' => $response->status(), 'headers' => $response->headers(), 'body' => $response->body(), 'duration' => $response->handlerStats()['total_time'] ?? null ]); }); }); ``` ### 2. Implement Health Checks ```php // API health monitoring class APIHealthChecker { public function checkPaymentGateway() { try { $response = Http::timeout(5)->get('https://api.stripe.com/v1/account'); return $response->successful(); } catch (Exception $e) { return false; } } } ``` ### 3. Use Mock Services for Testing ```php // Mock external APIs during testing class PaymentServiceTest extends TestCase { public function test_payment_timeout_handling() { Http::fake([ 'api.stripe.com/*' => Http::response([], 408), // Timeout ]); $this->expectException(PaymentTimeoutException::class); $paymentService = new PaymentService(); $paymentService->processPayment($this->getTestPaymentData()); } } ``` --- ## 📚 Related Documentation - **[Configuration](Configuration.md)** - HTTP event capture configuration - **[Performance Analysis](Example-Performance-Analysis.md)** - General performance optimization - **[Security](Security.md)** - API security and PII protection - **[Production Monitoring](Production-Monitoring.md)** - API monitoring in production --- **Result:** Payment system reliability improved from **90% to 98%** success rate, with **67% faster** response times and **100% elimination** of double-charging incidents!