# Correlation ID Implementation Guide ## Overview Correlation ID logging has been implemented in the AUTH microservice to enable request tracing across distributed systems. This allows you to track a single request as it flows through multiple microservices. ## What is a Correlation ID? A correlation ID is a unique identifier (UUID) that is: - Generated for each incoming request (if not already present) - Propagated through all logs for that request - Passed to downstream services via HTTP headers - Returned in response headers for client tracking ## Implementation Components ### 1. Correlation ID Middleware (`app/middleware/correlation_id.py`) The middleware handles: - Extracting correlation ID from `X-Correlation-ID` header - Generating new UUID if not present - Storing in context variable for request lifecycle - Adding correlation ID to response headers ### 2. Logging Integration (`app/core/logging.py`) The logging system includes: - `CorrelationIdFilter`: Adds correlation ID to all log records - JSON formatter includes `correlation_id` field - All handlers (console, file) have the filter applied ### 3. HTTP Client Utility (`app/utils/http_client.py`) The `CorrelationHttpClient` class provides methods that automatically propagate correlation IDs to downstream services: - `get()`, `post()`, `put()`, `delete()` methods - Automatically includes `X-Correlation-ID` header ## Usage Examples ### 1. Automatic Logging All logs automatically include the correlation ID: ```python from app.core.logging import get_logger logger = get_logger(__name__) # This log will automatically include correlation_id logger.info("Processing user login", extra={"user_id": user_id}) ``` ### 2. Getting Current Correlation ID ```python from app.middleware.correlation_id import get_correlation_id correlation_id = get_correlation_id() logger.info(f"Current correlation ID: {correlation_id}") ``` ### 3. Making HTTP Calls to Other Services ```python from app.utils.http_client import CorrelationHttpClient # Correlation ID is automatically included in headers response = await CorrelationHttpClient.post( url="http://scm-service/api/merchants/list", json={"filters": {}} ) ``` ### 4. Manual Header Propagation If you need to use a different HTTP client: ```python from app.middleware.correlation_id import get_correlation_id, CORRELATION_ID_HEADER import httpx correlation_id = get_correlation_id() headers = {CORRELATION_ID_HEADER: correlation_id} async with httpx.AsyncClient() as client: response = await client.get(url, headers=headers) ``` ## Log Format Logs now include the correlation ID in JSON format: ```json { "timestamp": "2024-03-07T10:30:45.123456", "level": "INFO", "logger": "app.auth.services.service", "message": "User login successful", "correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "module": "service", "function": "login_user", "line": 123, "user_id": "user123" } ``` ## Tracing Requests Across Services ### Client Request Flow 1. Client makes request (optionally with `X-Correlation-ID` header) 2. AUTH service receives request 3. Middleware extracts or generates correlation ID 4. All logs include correlation ID 5. AUTH service calls SCM service with correlation ID in header 6. SCM service logs with same correlation ID 7. Response includes `X-Correlation-ID` header ### Example: Tracing a Login Request ```bash # Client request curl -X POST https://api.example.com/auth/login \ -H "X-Correlation-ID: abc-123" \ -d '{"email": "user@example.com", "password": "pass"}' # AUTH service logs (correlation_id: abc-123) {"timestamp": "...", "correlation_id": "abc-123", "message": "Login request received"} {"timestamp": "...", "correlation_id": "abc-123", "message": "Validating credentials"} {"timestamp": "...", "correlation_id": "abc-123", "message": "Fetching user permissions from SCM"} # SCM service logs (correlation_id: abc-123) {"timestamp": "...", "correlation_id": "abc-123", "message": "Permission request received"} {"timestamp": "...", "correlation_id": "abc-123", "message": "Returning user permissions"} # AUTH service logs (correlation_id: abc-123) {"timestamp": "...", "correlation_id": "abc-123", "message": "Login successful"} ``` ## Searching Logs by Correlation ID ### Using grep ```bash # Search all logs for a specific correlation ID grep "abc-123" logs/app.log # Search with jq for better formatting grep "abc-123" logs/app.log | jq '.' ``` ### Using log aggregation tools If using ELK, Splunk, or similar: ``` correlation_id:"abc-123" ``` ## Best Practices 1. **Always use CorrelationHttpClient** for inter-service communication 2. **Include correlation ID in error responses** for client debugging 3. **Log correlation ID at service boundaries** (entry/exit points) 4. **Pass correlation ID to background tasks** if they're part of the same logical operation 5. **Don't modify correlation IDs** once set - they should remain constant throughout the request lifecycle ## Testing ### Test Correlation ID Generation ```bash # Request without correlation ID (will be generated) curl -X GET http://localhost:8002/health -v # Check response headers for X-Correlation-ID ``` ### Test Correlation ID Propagation ```bash # Request with correlation ID curl -X GET http://localhost:8002/health \ -H "X-Correlation-ID: test-123" -v # Verify same ID is returned in response headers ``` ### Test Logging ```bash # Make request with known correlation ID curl -X POST http://localhost:8002/auth/login \ -H "X-Correlation-ID: test-456" \ -H "Content-Type: application/json" \ -d '{"email": "test@example.com", "password": "test"}' # Check logs grep "test-456" logs/app.log | jq '.' ``` ## Troubleshooting ### Correlation ID not appearing in logs 1. Check that middleware is properly registered in `main.py` 2. Verify `CorrelationIdFilter` is added to all log handlers 3. Ensure logging is configured before making requests ### Correlation ID not propagating to downstream services 1. Use `CorrelationHttpClient` instead of direct httpx calls 2. Verify downstream service supports `X-Correlation-ID` header 3. Check that correlation ID is in context (`get_correlation_id()` returns value) ### Different correlation IDs in related logs 1. Ensure you're not creating new async contexts without propagating correlation ID 2. For background tasks, explicitly pass correlation ID 3. Verify middleware is processing requests before other middlewares ## Integration with Other Microservices To implement correlation ID in other microservices (SCM, POS, SPA, etc.): 1. Copy `app/middleware/correlation_id.py` to the service 2. Update `app/core/logging.py` to include `CorrelationIdFilter` 3. Add `CorrelationIdMiddleware` to `main.py` 4. Copy `app/utils/http_client.py` for HTTP client utilities 5. Update inter-service calls to use `CorrelationHttpClient` ## Benefits - **Debugging**: Trace requests across multiple services - **Performance Analysis**: Identify bottlenecks in request flow - **Error Tracking**: Link errors across service boundaries - **Audit Trail**: Complete request history for compliance - **Monitoring**: Better observability in distributed systems