Async-safe structured JSON logging for FastAPI on SAP BTP
Project description
SAP FastAPI Logger
Async-safe, structured JSON logging for FastAPI applications running on SAP BTP (Business Technology Platform).
This library solves the critical "Context Leakage" issue common when using standard logging libraries with ASGI frameworks like FastAPI. It ensures that Correlation IDs are correctly propagated across asynchronous requests and background tasks, making logs traceable in SAP Cloud Logging (Kibana).
🚨 The Problem
Standard Python logging libraries (including sap-cf-logging) rely on threading.local to store request context.
- In Flask (WSGI): One request = One thread. This works fine.
- In FastAPI (ASGI): One thread handles multiple concurrent requests via an event loop.
The Consequence: Using standard logging in FastAPI causes Context Leakage.
- Logs from User A appear with User B's Correlation ID.
- Correlation IDs are lost ("null") when
awaitis called. - Background tasks lose context entirely.
✅ The Solution
sap-fastapi-logger replaces thread-local storage with Python's native contextvars. This attaches context to the logical task rather than the thread, ensuring 100% async safety.
Features
- 🚀 Zero Context Leakage: Uses
contextvarsfor safe async context propagation. - 📊 SAP BTP Compatible: Outputs strict JSON format required by SAP Cloud Logging / Kibana (
msg,written_at,correlation_id,level). - 🔗 Auto-Correlation: Automatically extracts
X-CorrelationIDfrom headers or generates a UUID. - ⚡ Background Task Support: Includes a drop-in replacement for FastAPI's
BackgroundTasksthat preserves context.
📦 Installation
pip install sap-fastapi-logger
🚀 Quick Start
1. Basic Setup (in server.py or main.py)
You only need to do two things: initialize the logger and add the middleware.
import logging
from fastapi import FastAPI
from sap_fastapi_logger import setup_logging, CorrelationMiddleware
# 1. Initialize the JSON Logger (Run this before creating the app)
setup_logging()
app = FastAPI()
# 2. Add the Middleware to handle Correlation IDs
app.add_middleware(CorrelationMiddleware)
@app.get("/")
async def root():
# Usage: Just use the standard python logger!
logging.info("Processing request...")
return {"message": "Hello World"}
Output in Console (and Kibana):
{"level": "INFO", "msg": "Processing request...", "logger": "root", "correlation_id": "a1b2-c3d4-e5f6...", "written_at": "2025-01-01 12:00:00,000"}
⚡ Handling Background Tasks
Standard BackgroundTasks in FastAPI will lose the correlation ID because the middleware finishes and resets the context before the background task runs.
Use ContextAwareBackgroundTasks provided by this library. It automatically captures the ID from the request and injects it into the background thread.
Example
from fastapi import FastAPI
import logging
# Import the custom class
from sap_fastapi_logger import ContextAwareBackgroundTasks
app = FastAPI()
def long_running_process(contract_id: str):
# This log will HAVE the correct correlation ID
logging.info(f"Processing contract {contract_id} in background...")
@app.post("/extract")
def extract_data(
# Type hint using the custom class
background_tasks: ContextAwareBackgroundTasks
):
logging.info("Request received. Starting background task.")
# Use exactly like standard FastAPI BackgroundTasks
background_tasks.add_task(long_running_process, contract_id="999")
return {"message": "Processing started"}
🛠 Advanced Usage
Accessing the Correlation ID Manually
If you need to get the current Correlation ID string (e.g., to pass to a database query or an external API header), you can access the context variable directly.
from sap_fastapi_logger import correlation_id_ctx
@app.get("/debug")
def debug():
current_id = correlation_id_ctx.get()
return {"my_id": current_id}
How it works (Architecture)
- Middleware: Intercepts request Generates/Extracts ID Sets
ContextVar. - Formatter:
loggingcalls Formatter Formatter readsContextVarInjects into JSON. - Background Tasks:
ContextAwareBackgroundTaskssnapshotsContextVarduring request Re-hydrates it inside the worker thread.
📄 License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sap_fastapi_logger-0.1.1.tar.gz.
File metadata
- Download URL: sap_fastapi_logger-0.1.1.tar.gz
- Upload date:
- Size: 4.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f7c36321ed1d9a47064f9751d278fabffbd15e25b5f81909f8fc06147986af7
|
|
| MD5 |
17c5352ad5fa7a500f99f217b549724e
|
|
| BLAKE2b-256 |
fe8361e00c36327098e5ecda1af84a6519dd845958749632df3e7505e09a52d4
|
File details
Details for the file sap_fastapi_logger-0.1.1-py3-none-any.whl.
File metadata
- Download URL: sap_fastapi_logger-0.1.1-py3-none-any.whl
- Upload date:
- Size: 5.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34032a7ae0cd3f8b4b27de258f29ff77cc7c99cd4a61b31e31a4f97b98405941
|
|
| MD5 |
0b006098bccbc384e1e831c89ace6127
|
|
| BLAKE2b-256 |
5f742a6b0a64314fb5a3aec661450358ea4a344c54e92c52fb86cfe1d0be9892
|