Skip to main content

dd-logging

Shared logging helpers for Digital Duck projects.

One consistent pattern for CLI tools and apps: a timestamped log file per run, in plain text, JSONL, or both. Stdlib only (logging, json).

Used by SPL.py, graflang, spl-llm and spl-flow.

Install

pip install dd-logging                 # from PyPI
pip install -e /path/to/dd-logging     # local editable install

Usage

from dd_logging import setup_logging, setup_console_logging, get_logger, log_event, disable_logging

# 1. Once per process (CLI entry point or app startup)
log_path = setup_logging(
    "run",
    root_name="my_app",        # top-level logger namespace
    adapter="openrouter",      # appended to the filename (optional)
    model="meta/llama-3",      # appended after the adapter, made filename-safe (optional)
    log_level="info",          # debug | info | warning | error
    log_format="both",         # text | jsonl | both
    console=False,             # also log to stderr (e.g. --verbose)
)
# → logs/run-openrouter-20260215-143022.log      (returned)
#   logs/run-openrouter-20260215-143022.jsonl    (when log_format="both")

# 2. In each module
_log = get_logger("nodes.text2spl", root_name="my_app")
_log.info("translating query  len=%d", len(query))

# 3. Structured events: readable in the .log, queryable fields in the .jsonl
log_event(_log, "node.fire", node="draft", fired=2)
# .log   12:00:01  INFO     my_app.nodes.text2spl  node.fire node=draft fired=2
# .jsonl {"ts": "...", "level": "INFO", "logger": "my_app.nodes.text2spl",
#         "msg": "node.fire node=draft fired=2", "event": "node.fire",
#         "node": "draft", "fired": 2}

# 3b. CLIs that want warnings on screen but a log file only for some commands
setup_console_logging("my_app", "info")     # stderr only; a later setup_logging() replaces it

# 4. Silence everything (e.g. --no-log)
disable_logging("my_app")

setup_logging returns the primary file: the text file for text/both, the JSONL file for jsonl.

JSONL format

One object per line: ts (UTC ISO-8601, ms), level, logger, msg, then any extra={...} fields, plus exc (formatted traceback) for log.exception(...). Non-serialisable values are rendered with str(). Field names that clash with LogRecord attributes in log_event get an f_ prefix.

jq -c 'select(.event=="node.fire") | {ts,node}' logs/run-*.jsonl

Environment overrides

Used only when the matching argument is left unset:

Variable Meaning
DD_LOG_LEVEL debug / info / warning / error
DD_LOG_DIR directory for log files (default ./logs)
DD_LOG_FORMAT text / jsonl / both
# myapp/logging_config.py
from pathlib import Path
from dd_logging import ProjectLogging

_pl = ProjectLogging("my_app", log_dir=Path(__file__).resolve().parent.parent / "logs")
get_logger, setup_logging, setup_console_logging, disable_logging, log_event = (
    _pl.get_logger, _pl.setup_logging, _pl.setup_console_logging, _pl.disable_logging, _pl.log_event)

Call-sites then write get_logger("api") and setup_logging("run", log_format="both").

Log file naming

<log_dir>/<run_name>[-<adapter>][-<model>]-<YYYYMMDD-HHMMSS>.<log|jsonl>

Logger hierarchy

my_app                     ← root (file handlers attached here)
├── my_app.api             ← get_logger("api", "my_app")
└── my_app.nodes.text2spl  ← get_logger("nodes.text2spl", "my_app")

Child loggers inherit the root's handlers; no per-module setup.

Design notes

  • propagate=False on the root: no duplicate output when the Python root logger already has a handler (Streamlit, pytest, Jupyter).
  • Repeat setup is safe: handlers from an earlier setup_logging call are closed and replaced (file and console).
  • Silent until configured: get_logger gives the root a NullHandler, so a library that logs before setup_logging doesn't trip Python's last-resort stderr.
  • No third-party dependencies.

Projects using dd-logging

Project Root name
SPL.py spl
graflang graflang
spl-flow spl_flow

Development

pip install -e ".[dev]" && pytest

License

MIT

Metadata

Release files for dd-logging 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 dd-logging 0.2.0
File Size Uploaded Provenance
dd_logging-0.2.0.tar.gz 9.6 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 18.4 kB

Release files / dd_logging-0.2.0.tar.gz

Download URL dd_logging-0.2.0.tar.gz
Size 9.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8706eb46e5b97a695608d7237fd1a9453552e860ceeed861339a6dd1fc85d882
BLAKE2b-256 checksum
How to use checksums
79ef47a9f214da453216d203aa8e9c7ee3d917fcc27be2fd15e6a1888df32755
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.5

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

Download URL dd_logging-0.2.0-py3-none-any.whl
Size 8.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d91544e56e64aedabdee8b30f6f01fb494727b511d706fdaf27e9f6fe8e09685
BLAKE2b-256 checksum
How to use checksums
6a49339f86a0c04b07ff6ac7bae7b18e1c06899626cd924b92bcfada3ff2e29e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.5

Security for dd-logging 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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