Skip to content

Add add_log_level() custom log-level API#466

Closed
goodboy wants to merge 0 commit into
trio_033_upgradefrom
custom_log_levels_api
Closed

Add add_log_level() custom log-level API#466
goodboy wants to merge 0 commit into
trio_033_upgradefrom
custom_log_levels_api

Conversation

@goodboy

@goodboy goodboy commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Add add_log_level() custom log-level API

Motivation

Registering a custom log level with tractor's logging machinery
meant hand-syncing four separate pieces — the CUSTOM_LEVELS map
(which drives the stacklevel bump + get_logger() audit),
logging.addLevelName(), the STD_PALETTE/BOLD_PALETTE color
entries, and a same-named emit method bound on StackLevelAdapter.
Miss one and you get a wrong call-site in tracebacks, an unnamed
level, no color, or a missing log.<name>() method. There was no
single entry-point keeping them consistent.

add_log_level() collapses all four into one call, so adding a level
is declarative and the per-level get_logger() audit keeps passing.
The new IO level (21) is registered through it as the first
consumer.

Summary of changes

  • Add add_log_level(name, value, color='white') (tractor.log) —
    one call wires the CUSTOM_LEVELS entry, logging.addLevelName(),
    the STD_PALETTE/BOLD_PALETTE colors, and the bound lowercase
    StackLevelAdapter.<name>() emit method. Register IO=21 as the
    first consumer; tests.test_log_sys covers the round-trip.
  • Hoist the per-actor proc-title prefix into a _def_prefix module
    constant (devx._proctitle) so the prefix is defined once and
    reused; update tests.devx.test_proctitle accordingly.
  • Pin xonsh>=0.23.8 (pyproject.toml) and relock uv.lock to
    match the bumped floor.
  • Minor touch-ups riding along: code-style / newline tweaks and small
    _root / _testing._reap / runtime._state /
    xontrib.tractor_diag adjustments.

TODOs before landing

(this pr content was generated in some part by claude-code)

Copilot AI review requested due to automatic review settings June 22, 2026 21:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a single entry-point for registering custom log levels in tractor’s logging system, uses it to add a new IO level, and refactors the actor proc-title prefix into a shared constant to keep proctitle + reaper recognition aligned.

Changes:

  • Add tractor.log.add_log_level() to register a custom level across CUSTOM_LEVELS, stdlib logging, palettes, and StackLevelAdapter emit methods; register IO=21.
  • Hoist the sub-actor proc-title prefix into tractor.devx._proctitle._def_prefix and update reaper marker usage + tests accordingly.
  • Bump the xonsh minimum version to >=0.23.8 and update lockfile.

Reviewed changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tractor/log.py Adds add_log_level() API and registers the new IO level.
tests/test_log_sys.py Adds tests validating custom-level registration and adapter method wiring.
tractor/devx/_proctitle.py Introduces _def_prefix constant and updates set_actor_proctitle() to use it.
tractor/_testing/_reap.py Updates intrinsic proc-title markers to track the new proctitle prefix constant.
tests/devx/test_proctitle.py Updates proc-title assertions to use _def_prefix.
xontrib/tractor_diag.xsh Displays updated intrinsic marker info in the acli.reap xonsh alias output.
pyproject.toml Pins xonsh>=0.23.8.
uv.lock Relocks to reflect the bumped xonsh floor.
tractor/runtime/_state.py Minor whitespace / formatting cleanup.
tractor/_root.py Minor whitespace / formatting cleanup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tractor/log.py
Comment on lines +288 to +310
name_up: str = name.upper()
name_lo: str = name.lower()

CUSTOM_LEVELS[name_up] = value
logging.addLevelName(value, name_up)
STD_PALETTE[name_up] = color
BOLD_PALETTE['bold'][name_up] = f'bold_{color}'

if not hasattr(StackLevelAdapter, name_lo):
# bind via default-arg so `value` is captured (not
# late-bound); delegates to `.log()` exactly like the
# hand-written level methods above.
def _emit(
self,
msg: str,
*,
_level: int = value,
) -> None:
return self.log(_level, msg)

_emit.__name__ = name_lo
_emit.__qualname__ = f'StackLevelAdapter.{name_lo}'
setattr(StackLevelAdapter, name_lo, _emit)
Comment thread tractor/_testing/_reap.py
Comment on lines 233 to +237
_TRACTOR_PROC_CMDLINE_MARKERS: tuple[str, ...] = (
'tractor._child',
'tractor[',
_proctitle._def_prefix,
)
_TRACTOR_PROC_COMM_MARKER: str = 'tractor['
_TRACTOR_PROC_COMM_MARKER: str = _proctitle._def_prefix
Comment thread tests/test_log_sys.py
Comment on lines +199 to +223
try:
log.add_log_level(name, val, 'cyan')

assert log.CUSTOM_LEVELS[name] == val
assert logging.getLevelName(val) == name
assert log.STD_PALETTE[name] == 'cyan'
assert log.BOLD_PALETTE['bold'][name] == 'bold_cyan'

# the audit in `get_logger()` (asserts a method per
# `CUSTOM_LEVELS` entry) must still pass.
xlog = log.get_logger('xlvl_test')
emit = getattr(xlog, name.lower(), None)
assert callable(emit)
emit('hello from a plugged-in level')

finally:
# best-effort cleanup of our module-global mutations so
# later `get_logger()` audits don't see a half-removed
# level.
log.CUSTOM_LEVELS.pop(name, None)
log.STD_PALETTE.pop(name, None)
log.BOLD_PALETTE['bold'].pop(name, None)
if hasattr(log.StackLevelAdapter, name.lower()):
delattr(log.StackLevelAdapter, name.lower())

Comment thread tractor/log.py
Comment on lines +288 to +290
name_up: str = name.upper()
name_lo: str = name.lower()

@goodboy goodboy added the devx-tooling "developer experience" improvements as provided `tractor.devx` for runtime dependents. label Jun 22, 2026
@goodboy goodboy force-pushed the trio_033_upgrade branch from 6683e3f to 1229fb5 Compare June 23, 2026 22:53
@goodboy goodboy closed this Jun 23, 2026
@goodboy goodboy force-pushed the custom_log_levels_api branch from ee79939 to 3b022d4 Compare June 23, 2026 22:53
@goodboy

goodboy commented Jun 24, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #467 — the stack reorder ( now sits below trio_033_upgrade) made this PR's base contain its head, so GitHub auto-closed it and won't let it reopen/retarget. Continuing as #467 (base trionics_start_or_cancel).

@goodboy

goodboy commented Jun 24, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #467 — the stack reorder put custom_log_levels_api below trio_033_upgrade, so this PR base now contains its head and GitHub auto-closed it (and refuses to reopen/retarget). Continuing as #467 (base trionics_start_or_cancel).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devx-tooling "developer experience" improvements as provided `tractor.devx` for runtime dependents.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants