Skip to main content

Lightweight self-hosted debugger and metrics dashboard for FastAPI.

Project description

โšก fastapi-flare

Lightweight self-hosted debugger and metrics dashboard for FastAPI.
Zero-config by default (SQLite) โ€” PostgreSQL-ready for production.


Python FastAPI PostgreSQL License: MIT


fastapi-flare dashboard preview

What is fastapi-flare?

fastapi-flare is a self-hosted error tracking and metrics library for FastAPI applications.
It automatically captures HTTP and unhandled exceptions, stores them locally or in PostgreSQL, and exposes a dark-theme dashboard โ€” all with a single line of code.

No external services. No SaaS. No noise.


Features

๐Ÿš€ One-line setup setup(app) โ€” works immediately, no config required
๐Ÿ” Auto-capture HTTP 4xx/5xx and unhandled Python exceptions
๐Ÿงต Non-HTTP capture Background tasks, workers, logger.exception(), stray asyncio tasks
๐Ÿงฉ Issue grouping Deterministic fingerprint collapses repeated errors into one issue with occurrence count, first/last seen, resolve/reopen
๐Ÿ–ฅ๏ธ Admin dashboard Built-in at /flare โ€” dark theme, filters, pagination
๐Ÿ—„๏ธ Dual storage SQLite (zero-config default) or PostgreSQL (production)
๐Ÿ”ฅ Fire-and-forget Logging never blocks your request handlers
โš™๏ธ Background worker Async task runs retention cleanup 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 via FLARE_* environment variables

Installation

pip install fastapi-flare

Requirements: Python 3.11+, FastAPI.
aiosqlite and asyncpg are bundled โ€” no extra installs needed for either backend.


Quick Start

Zero-config (SQLite, works immediately):

from fastapi import FastAPI
from fastapi_flare import setup

app = FastAPI()
setup(app)
# Dashboard at http://localhost:8000/flare
# Creates flare.db automatically โ€” no setup required.

PostgreSQL (production):

from fastapi_flare import setup, FlareConfig

setup(app, config=FlareConfig(
    storage_backend="postgresql",
    pg_dsn="postgresql://user:password@localhost:5432/mydb",
))

Storage Backends

SQLite (default)

Zero-config local file storage. Works immediately without any external dependencies.
Ideal for development, quick testing, small deployments, and air-gapped environments.

setup(app, config=FlareConfig(
    storage_backend="sqlite",     # default โ€” can be omitted
    sqlite_path="flare.db",       # path to the .db file
))

Via environment variables:

FLARE_STORAGE_BACKEND=sqlite
FLARE_SQLITE_PATH=/data/flare.db

Uses WAL mode and indexed queries for efficient reads and writes.


PostgreSQL (production)

Production-grade backend using asyncpg with a connection pool.
Direct INSERT on every log entry โ€” no intermediate buffer or drain step.

setup(app, config=FlareConfig(
    storage_backend="postgresql",
    pg_dsn="postgresql://user:password@localhost:5432/mydb",
))

Via environment variables:

FLARE_STORAGE_BACKEND=postgresql
FLARE_PG_DSN=postgresql://user:password@localhost:5432/mydb

Special characters in passwords:
URL-encode @ as %40, # as %23, & as %26, etc.
Example: password@123 โ†’ FLARE_PG_DSN=postgresql://user:password%40123@host:5432/db

The table flare_logs (or your custom name) is created automatically on first connection.


Multi-Project Isolation

You can run multiple independent APIs storing their logs in the same PostgreSQL server.
Two isolation strategies are available โ€” choose what fits best:

Strategy 1 โ€” One database per project (full isolation)

Each API points to a different database. Complete separation at the database level.

# API checkout
FLARE_PG_DSN=postgresql://user:pass@host:5432/checkout_db

# API auth
FLARE_PG_DSN=postgresql://user:pass@host:5432/auth_db

# API orders
FLARE_PG_DSN=postgresql://user:pass@host:5432/orders_db

Strategy 2 โ€” One database, separate tables (centralized)

All APIs share one database, each writing to its own table.
Simpler to manage โ€” one database to back up, one server to monitor.

# All APIs point to the same database
FLARE_PG_DSN=postgresql://user:pass@host:5432/mydb

# Each project gets its own table
FLARE_PG_TABLE_NAME=flare_logs_checkout  # API checkout
FLARE_PG_TABLE_NAME=flare_logs_auth      # API auth
FLARE_PG_TABLE_NAME=flare_logs_orders    # API orders

Each table is created automatically by flare on first connection.


Full Configuration

from fastapi_flare import setup, FlareConfig

setup(app, config=FlareConfig(
    # โ”€โ”€ Storage (choose one) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    storage_backend="sqlite",          # "sqlite" (default) | "postgresql"

    # SQLite options
    sqlite_path="flare.db",

    # PostgreSQL options
    pg_dsn="postgresql://user:pass@localhost:5432/mydb",
    pg_table_name="flare_logs",        # custom table name for multi-project setups

    # โ”€โ”€ Retention โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    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)

    # โ”€โ”€ Request tracking (HTTP Requests tab) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    track_requests=True,           # enable the HTTP Requests tab (default: True)
    track_2xx_requests=False,      # also record successful 2xx responses (default: False)
    request_max_entries=1000,      # ring buffer size for tracked requests
    capture_request_headers=False, # store request headers per entry (adds data volume)

    # โ”€โ”€ Non-HTTP error capture โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    capture_logging=False,             # forward WARNING+ from logging module
    capture_logging_loggers=None,      # "myapp.worker,myapp.jobs" โ€” None = root
    capture_asyncio_errors=False,      # capture stray asyncio task failures

    # โ”€โ”€ Worker โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    worker_interval_seconds=5,
    worker_batch_size=100,
))

Tip โ€” showing all requests in the HTTP Requests tab:
By default only 4xx and 5xx are recorded. To also capture 200 OK and other successful responses, set track_2xx_requests=True (or FLARE_TRACK_2XX_REQUESTS=true).

Environment Variables

All options can be configured via FLARE_* environment variables โ€” no code changes needed:

FLARE_STORAGE_BACKEND=postgresql
FLARE_PG_DSN=postgresql://user:pass@localhost:5432/mydb
FLARE_PG_TABLE_NAME=flare_logs
FLARE_RETENTION_HOURS=72
FLARE_MAX_ENTRIES=5000
FLARE_DASHBOARD_PATH=/errors
FLARE_DASHBOARD_TITLE="Production Errors"

# Request tracking
FLARE_TRACK_REQUESTS=true
FLARE_TRACK_2XX_REQUESTS=true   # record 200 OK and other successful responses
FLARE_REQUEST_MAX_ENTRIES=1000
FLARE_CAPTURE_REQUEST_HEADERS=false

# Non-HTTP error capture
FLARE_CAPTURE_LOGGING=true                 # forward logger.exception / logger.error
FLARE_CAPTURE_LOGGING_LOGGERS=myapp.worker # optional comma-separated allow-list
FLARE_CAPTURE_ASYNCIO_ERRORS=true          # capture stray asyncio tasks

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
Storage overview Backend info, connection status, pool stats (PostgreSQL) or file size (SQLite)
Auto-refresh 30s polling toggle

Issue Grouping (new in 0.3.0)

Until 0.2.x every captured error was a standalone row. Five hundred occurrences of the same ValueError meant five hundred lines to read. Starting in 0.3.0 fastapi-flare groups semantically-equivalent errors into issues the way Sentry and Rollbar do โ€” with occurrence counting, first/last-seen, and a resolve/reopen workflow.

What changed

  • New aba Issues at /flare/issues โ€” grouped view.
  • New table flare_issues (auto-migrated on both SQLite and PostgreSQL).
  • New column issue_fingerprint on flare_logs (idempotent ADD COLUMN IF NOT EXISTS).
  • Every push_log() now computes a deterministic fingerprint and upserts the issue.
  • New JSON API under /flare/api/issues.
  • The existing Errors tab (/flare) is unchanged โ€” it remains the raw stream.

No configuration required. Upgrading is transparent; existing deployments get the new table and column on next start, and rows created before the upgrade simply have issue_fingerprint = NULL.

How the fingerprint works

For each captured log, a 16-char blake2b hash is computed from:

Scenario Hash input
Has stack trace (generic exception / logger.exception) exception_type | endpoint | top-5 frames
HTTP-only signal (raised HTTPException) http | status_code | endpoint
Validation error (RequestValidationError) validation | endpoint
Fallback event | endpoint | message[:200]

Each stack frame is normalised to (basename(file), function_name) โ€” line numbers and absolute paths are dropped on purpose so ordinary refactors (moving code down the file, renaming a /srv/app/... path) do not re-fingerprint the same bug. Rename the file or the function and the issue does split โ€” that's usually the signal you want.

This is intentionally different from the cooldown fingerprint in fastapi_flare.alerting, which stays coarse (event + endpoint) to throttle Slack/Discord pings.

Behaviour you can rely on

  • 500 identical errors โ†’ 1 issue with occurrence_count = 500, the latest last_seen, and the original first_seen preserved.
  • Same ValueError, different call path โ†’ separate issues. Lets you tell apart an actual regression from an unrelated code path that happens to raise the same type.
  • Resolved issues reopen automatically the next time the same fingerprint fires โ€” resolved flips back to false and resolved_at is cleared.
  • Level upgrades, never downgrades. A WARNING issue that later hits ERROR becomes ERROR for good.
  • Issue state survives retention. When retention_hours purges raw logs, the flare_issues row keeps occurrence_count, first_seen, and last_seen. Only the drill-down list of occurrences shrinks.

Using the dashboard

Open /flare/issues:

  • Stat cards at the top โ€” Open / New (24h) / Resolved (7d) / Total.
  • Filter chips โ€” All / Open / Resolved.
  • Search โ€” matches on exception_type, endpoint, or sample message.
  • Row click โ€” opens an issue modal with the list of occurrences. Each occurrence row is clickable and shows the full stack trace, request body, headers, and context, the same as the Errors tab.
  • Resolve / Reopen button inside the modal. The change is reflected immediately in the stat cards and list.

JSON API

Method Path Description
GET /flare/api/issues Paginated list. Query: page, limit, resolved=true/false, search=...
GET /flare/api/issues/stats Counts used by the stat cards
GET /flare/api/issues/{fingerprint} Issue detail + paginated occurrences
PATCH /flare/api/issues/{fingerprint} Body {"resolved": true | false}

Example:

curl -s http://localhost:8003/flare/api/issues?resolved=false | jq
# { "issues": [ {...} ], "total": 12, "page": 1, "limit": 50, "pages": 1 }

curl -X PATCH http://localhost:8003/flare/api/issues/63d05fb9d296a8e1 \
  -H 'Content-Type: application/json' \
  -d '{"resolved": true}'
# { "ok": true, "action": "issue_status", "detail": "Issue resolved" }

Full reference (fingerprint internals, storage model, migration, gotchas): docs/issues.md.

Try it โ€” the demo app

A dedicated example under examples/example_issues.py exercises every grouping scenario:

poetry run uvicorn examples.example_issues:app --reload --port 8003
Route What it proves
GET /boom/value-error (ร—10) 1 issue with occurrence_count = 10
GET /boom/key-error (ร—5) separate issue (different exception type)
GET /boom/deep (ร—3) separate issue (same ValueError, different stack)
GET /items/{iid} 404 โ†’ HTTP 404 issue per endpoint
GET /users 403 โ†’ HTTP 403 issue
POST /signup with bad body 422 โ†’ RequestValidationError issue per endpoint
POST /orders with bad total 500 โ†’ RuntimeError issue
GET /trigger/manual captured via capture_exception() outside the request path
GET /stress/{n} generates n errors at once to exercise pagination

Full validation walkthrough:

# 1. Start the app
poetry run uvicorn examples.example_issues:app --reload --port 8003

# 2. Fire traffic
for i in {1..10}; do curl -s http://localhost:8003/boom/value-error >/dev/null; done
for i in {1..5};  do curl -s http://localhost:8003/boom/key-error   >/dev/null; done
curl -s http://localhost:8003/items/999 >/dev/null
curl -s http://localhost:8003/stress/50 >/dev/null

# 3. Open /flare/issues โ€” you'll see one row per issue kind with the right counts.
# 4. Click a row โ†’ modal shows every occurrence. Click one โ†’ full stack trace.
# 5. Click Resolve โ†’ issue leaves the Open filter.
# 6. Fire the same endpoint again โ†’ issue reopens automatically.

What's stored โ€” FlareIssue

class FlareIssue(BaseModel):
    fingerprint: str            # 16-char blake2b hex, primary key
    exception_type: str | None  # "ValueError" | "HTTP 404" | "RequestValidationError" | ...
    endpoint: str | None
    sample_message: str         # first message seen for this issue
    sample_request_id: str | None
    occurrence_count: int
    first_seen: datetime
    last_seen: datetime
    level: Literal["ERROR", "WARNING"]  # upgrades to ERROR, never downgrades
    resolved: bool
    resolved_at: datetime | None

Known limitations

  • Dynamic path params โ€” endpoints like /items/1 and /items/2 currently produce separate issues because handlers still capture request.url.path (raw). A follow-up will use the matched route template (/items/{iid}) instead, collapsing those into a single issue.
  • SQLite multi-tenancy โ€” flare_issues uses a fixed name on SQLite (matches the rest of the SQLite backend, which already has fixed logs, requests, flare_settings, flare_metrics_snapshots). PostgreSQL derives the issues table from pg_table_name like everything else, so multi-project PG setups work out of the box.
  • No backfill โ€” logs captured before 0.3.0 have NULL for issue_fingerprint and are not surfaced on the Issues tab. Running traffic after upgrade populates the grouping from that point forward.

Log Entry Schema

Every captured error is stored as a structured FlareLogEntry:

class FlareLogEntry(BaseModel):
    id: str                       # backend-native ID (row id for PG/SQLite)
    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
    issue_fingerprint: str | None # links this row to a FlareIssue (v0.3.0+)
    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
    request_body: dict | None     # captured request body (if enabled)

Capturing Non-HTTP Errors

By default fastapi-flare captures HTTP 4xx/5xx and unhandled exceptions inside the request path. You can also route errors that happen outside any request โ€” background tasks, workers, cron jobs, consumers, startup code, detached asyncio tasks โ€” into the same dashboard.

Three mechanisms are available. Use any combination.

1. Python logging integration (automatic)

Forwards every WARNING / ERROR record from Python's standard logging into Flare. Zero changes to your existing code โ€” any logger.exception(...) or logger.error(...) already in your codebase starts showing up on /flare.

setup(app, config=FlareConfig(
    capture_logging=True,
    # Optional: only listen to specific loggers.
    # Empty / omitted = attach to the root logger (catches everything that propagates).
    capture_logging_loggers="myapp.worker,myapp.jobs",
))

Anywhere in your code:

import logging
logger = logging.getLogger("myapp.worker")

try:
    process_job()
except Exception:
    logger.exception("job failed")   # โ† appears in /flare

The captured entry gets event=log.<logger-name>, endpoint=None, and a context auto-populated with logger, module, func, line, file.

2. Manual capture (explicit)

When you've already caught an exception and want to record it without re-raising, call capture_exception:

from fastapi_flare import capture_exception

try:
    await charge_customer(order)
except StripeError as e:
    await capture_exception(
        e,
        event="payment.retry_exhausted",
        context={"order_id": order.id, "attempts": 5},
    )
    # handle gracefully โ€” user is not affected

For non-exception signals (rate limits, degraded deps, audit events):

from fastapi_flare import capture_message

await capture_message(
    "rate-limit hit on outbound API",
    level="WARNING",
    event="outbound.rate_limited",
    context={"api": "sendgrid", "hits": 142},
)

3. asyncio unhandled-task capture

asyncio.create_task(...) that raises without being awaited normally disappears silently โ€” the event loop just prints a warning to stderr. Enable capture so these land on the dashboard:

setup(app, config=FlareConfig(
    capture_asyncio_errors=True,
))

Now any detached task that blows up gets recorded with event=asyncio.unhandled, full stack trace, and a context describing the task.

context โ€” free-form metadata

The context dict you pass (or the one auto-filled by the logging handler) is stored as JSON and rendered under the Context section of the modal. Use it for anything that doesn't fit the fixed fields โ€” job IDs, provider names, feature flags, versions, etc. Keys matching FlareConfig.sensitive_fields (password, token, api_key, โ€ฆ) are automatically redacted before storage.

Low-level API

All three mechanisms ultimately call push_log, which is still public if you need full control:

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(
    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

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)

setup(app, config=FlareConfig(
    zitadel_domain="auth.mycompany.com",
    zitadel_client_id="000000000000000001",
    zitadel_project_id="000000000000000002",
    zitadel_redirect_uri="https://myapp.com/flare/callback",
    zitadel_session_secret="<32-byte-hex>",
))

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>
# Generate: python -c "import secrets; print(secrets.token_hex(32))"

Flow:

  1. User opens /flare โ†’ no session โ†’ redirected to /flare/auth/login
  2. PKCE challenge generated โ†’ redirected to Zitadel login
  3. User logs in โ†’ Zitadel redirects to callback-url?code=...
  4. fastapi-flare exchanges code for token โ†’ creates signed session cookie
  5. User redirected to /flare โ€” access granted โœ…

Routes created automatically:

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

API Mode (Bearer Token)

When zitadel_redirect_uri is not set, the dashboard validates the Authorization: Bearer <token> header directly. No redirect flow.

Manual Mode (custom dependency)

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(dashboard_auth_dependency=dep))

Running the Example

# Zero-config SQLite (no setup needed)
poetry run uvicorn examples.example:app --reload --port 8000
# Dashboard at http://localhost:8000/flare

PostgreSQL example โ€” set in your .env:

FLARE_STORAGE_BACKEND=postgresql
FLARE_PG_DSN=postgresql://user:pass@localhost:5432/mydb

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

Non-HTTP capture demo

A dedicated example exercises the capture_logging, capture_asyncio_errors, capture_exception, and capture_message features end-to-end:

poetry run uvicorn examples.example_non_http_capture:app --reload --port 8002
# Dashboard at http://localhost:8002/flare
Route What it captures
GET /trigger/logger logger.exception(...) inside a handler
GET /trigger/manual capture_exception(e, context=...)
GET /trigger/asyncio A stray asyncio.create_task that raises
GET /trigger/background A worker thread that logs via logger.exception
GET /trigger/warn capture_message(...) at WARNING level

The app also emits two entries on startup โ€” proving that records outside the request path are visible on /flare before anyone hits an endpoint.


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
fastapi-flare Self-hosted, zero-config error tracking โ€” SQLite or PostgreSQL

Why not Sentry?

fastapi-flare Sentry
Hosting Self-hosted, your infra External SaaS
Account required No Yes
Setup One setup(app) call SDK + DSN + account config
Storage SQLite or PostgreSQL Kafka, ClickHouse, Postgres, โ€ฆ
Cost Zero Free tier โ†’ paid plans
Privacy Data never leaves your server Data sent to third-party
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.


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.4.0.tar.gz (114.3 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.4.0-py3-none-any.whl (124.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: fastapi_flare-0.4.0.tar.gz
  • Upload date:
  • Size: 114.3 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.4.0.tar.gz
Algorithm Hash digest
SHA256 a89c5898d0b55a2e2c7c0d4db93349530496cb025d1fc6e2c997bd5da2df3893
MD5 83d33d56bc2be0cac656146e2f8859b9
BLAKE2b-256 0e59dae7dd0a47b6b414baa4ec542dde2171e10e1f9aff0624631e7f33d21659

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fastapi_flare-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 124.6 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.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a9194e94080e6b9d8e139a7c3ebae90afc2c852e705f62bee96a385cd6fbe588
MD5 0b4bba524578de2b08b104ff04cc04d4
BLAKE2b-256 56c5c4c0def9cabd0bfe96648ec45f694b024417a12851369b35d123c60ec04c

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