Skip to main content

nahiarhdlog

CI PyPI version Python Version License: MIT

Embedded observability for FastAPI — searchable logs, error tracking, alerts, metrics, tracing, and a token-locked dashboard. Zero infrastructure: everything lives in one SQLite file.

nahiarhdlog dashboard

Why nahiarhdlog?

  • No infrastructure. No ELK, no agents, no SaaS — pip install and you have history, search, and a UI.
  • Embedded dashboard. Your logs live at /admin/logs inside your own app, behind your own token.
  • Negligible overhead. Requests enqueue a small dict (p95 ~0.04 ms); SQLite writes happen in batches on a background thread. The queue is bounded — when full, events drop with a visible counter instead of ever blocking a request.
  • Framework-agnostic core. FastAPI first; the core imports no web framework, so Flask/Django adapters can follow without changing it.

Install

pip install nahiarhdlog
# or: uv add nahiarhdlog

Requires Python ≥ 3.10. Events are stored in .nahiarhdlog/nahiarhdlog.db (SQLite, WAL mode, FTS5 search).

Quickstart

from fastapi import FastAPI
from nahiarhdLOG import observe

app = FastAPI()
observe(app, dashboard_token="secret")  # logs + errors + metrics + dashboard

That's it. Every request, every stdlib log record, and every uncaught exception is now captured. Open /admin/logs and enter the token on the lock screen.

Features

Area What you get
Logs Auto-captured stdlib records + requests; full-text search (FTS5), level/type/time/trace filters, pagination
Errors Grouped by ExcType@file.py:line, full tracebacks, top-errors ranking
Alerts Threshold rules (N events in M seconds) + cooldown; webhook, Telegram, and SMTP sinks
Metrics RPS, error rate, latency p50/p95, time-bucketed series — computed from the same request events
Tracing One trace_id per request shared by logs and errors; timeline view; optional OpenTelemetry export
Dashboard Embedded at /admin/logs, token-locked, dark/light mode, mobile-friendly, live tail
Configuration — all arguments and .env wiring

observe() takes explicit arguments and never reads your environment or .env file itself — each app owns its config, so the same package works unchanged across projects:

Argument Default Meaning
db_path ".nahiarhdlog/nahiarhdlog.db" SQLite file for events (parent dirs auto-created)
dashboard_token None (dashboard off) Token for the dashboard; unset = no dashboard
dashboard_prefix "/admin/logs" Where the dashboard lives
retention_days 7 How long events are kept
sample_rate 1.0 1.0 = every request; 500s are always kept
level logging.INFO Minimum stdlib level captured
skip_paths [] Extra paths the middleware ignores (dashboard prefix is always excluded)

Typical .env-based wiring in your app:

# .env (never commit this file)
NAHILOG_DB=/var/lib/myapp/nahiarhdlog.db
NAHILOG_TOKEN=long-random-secret
import os
from fastapi import FastAPI
from nahiarhdLOG import observe

app = FastAPI()
observe(
    app,
    db_path=os.environ.get("NAHILOG_DB", ".nahiarhdlog/nahiarhdlog.db"),
    dashboard_token=os.environ.get("NAHILOG_TOKEN"),  # None = dashboard disabled
)

If your app loads .env via dotenv_values (read-only dict) instead of load_dotenv, os.environ won't see those values — pass them through your env helper instead.

Alerts & OpenTelemetry — rules, sinks, trace export
from nahiarhdLOG.alerter import Rule, SmtpSink, TelegramSink, WebhookSink

observe(
    app,
    rules=[Rule("api-errors", count=10, window_seconds=600, cooldown_seconds=1800)],
    sinks=[
        WebhookSink("https://hooks.example/deploy"),          # POSTs {"subject","body"} as JSON
        TelegramSink(bot_token="123:ABC", chat_id="-100..."),  # Bot API sendMessage
        SmtpSink("smtp.example.com", ["ops@example.com"], username="bot", password="..."),
    ],
    dashboard_token="secret",
)

Rules evaluate in a background thread; a failing sink never blocks the others.

pip install "nahiarhdlog[otel]"
from nahiarhdLOG.otel import export_trace
from nahiarhdLOG.query import get_trace

export_trace(get_trace(collector.storage, trace_id))  # keeps the original trace id

Example app

# terminal 1: run the demo
uv run python examples/basic_app.py serve

# terminal 2: generate traffic
uv run python examples/basic_app.py traffic --n 300

Open http://127.0.0.1:8000/admin/logs with token demo-token.

FAQ

Which Python versions? 3.10+ (3.10, 3.11, 3.12 tested in CI).

Where is data stored? One SQLite file (.nahiarhdlog/nahiarhdlog.db by default), WAL mode, FTS5 index for search. Delete the directory to wipe everything. Set retention_days for automatic purging.

Is the dashboard secure? It is mounted only when dashboard_token is set, and every page + API call requires the token (cookie set at login; old ?token= links migrate). Without it you get a lock screen (401). Use a long random token and HTTPS in production.

Why don't I see the dashboard's own requests in the logs? By design: the dashboard prefix is auto-excluded so its polling doesn't drown your signal. Add more with skip_paths.

What's the overhead? Requests only enqueue a small dict; SQLite writes happen in batches on a background thread. Run python scripts/probe_perf.py to measure on your machine.

Flask / Django / plain scripts? On the roadmap. The core (collector, storage, query, alerter, metrics) imports no web framework — only the thin adapters/ layer does, enforced by an automated boundary test.

How do I disable the dashboard? Omit dashboard_token (default): nothing is mounted.

Roadmap

  • Core logging, SQLite+FTS5 storage, search API
  • Error tracker + webhook alerts
  • Metrics + tracing (+ optional OpenTelemetry export)
  • Embedded dashboard UI
  • Flask/Django adapters
  • Postgres storage backend

Development

uv pip install -e ".[dev,otel]"
uv run --no-sync python -m pytest
uv run --no-sync python scripts/probe_perf.py --n 10000

Changelog

  • 0.2.0 — Default database moved to .nahiarhdlog/nahiarhdlog.db (a dot-directory keeps project roots clean; missing parent dirs are auto-created). Note: apps on the old default start a fresh database here — the old nahiarhdlog.db is left untouched.
  • 0.1.3 — Dashboard login persists via cookie: refresh and new tabs stay signed in; lock screen signs in without putting the token in the URL; old ?token= bookmarks keep working and migrate to a cookie. Added Lock button. Shutdown hook moved to lifespan composition (works alongside user-defined lifespans, Starlette 0.52–1.x).
  • 0.1.2 — Requests capture client IP + user agent; detail dialog rebuilt (no empty rows, status chips, "view full trace" jump); log rows keyboard-accessible (Tab + Enter).
  • 0.1.1 — NahiarhdHandler no longer appends a second traceback when the message already contains one (loguru-style pre-formatted records, manually formatted tracebacks).
  • 0.1.0 — Initial release: searchable logs, error tracker + alerts, metrics, tracing, embedded dashboard.

License

MIT — see LICENSE.

By Raihan Hidayatullah Djunaedi · nahiarhd.com · PyPI @nahiarhd

Metadata

Release files for nahiarhdlog 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nahiarhdlog 0.2.0
File Size Uploaded
nahiarhdlog-0.2.0.tar.gz 43.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nahiarhdlog 0.2.0
File Interpreter ABI Platform
nahiarhdlog-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 78.9 kB

Release files / nahiarhdlog-0.2.0.tar.gz

Download URL nahiarhdlog-0.2.0.tar.gz
Size 43.0 kB
Tags Source
SHA-256 checksum
How to use checksums
0c046d7f55b58b4434b46849d7258492f5d018df191f19df9842cb6952962b83
BLAKE2b-256 checksum
How to use checksums
504d49951e8e02527e23176261655941ddefcc73858de0c379bb4183a58b55c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / nahiarhdlog-0.2.0-py3-none-any.whl

Download URL nahiarhdlog-0.2.0-py3-none-any.whl
Size 35.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78ce14fdd3f5f12593df91d070e6fea1532c47d21c9e532be2e570dbd084519c
BLAKE2b-256 checksum
How to use checksums
8d978285f8e9b8b75590d778c7b3973f50d5b5befbb61e9569af574dce889b7a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

0.8.1

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page