Add add_log_level() custom log-level API#466
Closed
goodboy wants to merge 0 commit into
Closed
Conversation
There was a problem hiding this comment.
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 acrossCUSTOM_LEVELS, stdliblogging, palettes, andStackLevelAdapteremit methods; registerIO=21. - Hoist the sub-actor proc-title prefix into
tractor.devx._proctitle._def_prefixand update reaper marker usage + tests accordingly. - Bump the
xonshminimum version to>=0.23.8and 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 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 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 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 on lines
+288
to
+290
| name_up: str = name.upper() | ||
| name_lo: str = name.lower() | ||
|
|
6683e3f to
1229fb5
Compare
ee79939 to
3b022d4
Compare
Owner
Author
Owner
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add
add_log_level()custom log-level APIMotivation
Registering a custom log level with
tractor's logging machinerymeant hand-syncing four separate pieces — the
CUSTOM_LEVELSmap(which drives the
stacklevelbump +get_logger()audit),logging.addLevelName(), theSTD_PALETTE/BOLD_PALETTEcolorentries, 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 nosingle entry-point keeping them consistent.
add_log_level()collapses all four into one call, so adding a levelis declarative and the per-level
get_logger()audit keeps passing.The new
IOlevel (21) is registered through it as the firstconsumer.
Summary of changes
add_log_level(name, value, color='white')(tractor.log) —one call wires the
CUSTOM_LEVELSentry,logging.addLevelName(),the
STD_PALETTE/BOLD_PALETTEcolors, and the bound lowercaseStackLevelAdapter.<name>()emit method. RegisterIO=21 as thefirst consumer;
tests.test_log_syscovers the round-trip._def_prefixmoduleconstant (
devx._proctitle) so the prefix is defined once andreused; update
tests.devx.test_proctitleaccordingly.xonsh>=0.23.8(pyproject.toml) and relockuv.locktomatch the bumped floor.
_root/_testing._reap/runtime._state/xontrib.tractor_diagadjustments.TODOs before landing
trio_033_upgrade; rebase forward as thelower stack lands. (
mtf_backend/ Addmain_thread_forkserverbackend #463 stacks above this.)(this pr content was generated in some part by
claude-code)