Skip to main content

dazzle-loglib

PyPI Release Date PyPI Downloads Python License: MIT GitHub Discussions Platform

Channel/verbosity-aware CLI output management -- the diagnostic-output member of the perpendicular tier of the DazzleLib stack.

One signed verbosity axis crossed with consumer-defined named channels, so a program can answer how loud is each channel of my self-narration, and where does each message go? — per subsystem, independently, from one -v-stacking CLI surface.

pip install dazzle-loglib

What this owns (and what it doesn't)

Owns Does not own
The verbosity gate — one integer comparison, and no message is formatted unless it passes Color and rich formatting (supply a renderer callable; the hook is built in)
The channel registry each program declares for itself Your channel vocabulary — there is no built-in "correct" channel set
Where a message goes (per-manager, per-channel, or per-message destinations) Durable structured logs; this is on-demand interactive detail, not the audit record
Env/CLI resolution with defined precedence Reading the environment implicitly — you name your own variables
A hint registry (runtime, context-filtered, session-deduplicated) Help-surface content — that's dazzle-helplib's TIPs, a deliberately separate mechanism

The model: verbosity x channel

One signed verbosity axis (a dazzle_lib.Continuum with an invariant zero):

<-- quieter -------------------- default --------------------------- louder -->
-4       -3       -2       -1       0      1       2       3        4        5
wall  errors warnings  minimal default extra diagnostics config lite-debug debug

A message at level shows when level <= threshold; at -4 (the hard wall) nothing shows at all. -v steps warmer, -q steps colder, and they compose (-vv -q = 1).

Channels are the orthogonal dimension, and each program declares its own:

from dazzle_loglib import init_output, get_output, ChannelDef

init_output(
    verbosity=args.verbose - args.quiet,
    strict_channels=True,
    channel_defs=[
        ChannelDef("liveness", "Session liveness verification"),
        ChannelDef("git",      "Git operations"),
        ChannelDef("scan",     "Discovery and scanning"),
        ChannelDef("vals",     "Value annotations on results", opt_in=True),
    ],
    channels=args.show,          # e.g. ["liveness:diagnostics", "scan:2"]
)

out = get_output()
out.emit(1, "scanned {n} sessions", channel="scan", n=count)
out.emit(2, "entry={id} pid={pid} in_by_pid={hit} -> reject({rung})",
         channel="liveness", id=entry_id, pid=pid, hit=hit, rung=rung)

Each channel can be pinned independently of the global level, so --show liveness:debug floods one subsystem without drowning the rest. Named rungs work anywhere integers do, opt-in channels stay cold until raised, and the channels x verbosity crossing is a real ContinuumSpace (out.verbosity_space()) — so further axes compose rather than bolt on.

Status

0.3.x, alpha — and deliberately still flexible. This library ships mid-development of the wider DazzleLib stack: its first real consumer has not landed yet, and adoption is what usually reshapes an API. So the promise here is no silent drift rather than no changedocs/api-stability.md enumerates the tracked surface (pinned by an import-stability canary), the parts explicitly excluded from any promise, and, honestly, where movement is still expected. Changes land in CHANGELOG.md with a version bump, never quietly.

Usage

Zero cost when gated

emit() never formats a message that will not show — keyword arguments are interpolated only after the gate passes. For expensive collection, ask first:

if out.is_level_active(2, "liveness"):
    rows = expensive_enumeration()        # skipped entirely at default verbosity
    out.emit(2, "rows={n}", channel="liveness", n=len(rows))

Resolution with defined precedence

from dazzle_loglib import resolve_verbosity, resolve_channel_specs

verbosity = resolve_verbosity(args.verbose, args.quiet,
                              explicit=args.verbosity,     # --verbosity N wins outright
                              env_var="MYAPP_VERBOSITY")   # consulted only when the CLI is silent
specs = resolve_channel_specs(args.show, env_var="MYAPP_SHOW")

Precedence is explicit > CLI counts > environment > default, and CLI counts count as expressed whenever either is nonzero — -v -q nets to zero but still beats the environment. Hooks, schedulers, and other non-interactive contexts turn detail up by setting the variables; nothing edits scripts.

Injecting an emitter (the std-swappable seam)

Libraries that should never depend on a logging package can still speak:

from dazzle_loglib.protocols import EmitterProtocol, NullEmitter

def verify_tree(root, emitter: EmitterProtocol = None):
    emitter = emitter or NullEmitter()     # silent by default
    if emitter.is_level_active(2, "verify"):
        emitter.emit(2, "checking {p}", channel="verify", p=root)

EmitterProtocol is structural: a real OutputManager satisfies it, and so does a four-line shim over print (or CallableEmitter(logging.getLogger(__name__).info)). The contract travels down the stack; the implementation stays out of your dependency tree.

Renderers, hints, and tracing

emit() resolves a renderer in layers — per-call render=, per-channel renderer, global default_renderer, then plain print() to the resolved destination (stderr by default; 'stdout'/'stderr' sentinels resolve at emit time, so rebound streams are honored). Color belongs in a renderer callable (init_output(renderer=console.print)), never in the core. Also included: a Hint registry (context-filtered, session-deduplicated, routed through the same gate) and a @trace decorator (function entry/exit at full debug on the trace channel).

Installation

pip install dazzle-loglib

From source

git clone https://github.com/DazzleLib/dazzle-loglib.git
cd dazzle-loglib
pip install -e ".[dev]"

Documentation

Migrating from a vendored log_lib

Projects carrying the ancestral copy: 0.2.0 re-runged the verbosity scale (config 2→3, debug 3→5, timing renamed extra) and replaced module-set channel registration with channel_defs=. The legacy module sets still import but warn on mutation and are excluded from the API-stability guarantee. See DazzleTools/dazzlecmd#118 for the cutover playbook.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

python -m venv .venv
source .venv/bin/activate   # or .venv\Scripts\activate on Windows
pip install -e ".[dev]"

# Run tests
python -m pytest tests/ -v

# Install git hooks
bash scripts/repokit-common/install-hooks.sh

Two house rules this library lives by:

  • Dependencies point down only. The perpendicular tier consumes the bedrock and nothing else — never a consumer, never a sibling. dazzle-loglib and dazzle-helplib do not import each other.
  • The public surface changes loudly or not at all. The symbols and behaviors listed in docs/api-stability.md are pinned by tests/test_import_stability.py, so drift fails a test rather than reaching a consumer. While the stack is mid-development the surface is still expected to move; the discipline is that it moves deliberately, versioned, and documented.

Like the project?

"Buy Me A Coffee"

Part of DazzleLib

dazzle-loglib sits in the perpendicular tier: usable from any layer, depending only on the dazzle-lib bedrock.

Related Projects

License

dazzle-loglib, Copyright (C) 2026 Dustin Darcy

Licensed under the MIT License -- see LICENSE. The whole DazzleLib stack is MIT-licensed.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dazzle_loglib-0.3.3.tar.gz (41.0 kB view details)

Uploaded Source

Built Distribution

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

dazzle_loglib-0.3.3-py3-none-any.whl (31.6 kB view details)

Uploaded Python 3

File details

Details for the file dazzle_loglib-0.3.3.tar.gz.

File metadata

  • Download URL: dazzle_loglib-0.3.3.tar.gz
  • Upload date:
  • Size: 41.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dazzle_loglib-0.3.3.tar.gz
Algorithm Hash digest
SHA256 098bd03d1106516bdbe31b6621b5cef0b151bf51aea117317a27896d3c77f7bd
MD5 b6394957666b0e502d7cf89906c6cc3f
BLAKE2b-256 ed3cec13498bdf6b99377cc7af8c0af382ec5083edad394e8283c6407edec765

See more details on using hashes here.

Provenance

The following attestation bundles were made for dazzle_loglib-0.3.3.tar.gz:

Publisher: release.yml on DazzleLib/dazzle-loglib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dazzle_loglib-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: dazzle_loglib-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 31.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dazzle_loglib-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 c0b5f6222edc6b020ff9ca8e4d71a7b40fe6865ae2d557133eb046893baa6ee9
MD5 8b0574df7ef5b048b281132ae4b401a7
BLAKE2b-256 f6ce2476b51e49457c5a93db0344a3c8f2806aeaacc8389d30fce8626e7cb5fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for dazzle_loglib-0.3.3-py3-none-any.whl:

Publisher: release.yml on DazzleLib/dazzle-loglib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.3 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page