Skip to main content

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.

  1. Logs from User A appear with User B's Correlation ID.
  2. Correlation IDs are lost ("null") when await is called.
  3. 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 contextvars for 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-CorrelationID from headers or generates a UUID.
  • Background Task Support: Includes a drop-in replacement for FastAPI's BackgroundTasks that 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)

  1. Middleware: Intercepts request Generates/Extracts ID Sets ContextVar.
  2. Formatter: logging calls Formatter Formatter reads ContextVar Injects into JSON.
  3. Background Tasks: ContextAwareBackgroundTasks snapshots ContextVar during request Re-hydrates it inside the worker thread.

📄 License

This project is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sap_fastapi_logger-0.1.2.tar.gz (4.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sap_fastapi_logger-0.1.2-py3-none-any.whl (5.5 kB view details)

Uploaded Python 3

File details

Details for the file sap_fastapi_logger-0.1.2.tar.gz.

File metadata

  • Download URL: sap_fastapi_logger-0.1.2.tar.gz
  • Upload date:
  • Size: 4.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for sap_fastapi_logger-0.1.2.tar.gz
Algorithm Hash digest
SHA256 5d49097a55dbd8fe536b0d46520b4f82567537860c9ff61af500ff426cae477a
MD5 35eb14a19aee527686b053a720e72d83
BLAKE2b-256 10a2a917cbbcb3e5b5edd5f07d1bb996ea3da208d1fb897abaf861ec128e2093

See more details on using hashes here.

File details

Details for the file sap_fastapi_logger-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for sap_fastapi_logger-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 71b8dbb625f3662cd8c8db34efe6622470b007f562a7f113df1bff1611fa7f61
MD5 d723cc94a32c2ad901bb943fe1f5ee17
BLAKE2b-256 45250e230fb87f417f19957a503a7dcd98af1fa1e2264f0fa881980bd4543d3a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page