# FastAPI JSON logging to stdout (Uvicorn access logs included)

Container platforms like Docker, Kubernetes, and AWS ECS expect structured JSON logs on stdout. Without consistent formatting, log aggregation systems (CloudWatch, Datadog, ELK) can't parse your logs reliably.

## The Problem

A typical FastAPI application produces two distinct log streams:

**Application logs** (your code):
```
INFO:     Processing order 12345
```

**Uvicorn access logs** (HTTP requests):
```
INFO:     127.0.0.1:52486 - "GET /api/orders HTTP/1.1" 200 OK
```

These plain text formats cause problems:

1. **Inconsistent structure** - App logs and access logs have different formats
2. **Color codes** - Uvicorn adds ANSI escape sequences that break JSON parsers
3. **No machine-readable fields** - Can't filter by status code, latency, or request ID

## The Solution

fapilog provides unified JSON output for both application and access logs:

```python
from fastapi import FastAPI, Depends
from fapilog.fastapi import FastAPIBuilder, get_request_logger

app = FastAPI(
    lifespan=FastAPIBuilder()
        .with_preset("fastapi")
        .build()
)

@app.get("/api/orders/{order_id}")
async def get_order(order_id: str, logger=Depends(get_request_logger)):
    await logger.info("Processing order", order_id=order_id)
    return {"order_id": order_id, "status": "shipped"}
```

The `fastapi` preset configuration:
- Outputs JSON to stdout (no files)
- Disables color codes
- Includes request context (request_id) automatically
- Masks sensitive fields (passwords, API keys, tokens)

## Sample Output

**Application log:**
```json
{"timestamp": "2026-01-21T10:30:00.123Z", "level": "INFO", "message": "Processing order", "order_id": "12345", "request_id": "550e8400-e29b-41d4-a716-446655440000"}
```

**Access log:**
```json
{"timestamp": "2026-01-21T10:30:00.456Z", "level": "INFO", "message": "HTTP request", "method": "GET", "path": "/api/orders/12345", "status_code": 200, "duration_ms": 15.2, "request_id": "550e8400-e29b-41d4-a716-446655440000"}
```

Both share consistent field names (`timestamp`, `level`, `message`, `request_id`), making log aggregation straightforward.

## Including Uvicorn Access Logs

fapilog's `FastAPIBuilder` automatically installs middleware that captures HTTP requests. The `LoggingMiddleware` handles:

- Request method, path, and query parameters
- Response status codes
- Request duration
- Client IP address
- Request ID correlation

No additional Uvicorn configuration is needed. The default Uvicorn access log is effectively replaced by fapilog's structured output.

### Disabling Default Uvicorn Logs

If you want to suppress Uvicorn's default access logging entirely (recommended to avoid duplicate logs), configure Uvicorn:

```python
import uvicorn

if __name__ == "__main__":
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=8000,
        access_log=False,  # Disable Uvicorn's access log
    )
```

Or via CLI:
```bash
uvicorn main:app --host 0.0.0.0 --port 8000 --no-access-log
```

## Docker Configuration

A minimal Dockerfile for JSON logging:

```dockerfile
FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Use --no-access-log to avoid duplicate access logs
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--no-access-log"]
```

### Docker Compose

```yaml
services:
  api:
    build: .
    ports:
      - "8000:8000"
    environment:
      - FAPILOG_CORE__LOG_LEVEL=INFO
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
```

## Explicit Format Control

If you're not using the FastAPI integration but still want JSON output:

```python
from fapilog import get_async_logger

async def main():
    # format="json" ensures JSON output regardless of environment
    logger = await get_async_logger(format="json")
    await logger.info("Starting service", version="1.0.0")
```

For automatic format detection (JSON in containers, pretty in terminals):

```python
logger = await get_async_logger(format="auto")
```

## Going Deeper

- [FastAPI request_id Logging](fastapi-request-id-logging.md) - Correlation ID middleware
- [Context Enrichment](../user-guide/context-enrichment.md) - Adding custom fields to all logs
- [Redaction](../redaction/index.md) - Masking sensitive data
- [Why Fapilog?](../why-fapilog.md) - How fapilog compares to other logging libraries
