Skip to main content

Lightweight self-hosted observability for FastAPI.

Project description

⚡ fastapi-flare

Lightweight self-hosted observability for FastAPI.
Backed by Redis Streams or SQLite — no SaaS, no overhead.


Python FastAPI Redis License: MIT


fastapi-flare dashboard preview

What is fastapi-flare?

fastapi-flare is a self-hosted error tracking library for FastAPI applications. It automatically captures HTTP and unhandled exceptions, stores them in Redis Streams, and exposes a beautiful dark-theme dashboard — all with a single line of code.

No external services. No configuration files. No noise.


Features

🚀 One-line setup setup(app) and you're done
🔍 Auto-capture HTTP 4xx/5xx and unhandled Python exceptions
🖥️ Admin dashboard Built-in at /flare — dark theme, filters, pagination
🗄️ Dual storage Redis Streams (production) or SQLite (zero-infra)
🔥 Fire-and-forget Logging never blocks or affects your request handlers
⚙️ Background worker Async task drains queue to stream every 5 seconds
🕒 Retention policies Time-based (default 7 days) + count-based (10k entries)
🔐 Auth-ready Protect the dashboard with any FastAPI Depends()
🌍 Env-configurable All settings available as FLARE_* environment variables

Installation

pip install fastapi-flare

All features (SQLite backend, Zitadel JWT auth) are included in the base install.

Requirements: Python 3.11+, FastAPI. Redis is only required when using the default redis storage backend.


Quick Start

Redis (default — production-ready, durable):

from fastapi import FastAPI
from fastapi_flare import setup

app = FastAPI()
setup(app, redis_url="redis://localhost:6379")

SQLite (zero-infra — no Redis required):

from fastapi import FastAPI
from fastapi_flare import FlareConfig, setup

app = FastAPI()
setup(app, config=FlareConfig(storage_backend="sqlite", sqlite_path="flare.db"))

Visit http://localhost:8000/flare to open the error dashboard.


Storage Backends

Redis (default)

Uses a Redis List as buffer queue and a Redis Stream as durable storage. Best for production deployments where Redis is already available.

setup(app, config=FlareConfig(
    storage_backend="redis",           # default
    redis_url="redis://localhost:6379",
    redis_password=None,
    stream_key="flare:logs",
    queue_key="flare:queue",
))

Docker:

docker run -d -p 6379:6379 redis:7

SQLite

Stores everything in a local .db file. No external services, no Docker, no configuration — ideal for local development, small deployments, or air-gapped environments.

setup(app, config=FlareConfig(
    storage_backend="sqlite",
    sqlite_path="flare.db",            # path to the .db file
))

The SQLite backend uses WAL mode and indexed queries for efficient reads and writes.


Full Configuration

from fastapi_flare import setup, FlareConfig

setup(app, config=FlareConfig(
    # --- Backend (choose one) ---
    storage_backend="redis",           # "redis" | "sqlite"

    # Redis options (storage_backend="redis")
    redis_url="redis://localhost:6379",
    redis_password=None,
    stream_key="flare:logs",
    queue_key="flare:queue",

    # SQLite options (storage_backend="sqlite")
    # sqlite_path="flare.db",

    # --- Shared ---
    max_entries=10_000,               # Count-based cap
    retention_hours=168,              # Time-based retention (7 days)

    # Dashboard
    dashboard_path="/flare",
    dashboard_title="My App — Errors",
    dashboard_auth_dependency=None,   # e.g. Depends(verify_token)

    # Worker
    worker_interval_seconds=5,
    worker_batch_size=100,
))

Environment Variables

All options can be set via FLARE_* env vars — no code changes needed:

FLARE_REDIS_URL=redis://myhost:6379
FLARE_RETENTION_HOURS=72
FLARE_DASHBOARD_PATH=/errors
FLARE_DASHBOARD_TITLE="Production Errors"

Dashboard

The built-in dashboard gives you full visibility into your application errors without leaving your infrastructure.

Feature Detail
URL {dashboard_path} (default /flare)
Stats cards Errors/Warnings in last 24h, total entries, latest error time
Filters Level (ERROR / WARNING), event name, full-text search
Table Timestamp, level badge, event, message, endpoint, HTTP status
Detail modal Full message, error, stack trace, request metadata, context JSON
Auto-refresh 30s polling toggle

Redis Data Model

fastapi-flare uses two Redis structures:

Key Type Purpose
flare:queue List Incoming buffer — LPUSH by handlers, RPOP by worker
flare:logs Stream Durable time-ordered storage — XADD / XREVRANGE

Stream entries are automatically trimmed by two policies applied on every worker cycle:

  1. Count-basedMAXLEN ~ keeps at most max_entries items
  2. Time-basedXTRIM MINID removes entries older than retention_hours

Log Entry Schema

Every captured error is stored as a structured FlareLogEntry:

class FlareLogEntry(BaseModel):
    id: str                    # Redis Stream entry ID (millisecond-precise)
    timestamp: datetime
    level: Literal["ERROR", "WARNING"]
    event: str                 # e.g. "http_exception", "unhandled_exception"
    message: str
    request_id: str | None     # UUID from X-Request-ID header
    endpoint: str | None
    http_method: str | None
    http_status: int | None
    ip_address: str | None
    duration_ms: int | None
    error: str | None
    stack_trace: str | None
    context: dict | None       # Additional structured data

Manual Logging

You can push custom log entries from anywhere in your application:

from fastapi_flare.queue import push_log

await push_log(
    config,
    level="ERROR",
    event="payment_failed",
    message="Stripe charge declined",
    context={"order_id": "ord_123", "amount": 2500},
)

Protecting the Dashboard

Secure the dashboard using any FastAPI dependency:

from fastapi import HTTPException, Security
from fastapi.security import HTTPBearer

bearer = HTTPBearer()

def verify_token(token=Security(bearer)):
    if token.credentials != "my-secret":
        raise HTTPException(status_code=401, detail="Unauthorized")

setup(app, config=FlareConfig(
    redis_url="redis://localhost:6379",
    dashboard_auth_dependency=verify_token,
))

Zitadel Authentication

fastapi-flare has built-in support for protecting the /flare dashboard via Zitadel OIDC.
Two integration modes are available:

Mode When to use
Browser (PKCE) Users access /flare from a browser — automatically redirected to the Zitadel login page
Bearer Token API clients send Authorization: Bearer <token> — no redirect

Requires the [auth] extra:

pip install 'fastapi-flare[auth]'

Prerequisites

In the Zitadel console:

  1. Create a Web Application inside a project (type: PKCE / User Agent)
  2. Note the Domain — e.g. auth.mycompany.com
  3. Note the Client ID of the application
  4. Note the Project ID (visible in the project's general settings)
  5. For browser mode: register the callback URL — e.g. https://myapp.com/flare/callback

Browser Mode (PKCE) — access from a browser

When zitadel_redirect_uri is configured, opening /flare in a browser automatically redirects to Zitadel. After login, Zitadel calls the callback, the session is created in a signed cookie, and the user is redirected back to the dashboard.

setup(app, config=FlareConfig(
    redis_url="redis://localhost:6379",
    zitadel_domain="auth.mycompany.com",
    zitadel_client_id="000000000000000001",
    zitadel_project_id="000000000000000002",
    zitadel_redirect_uri="https://myapp.com/flare/callback",
))

Via environment variables:

FLARE_ZITADEL_DOMAIN=auth.mycompany.com
FLARE_ZITADEL_CLIENT_ID=000000000000000001
FLARE_ZITADEL_PROJECT_ID=000000000000000002
FLARE_ZITADEL_REDIRECT_URI=https://myapp.com/flare/callback
FLARE_ZITADEL_SESSION_SECRET=<32-byte-hex>  # python -c "import secrets; print(secrets.token_hex(32))"

Flow:

  1. User opens https://myapp.com/flare in a browser
  2. fastapi-flare detects no session → redirects to /flare/auth/login
  3. /flare/auth/login generates a PKCE challenge, stores code_verifier + state in the session, redirects to Zitadel
  4. User logs in on the Zitadel page
  5. Zitadel redirects to the configured callback URL with ?code=...&state=...
  6. fastapi-flare validates the state, exchanges the code for an access_token, calls /oidc/v1/userinfo
  7. User data and expiry timestamp are saved in the session (signed flare_session cookie)
  8. User is redirected to /flare — access granted ✅

Important: register exactly https://yourapp.com/<callback-path> as the Redirect URI in the Zitadel app. The callback path is extracted automatically from zitadel_redirect_uri — it does not need to be under /flare.

Routes created automatically:

Route Purpose
GET /flare/auth/login Starts the PKCE flow → redirects to Zitadel
GET <callback-path> Receives the code, exchanges it for a token, creates the session
GET /flare/auth/logout Clears the session → redirects to login

API Mode (Bearer Token) — no zitadel_redirect_uri

When zitadel_redirect_uri is not set, the dashboard validates the Authorization: Bearer <token> header. Ideal when the frontend already manages the PKCE flow and injects the token into requests.

setup(app, config=FlareConfig(
    redis_url="redis://localhost:6379",
    zitadel_domain="auth.mycompany.com",
    zitadel_client_id="000000000000000001",
    zitadel_project_id="000000000000000002",
    # no zitadel_redirect_uri → Bearer mode
))

Manual Mode — custom dependency (advanced)

from fastapi_flare import setup, FlareConfig
from fastapi_flare.zitadel import make_zitadel_dependency

dep = make_zitadel_dependency(
    domain="auth.mycompany.com",
    client_id="000000000000000001",
    project_id="000000000000000002",
)

setup(app, config=FlareConfig(
    redis_url="redis://localhost:6379",
    dashboard_auth_dependency=dep,
))

Project migration — accepting tokens from the old project

FLARE_ZITADEL_OLD_CLIENT_ID=old-client-id
FLARE_ZITADEL_OLD_PROJECT_ID=old-project-id

Tokens from both projects are accepted until you remove the _old_* fields.


How it works internally

  • The session is managed by Starlette's SessionMiddleware — a flare_session cookie signed with HMAC using zitadel_session_secret. All content (user, token, expiry) lives inside the cookie — no database or Redis required for session management.
  • The PKCE code_verifier and state are stored in the session (not in separate cookies), following the PKCE spec recommendations.
  • After the callback, fastapi-flare calls /oidc/v1/userinfo to fetch the real user data (email, name, etc.) and saves it in the session.
  • Sessions expire automatically after 1 hour — the user is transparently redirected to login.
  • Use clear_jwks_cache() to reset the JWKS cache in tests (Bearer mode).

Running the Example

SQLite mode (no dependencies):

poetry run uvicorn examples.example:app --reload --port 8000

Redis mode:

# 1. Copy and configure environment
cp .env.example .env

# 2. Start Redis (Docker)
docker run -d -p 6379:6379 redis:7

# 3. Switch the example to Redis and run
# In examples/example.py, change:
#   FlareConfig(storage_backend="redis")  # and set FLARE_REDIS_URL in .env
poetry run uvicorn examples.example:app --reload --port 8000

Test routes:

Route Behavior
GET / Returns 200 OK
GET /boom Triggers RuntimeError → captured as ERROR
GET /items/999 Triggers HTTPException 404 → captured as WARNING
GET /flare Opens the error dashboard

Comparison

Project What it does
sentry-sdk Full error tracking SaaS — more features, external dependency
fastapi-analytics Endpoint analytics / performance — not error-focused
fastapi-middleware-logger HTTP logging only, no storage or dashboard
api-watch Real-time monitoring, Flask/FastAPI
fastapi-flare Self-hosted, zero-config error visibility — no external services

fastapi-flare is for teams that want local, observable, production-ready error tracking without the overhead of a full observability platform.


Why not Sentry?

Sentry is a great product — but it comes with trade-offs that not every team wants to accept.

fastapi-flare Sentry
Hosting Self-hosted, your infra External SaaS
Account required No Yes
Infrastructure Redis only Kafka, ClickHouse, Postgres, …
Cost Zero Free tier → paid plans
Privacy Data never leaves your server Data sent to third-party
Setup One setup(app) call SDK + DSN + account config
Customization Full source access Configuration only

fastapi-flare is the right choice when you need fast, private, zero-dependency error visibility — especially in self-hosted, air-gapped, or cost-sensitive environments.
For large-scale teams who need release tracking, performance monitoring, and team workflows, Sentry remains the better fit.


License

MIT © Gabriel

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

fastapi_flare-0.1.4.tar.gz (55.6 kB view details)

Uploaded Source

Built Distribution

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

fastapi_flare-0.1.4-py3-none-any.whl (66.0 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_flare-0.1.4.tar.gz.

File metadata

  • Download URL: fastapi_flare-0.1.4.tar.gz
  • Upload date:
  • Size: 55.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.11.9 Windows/10

File hashes

Hashes for fastapi_flare-0.1.4.tar.gz
Algorithm Hash digest
SHA256 f72394b326e785a615b1d40744f82b620ec9f23527a6aa06b56aaaadd93d8489
MD5 ececa1290ce8306c4f65adea9f946373
BLAKE2b-256 cdfb36efbdf17a031ac9de8a9070e8bd6b29360172c2b2978e4251b9b199c876

See more details on using hashes here.

File details

Details for the file fastapi_flare-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: fastapi_flare-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 66.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.11.9 Windows/10

File hashes

Hashes for fastapi_flare-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 84920ddfcbd279ed56c97b7dd262390611788b540989a66d76a4471afd8a626d
MD5 d911cb32bc8a25d108b35836b6075e0e
BLAKE2b-256 822563790eca8da69f1f092a2ea4340e6983bff7f4034dfc772bf9b789256d5b

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