Metadata-Version: 2.4
Name: fastapi-api-logger
Version: 0.2.1
Summary: Plug & play auto-logging middleware for FastAPI with async I/O, structured JSON logs, request IDs, loguru integration, and a built-in dashboard
Project-URL: Homepage, https://github.com/paresh/fastapi-api-logger
Project-URL: Repository, https://github.com/paresh/fastapi-api-logger
Project-URL: Issues, https://github.com/paresh/fastapi-api-logger/issues
Author: Paresh
License-Expression: MIT
License-File: LICENSE
Keywords: api,async,dashboard,fastapi,logging,loguru,middleware,starlette
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: System :: Logging
Requires-Python: >=3.9
Requires-Dist: starlette>=0.27.0
Provides-Extra: dev
Requires-Dist: fastapi>=0.100; extra == 'dev'
Requires-Dist: httpx>=0.24; extra == 'dev'
Requires-Dist: loguru>=0.7; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: uvicorn>=0.23; extra == 'dev'
Provides-Extra: loguru
Requires-Dist: loguru>=0.7; extra == 'loguru'
Description-Content-Type: text/markdown

# fastapi-api-logger

Plug & play auto-logging middleware for FastAPI with async I/O, structured JSON logs, request tracing, loguru integration, and a built-in dashboard.

## Features

- **Zero-config middleware** — add one line and all requests are logged
- **Structured JSON logs** — timestamp, method, endpoint, status, status_code, response_time_ms
- **Correlation / Request ID** — unique ID per request, forwarded from API gateways, injected into response headers
- **Day-wise log files** — `logs/2026-03-25.log`, `logs/2026-03-26.log`, ...
- **Async & non-blocking** — logging never slows your API (bounded queue + background writer)
- **Status categorization** — SUCCESS (2xx), REDIRECT (3xx), WARNING (4xx), ERROR (5xx)
- **Error tracebacks** — full traceback captured for 5xx errors
- **Request/response body capture** — opt-in, with automatic sensitive field masking
- **Loguru integration** — optionally pipe all logs through loguru with configurable levels
- **Built-in dashboard** — web UI at `/logs` to browse, filter, and search logs in real-time
- **Configurable log rotation** — auto-deletes log files older than N days (you choose how many)
- **Pure ASGI** — works with FastAPI, Starlette, or any ASGI framework

## Quick Start

### Install

```bash
pip install fastapi-api-logger

# With loguru support
pip install fastapi-api-logger[loguru]

# With everything
pip install fastapi-api-logger[all]
```

### Basic Usage (2 lines)

```python
from fastapi import FastAPI
from fastapi_logger import LoggingMiddleware

app = FastAPI()
app.add_middleware(LoggingMiddleware)
```

That's it! All requests are now logged to `logs/YYYY-MM-DD.log` with unique request IDs.

### Full-Featured Usage

```python
from fastapi import FastAPI
from fastapi_logger import LoggingMiddleware, LogConfig, create_dashboard_router

app = FastAPI()

config = LogConfig(
    log_dir="logs",
    excluded_paths=["/health", "/docs", "/openapi.json"],
    enable_request_body=True,
    enable_response_body=True,
    sensitive_fields={"password", "token", "secret"},

    # Request ID
    enable_request_id=True,
    request_id_header="X-Request-ID",

    # Loguru
    enable_loguru=True,

    # Dashboard
    enable_dashboard=True,
    dashboard_prefix="/logs",

    # Rotation — delete logs older than 7 days
    log_rotation_days=7,
)

app.add_middleware(LoggingMiddleware, config=config)

# Mount the dashboard (visit http://localhost:8000/logs)
app.mount("", create_dashboard_router(config))
```

## Correlation / Request ID

Every request gets a unique ID (UUID4). This is essential for debugging in production.

```bash
$ curl -v http://localhost:8000/users/1
< x-request-id: a1b2c3d4e5f6...
```

**How it works:**
- If the client sends `X-Request-ID` header (e.g., from an API gateway), the middleware uses it
- Otherwise, a new UUID is generated
- The ID is added to the response headers AND the log entry
- Your endpoint can access it via `request.scope["state"]["request_id"]`

```python
@app.get("/users/{user_id}")
async def get_user(user_id: int, request: Request):
    request_id = request.scope["state"]["request_id"]
    return {"id": user_id, "request_id": request_id}
```

## Loguru Integration

Enable loguru to get beautiful colored terminal output alongside file logging:

```python
config = LogConfig(
    enable_loguru=True,
    loguru_level_success="INFO",     # 2xx
    loguru_level_warning="WARNING",  # 4xx
    loguru_level_error="ERROR",      # 5xx
)
```

Output:
```
2026-03-25 14:30:00 | INFO     | [a1b2c3d4] GET /users/1 → 200 SUCCESS (42.1ms)
2026-03-25 14:30:01 | WARNING  | [b2c3d4e5] GET /users/0 → 404 WARNING (3.2ms)
2026-03-25 14:30:02 | ERROR    | [c3d4e5f6] GET /crash → 500 ERROR (1.1ms)
```

Install loguru: `pip install fastapi-api-logger[loguru]`

## Dashboard

A built-in web UI to browse your logs — no React, no npm, just enable it:

```python
config = LogConfig(enable_dashboard=True, dashboard_prefix="/logs")
app.mount("", create_dashboard_router(config))
```

Visit `http://localhost:8000/logs` to see:
- Real-time log entries (auto-refreshes every 5s)
- Stats cards: total, success, warning, error counts + avg response time
- Filters: by status, method, endpoint search, date picker
- Sorting: newest, oldest, or slowest first
- Color-coded response times: green (<100ms), yellow (<500ms), red (>500ms)
- Expandable tracebacks and request bodies

## Configuration Reference

### All Options

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `log_dir` | `str` | `"logs"` | Directory for log files |
| `log_format` | `"json"` / `"text"` | `"json"` | Log output format |
| `excluded_paths` | `list[str]` | `["/health", ...]` | Glob patterns to skip |
| `enable_request_body` | `bool` | `False` | Capture request body |
| `enable_response_body` | `bool` | `False` | Capture response body |
| `sensitive_fields` | `set[str]` | `{"password", ...}` | Fields to mask as `***` |
| `max_body_size` | `int` | `10000` | Max body bytes to capture |
| `log_rotation_days` | `int` | `30` | Auto-delete logs older than N days (0 = keep forever) |
| `include_traceback` | `bool` | `True` | Include traceback for 5xx errors |
| `enable_request_id` | `bool` | `True` | Generate unique request ID per request |
| `request_id_header` | `str` | `"X-Request-ID"` | Header name for request ID |
| `inject_response_header` | `bool` | `True` | Add request ID to response headers |
| `enable_loguru` | `bool` | `False` | Also emit logs through loguru |
| `loguru_level_success` | `str` | `"INFO"` | Loguru level for 2xx |
| `loguru_level_warning` | `str` | `"WARNING"` | Loguru level for 4xx |
| `loguru_level_error` | `str` | `"ERROR"` | Loguru level for 5xx |
| `enable_dashboard` | `bool` | `False` | Enable the `/logs` web UI |
| `dashboard_prefix` | `str` | `"/logs"` | URL prefix for dashboard routes |
| `dashboard_page_size` | `int` | `100` | Entries per page in dashboard |

## Log Format

```json
{
    "timestamp": "2026-03-25T14:30:00.123456+00:00",
    "method": "POST",
    "endpoint": "/orders",
    "status": "SUCCESS",
    "status_code": 201,
    "response_time_ms": 85.23,
    "request_id": "a1b2c3d4e5f67890abcdef1234567890",
    "client_ip": "127.0.0.1",
    "request_body": "{\"item\": \"widget\", \"password\": \"***\"}",
    "response_body": "{\"id\": 42}"
}
```

## Architecture

```
Request → LoggingMiddleware (pure ASGI)
           ├─ Generates/extracts Request ID
           ├─ Injects X-Request-ID response header
           ├─ Measures response time (perf_counter)
           ├─ Captures status code, method, path
           ├─ Optionally captures request/response body
           ├─ Masks sensitive fields
           └─ Enqueues log entry (non-blocking, O(1))
                    ↓
              asyncio.Queue (bounded, 10k max)
                    ↓
              AsyncLogWriter (background task)
              ├─ Day-wise file: logs/YYYY-MM-DD.log
              ├─ Auto-rotation: deletes old files
              └─ Optional: loguru sink
```

## Development

```bash
git clone https://github.com/paresh/fastapi-api-logger.git
cd fastapi-api-logger
pip install -e ".[dev]"

# Run tests (51 tests)
pytest tests/ -v

# Run the demo app
uvicorn examples.demo_app:app --reload
# Visit http://localhost:8000/logs for the dashboard
```

## Publishing to PyPI

```bash
# Install build tools
pip install build twine

# Build
python -m build

# Verify
twine check dist/*

# Upload to TestPyPI (testing)
twine upload --repository testpypi dist/*

# Upload to PyPI (production)
twine upload dist/*
```

### Versioning

Update version in two places:
- `pyproject.toml` → `version = "X.Y.Z"`
- `src/fastapi_logger/__init__.py` → `__version__ = "X.Y.Z"`

## License

MIT
