Skip to main content

Production-ready observability SDK for Python web applications with FastAPI, Django, and Flask integrations

Project description

Ledger SDK for Python

Observability for developers who just want to ship.

Add one line of code. Get automatic request logging, exception tracking, and performance monitoring. No configuration required.

from ledger.integrations.fastapi import LedgerMiddleware

app.add_middleware(LedgerMiddleware, ledger_client=ledger)

That's it. Every request, response, and exception is now logged to your Ledger dashboard.

Python Version PyPI Version License

Supported Frameworks: FastAPI • Django • Flask

Why Ledger?

  • Actually zero overhead - Less than 0.1ms per request. Your users won't notice.
  • Works out of the box - No configuration files, no setup guides, no dashboards to build.
  • Production-ready from day one - Built-in retry logic, rate limiting, and graceful failure handling.

Installation

pip install ledger-sdk

Quick Start

FastAPI

from contextlib import asynccontextmanager
from fastapi import FastAPI
from ledger import LedgerClient
from ledger.integrations.fastapi import LedgerMiddleware

ledger = LedgerClient(
    api_key="ledger_proj_1_your_api_key",
    base_url="https://ledger-server.jtuta.cloud"
)

@asynccontextmanager
async def lifespan(app: FastAPI):
    yield
    await ledger.shutdown()

app = FastAPI(lifespan=lifespan)

app.add_middleware(LedgerMiddleware, ledger_client=ledger)

Django

# settings.py
import os
from ledger import LedgerClient

LEDGER_CLIENT = LedgerClient(
    api_key=os.getenv("LEDGER_API_KEY", "ledger_proj_1_your_api_key"),
    base_url=os.getenv("LEDGER_BASE_URL", "https://ledger-server.jtuta.cloud")
)

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.middleware.common.CommonMiddleware",
    "ledger.integrations.django.LedgerMiddleware",  # Add this
]

Flask

from flask import Flask
from ledger import LedgerClient
from ledger.integrations.flask import LedgerMiddleware

app = Flask(__name__)

ledger = LedgerClient(
    api_key="ledger_proj_1_your_api_key",
    base_url="https://ledger-server.jtuta.cloud"
)

app.config["LEDGER_CLIENT"] = ledger

LedgerMiddleware(app)

That's all you need. Start your app and watch the logs flow into your Ledger dashboard.

Get your API keyView examples

What You Get

Automatic capture - Every request, response, and exception. No manual logging code.

Distributed tracing - W3C-compatible spans across services. Trace IDs automatically attached to logs emitted inside a span.

Full context - Stack traces, request headers, response bodies, user attributes. Everything you need to debug.

Performance insights - Response times, error rates, slow endpoints. Know where to optimize.

Production reliability - Automatic retries, rate limiting, and graceful degradation. Works even when your network doesn't.

Zero performance impact - All logging happens in the background. Your API stays fast.

Manual Logging

ledger.log_info("User logged in", attributes={"user_id": 123})

ledger.log_warning("Slow query", attributes={"duration_ms": 450})

ledger.log_error("Payment failed", attributes={"amount": 99.99, "error_code": "CARD_DECLINED"})

try:
    result = process_payment()
except Exception as e:
    ledger.log_exception(e, message="Payment processing failed")

Exclude Paths

app.add_middleware(
    LedgerMiddleware,
    ledger_client=ledger,
    exclude_paths=["/health", "/metrics"]
)

Only Log Registered Routes

By default, the SDK only logs requests that match a registered route — scanner noise, 404s, and bot traffic are dropped automatically.

# To log everything including unmatched paths:
app.add_middleware(
    LedgerMiddleware,
    ledger_client=ledger,
    only_registered_routes=False
)

Configuration

The defaults work for most applications. Tune when needed:

ledger = LedgerClient(
    api_key="ledger_proj_1_your_api_key",
    flush_interval=5.0,        # Seconds between flushes
    flush_size=1000,            # Logs before auto-flush
    max_buffer_size=10000,      # Max logs in memory
)

High traffic (>1000 req/sec)? Decrease flush_interval to 2.0 and increase max_buffer_size to 50000.

Low traffic (<100 req/sec)? Increase flush_interval to 10.0 and decrease flush_size to 50.

Distributed Tracing

Trace requests across services with spans. Traces appear in Ledger's Trace List panel on the dashboard.

Setup

Tracing is enabled automatically when you call LedgerClient(...).

from ledger import LedgerClient
from ledger.tracing import get_tracer

ledger = LedgerClient(api_key="...", base_url="https://ledger-server.jtuta.cloud", service_name="my-service")
tracer = get_tracer()

Manual spans

with tracer.start_as_current_span("process-order", attributes={"order_id": 42}) as span:
    result = process_order(42)
    span.set_attribute("status", result.status)

Cross-service propagation

Inject the W3C traceparent header into outgoing HTTP calls so downstream services can continue the trace:

from ledger.tracing import propagation

with tracer.start_as_current_span("outgoing-call") as span:
    headers = {}
    propagation.inject(headers, span)
    response = httpx.get("https://downstream/api", headers=headers)

In the downstream service, extract the context before starting spans:

ctx = propagation.extract(request.headers)
with tracer.start_as_current_span("downstream-handler", parent=ctx):
    ...

FastAPI auto-instrumentation

With LedgerMiddleware, every request automatically becomes a root span. Spans you create inside request handlers are nested under it:

app.add_middleware(LedgerMiddleware, ledger_client=ledger)

@app.get("/orders/{id}")
async def get_order(id: int):
    tracer = get_tracer()
    with tracer.start_as_current_span("db-fetch", attributes={"order_id": id}):
        return await db.get_order(id)

Trace IDs in logs

Any log emitted inside an active span automatically includes the trace_id and span_id as attributes, linking logs to traces in the dashboard.

Monitoring the SDK

Check if the SDK is working properly:

if ledger.is_healthy():
    print("SDK is healthy")

status = ledger.get_health_status()
metrics = ledger.get_metrics()

Expose as HTTP endpoints (FastAPI):

@app.get("/sdk/health")
async def sdk_health():
    return ledger.get_health_status()

Production

Set your API key as an environment variable:

export LEDGER_API_KEY="ledger_proj_1_your_production_key"
export LEDGER_BASE_URL="https://ledger-server.jtuta.cloud"
import os

ledger = LedgerClient(
    api_key=os.getenv("LEDGER_API_KEY"),
    base_url=os.getenv("LEDGER_BASE_URL")
)

Need Help?

Links

License

MIT License - see LICENSE for details.

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

ledger_sdk-1.7.1.tar.gz (50.3 kB view details)

Uploaded Source

Built Distribution

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

ledger_sdk-1.7.1-py3-none-any.whl (37.6 kB view details)

Uploaded Python 3

File details

Details for the file ledger_sdk-1.7.1.tar.gz.

File metadata

  • Download URL: ledger_sdk-1.7.1.tar.gz
  • Upload date:
  • Size: 50.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for ledger_sdk-1.7.1.tar.gz
Algorithm Hash digest
SHA256 b241ec4cc61f3abcfec60c21e072d9a2ee0b8a6159ac0b80b93fd06592f72e37
MD5 7459c7fdab4c1c7e889edef8f54603a5
BLAKE2b-256 b4bbfdf25406b46ee79c95141bc1db253061522330716f2162a5da09a6e2dc69

See more details on using hashes here.

File details

Details for the file ledger_sdk-1.7.1-py3-none-any.whl.

File metadata

  • Download URL: ledger_sdk-1.7.1-py3-none-any.whl
  • Upload date:
  • Size: 37.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for ledger_sdk-1.7.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b7a8fd6c0d8ccbb68cc1d7b5b502f3a5251a5f61910f9fa00ac9853fa62b1b94
MD5 57fd5e17fde470979b8bea43d3f2b73b
BLAKE2b-256 a88ef54930cad5f498c892b81c0371224d79227aa02cc5b5afc9f061bca3d581

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