dazzle-loglib
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 change — docs/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
- docs/api-stability.md — the tracked surface, what is excluded, where movement is still expected, and the protocol homing promise
- docs/cli-integration.md — the canonical CLI wiring: flags, resolution, help tables, keeping
--jsonoutput pure - CHANGELOG.md — release history
- ROADMAP.md — where this is going (tracked live in #1)
- docs/platform-support.md — platform and Python support
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-loglibanddazzle-helplibdo 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?
Part of DazzleLib
dazzle-loglib sits in the perpendicular tier: usable from any layer, depending only on the dazzle-lib bedrock.
Related Projects
- dazzle-lib — the bedrock: protocols, payload schemas, and the
Continuumprimitive this builds on - dazzle-helplib — the sibling: help content, detail continuum, and TIPs
- dazzle-filekit — cross-platform file operations
- dazzle-linklib — content-addressable link records
- The stack map — how the pieces fit
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
098bd03d1106516bdbe31b6621b5cef0b151bf51aea117317a27896d3c77f7bd
|
|
| MD5 |
b6394957666b0e502d7cf89906c6cc3f
|
|
| BLAKE2b-256 |
ed3cec13498bdf6b99377cc7af8c0af382ec5083edad394e8283c6407edec765
|
Provenance
The following attestation bundles were made for dazzle_loglib-0.3.3.tar.gz:
Publisher:
release.yml on DazzleLib/dazzle-loglib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dazzle_loglib-0.3.3.tar.gz -
Subject digest:
098bd03d1106516bdbe31b6621b5cef0b151bf51aea117317a27896d3c77f7bd - Sigstore transparency entry: 2486912547
- Sigstore integration time:
-
Permalink:
DazzleLib/dazzle-loglib@552856c4d4ce8c3ea7fd49374a9758a1b8d595b8 -
Branch / Tag:
refs/tags/v0.3.3 - Owner: https://github.com/DazzleLib
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@552856c4d4ce8c3ea7fd49374a9758a1b8d595b8 -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0b5f6222edc6b020ff9ca8e4d71a7b40fe6865ae2d557133eb046893baa6ee9
|
|
| MD5 |
8b0574df7ef5b048b281132ae4b401a7
|
|
| BLAKE2b-256 |
f6ce2476b51e49457c5a93db0344a3c8f2806aeaacc8389d30fce8626e7cb5fd
|
Provenance
The following attestation bundles were made for dazzle_loglib-0.3.3-py3-none-any.whl:
Publisher:
release.yml on DazzleLib/dazzle-loglib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dazzle_loglib-0.3.3-py3-none-any.whl -
Subject digest:
c0b5f6222edc6b020ff9ca8e4d71a7b40fe6865ae2d557133eb046893baa6ee9 - Sigstore transparency entry: 2486913243
- Sigstore integration time:
-
Permalink:
DazzleLib/dazzle-loglib@552856c4d4ce8c3ea7fd49374a9758a1b8d595b8 -
Branch / Tag:
refs/tags/v0.3.3 - Owner: https://github.com/DazzleLib
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@552856c4d4ce8c3ea7fd49374a9758a1b8d595b8 -
Trigger Event:
release
-
Statement type: