Skip to content

Central, switchable logging across CLI, run(), and generated backends#63

Open
leon-k-martin wants to merge 2 commits into
devfrom
feat/central-logging
Open

Central, switchable logging across CLI, run(), and generated backends#63
leon-k-martin wants to merge 2 commits into
devfrom
feat/central-logging

Conversation

@leon-k-martin

Copy link
Copy Markdown
Collaborator

Central, switchable logging across all entry points

Running experiments emitted progress inconsistently: bare print() scattered through the package and generated code, an ad-hoc quiet/_log scheme plus verbose flags in the tvboptim templates, and — worst — tvbo/__init__.py did a process-wide logging.disable(logging.CRITICAL) that muted every logger (tvbo's own included), which is exactly why everyone reached for print.

This replaces that with one tvbo logger hierarchy and one switch, so tvbo run (CLI), SimulationExperiment.run(), and the generated backend scripts all log the same way and can be turned off centrally.

What changed

New tvbo/log.py — the central logging module:

  • A tvbo logger with a NullHandler (silent as a library by default; removed the global logging.disable).
  • Public API, re-exported from tvbo: configure_logging(), ensure_configured(), set_log_level(), get_log_level(), silence(), log_level() (context manager), get_logger().
  • One switch: TVBO_LOG_LEVEL env var (DEBUG/INFO/WARNING/ERROR/CRITICAL/OFF), or tvbo.set_log_level(...) / tvbo.silence() at runtime. An explicitly-set level sticks across repeated .run() calls.

Harmonized entry points

  • CLI: a global --log-level/-L, --verbose/-v, --quiet/-q callback configures the logger for every verb; cli/_common.info()/die() now route through it (machine-readable emit_json stays on stdout).
  • Python API: SimulationExperiment.run() calls ensure_configured() — visible progress in scripts/notebooks without clobbering an app's own logging setup.

Hot-path print → logger in classes/experiment.py, codegen/{code,templater}.py, data/types.py, adapters/julia.py, and the run-path classes/{dynamics,equation,observation,perturbation,atlas}.py.

Generated backend scripts (tvboptim experiment + algorithm, jax sim): emit logger = logging.getLogger("tvbo.run"), drop the _quiet/_log/print banner scheme, and configure logging in the standalone __main__ block from TVBO_LOG_LEVEL. In-process runs inherit tvbo's central config; the quiet=/verbose= kwargs are preserved for back-compat.

Behaviour change

import tvbo no longer calls logging.disable(CRITICAL), so tvbo (and other libraries') WARNING+ records are no longer globally suppressed. tvbo itself stays silent until an entry point or the app configures a handler.

Verified

  • Full package imports; every edited module compiles.
  • tvboptim experiment renders + runs; STEP progress logs at INFO; silence() / set_log_level("WARNING") / TVBO_LOG_LEVEL=OFF all suppress it and the setting sticks across runs.
  • CLI: info shows by default, hidden under --quiet, die still errors.
  • tests/test_tvboptim_byte_identity.py numeric faithfulness tests pass (trajectory/observation/optimization/inference).
  • The generated code is structurally identical to before apart from logging lines (verified by diff), so no numerical behaviour changed.

Note on a pre-existing failing test

test_experiment_result_roundtrips_via_sidecar (RWW-based) fails on this base with KeyError: 'empirical_fc' — reproduced on the committed base without these changes. It's unrelated to logging (the generated exploration code is byte-identical apart from log lines) and is already being reworked on dev (the in-progress Kuramoto _MINI_EXPERIMENT rewrite). Deselected from the numeric-guard run above.

Out of scope (follow-up)

prints in dev-tools (ontology/, database/, plot/, analysis/, api/) and other backend templates (rateml/julia) — mechanical, deferred.

Scope note

Branched from dev; unrelated uncommitted WIP in the main checkout is not included here (both touch experiment.py, so expect a small textual merge later).

…ckends

Replace the process-wide `logging.disable(CRITICAL)` and scattered bare
`print()`s with a single `tvbo` logger hierarchy and one central switch,
shared by `tvbo run`, `SimulationExperiment.run()`, and the generated
tvboptim/jax backend scripts, so logging is consistent no matter the entry
point and can be turned off centrally.

- tvbo/log.py: NullHandler by default (silent as a library); public API
  configure_logging / ensure_configured / set_log_level / get_log_level /
  get_logger / silence / log_level, plus the TVBO_LOG_LEVEL env switch. An
  explicitly set level sticks across repeated runs.
- __init__: drop the global logging.disable; re-export the public API.
- CLI: a global --log-level/--verbose/--quiet callback configures every verb;
  _common.info/die route through the logger (machine-readable emit_json stays
  on stdout).
- run(): ensure_configured() so scripts/notebooks surface progress like the CLI
  without clobbering an app's own logging.
- Hot-path print() -> logger in classes/, codegen/, data/, adapters/julia.
- Generated code: logging.getLogger("tvbo.run"); drop the _quiet/_log/print
  banner scheme; the standalone __main__ configures from TVBO_LOG_LEVEL.
  Generated output is byte-identical apart from logging lines.
- log.py: drop the unused get_logger() helper; trim the OFF-level aliases to
  OFF/NONE (the two documented spellings).
- experiment.py: hoist `from tvbo.log import ensure_configured` to module scope
  (was a per-call function-local import).
- cli: emit user-facing output through a bare formatter (no "LEVEL [name]"
  diagnostic prefix), matching the plain lines the CLI printed before.
- generated tvboptim: simplify the _log() helper to a single-arg form; guard the
  per-iteration algorithm progress with logger.isEnabledFor(INFO) so the float()
  device->host syncs are skipped when INFO is suppressed.
- codegen/templater._log_source: skip building the numbered listing when INFO is off.
- normalize stray blank lines after the added module loggers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant