Fix package logger names for daemon startup
Remove only the exact `piker.` prefix before delegating to Tractor's logger factories; `lstrip()` treated it as a character set and renamed submodules such as `piker.paper` to `piker.aper`. Drop stale parent-namespace assertions in service, data, broker and EMS startup while retaining console setup. Exercise both factories with service and prefix-sensitive submodule names. Prompt-IO: ai/prompt-io/opencode/20261019T123725Z_eed58566_logger_compat_prompt_io.md (this patch was generated in some part by `opencode` using `gpt-6.1-sol` (`openai`))wkt/ib_downstream_pin_eval
parent
eed5856622
commit
5adf77a94b
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
created_at: 2026-10-19T12:37:25Z
|
||||||
|
generated_by:
|
||||||
|
harness: opencode
|
||||||
|
provider: openai
|
||||||
|
model: openai/gpt-6.1-sol
|
||||||
|
git_ref: eed58566
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20261019T123725Z_eed58566_logger_compat_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
During the requested downstream/manual IB evaluation, the user reported
|
||||||
|
immediate chart startup failure at the stale assertion
|
||||||
|
`assert log.name == 'piker.service'` in maybe_spawn_daemon().
|
||||||
|
The user then asked why continuing the post-mortem debugger ended with
|
||||||
|
KeyboardInterrupt from the chart window's closeEvent().
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Located the existing downstream logger compatibility commit
|
||||||
|
c07e3cbde21807a4e193b3527ef8686a22cf4d96 and reproduced its code and
|
||||||
|
existing regression tests in the evaluation worktree, unstaged.
|
||||||
|
Preserved the earlier editable Tractor/dependency setup.
|
||||||
|
Explained that closeEvent() sends SIGINT during chart teardown, adding
|
||||||
|
a secondary KeyboardInterrupt after the original assertion unwinds.
|
||||||
|
No window-close behaviour was modified.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- piker/log.py: exact package-prefix removal in both logger factories.
|
||||||
|
- piker/service/_daemon.py: remove stale parent logger assertion.
|
||||||
|
- piker/data/_daemon.py: retain setup, remove assertion-only local.
|
||||||
|
- piker/brokers/_daemon.py: same broker startup compatibility fix.
|
||||||
|
- piker/clearing/_ems.py: same EMS startup compatibility fix.
|
||||||
|
- tests/test_logging.py: original four logger namespace regressions.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- Logger regressions: four passed with --noconftest.
|
||||||
|
- Normal pytest collection blocked by duplicate --ll registration.
|
||||||
|
- Separate local TCP registrar smoke: pikerd/data daemon startup,
|
||||||
|
registration and teardown succeeded; no provider feed opened.
|
||||||
|
- Imports resolve to this evaluation worktree and the evaluated
|
||||||
|
Tractor logging worktree.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
None observed in this compatibility patch at capture time.
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
created_at: 2026-10-19T12:37:25Z
|
||||||
|
generated_by:
|
||||||
|
harness: opencode
|
||||||
|
provider: openai
|
||||||
|
model: openai/gpt-6.1-sol
|
||||||
|
git_ref: eed58566
|
||||||
|
diff_cmd: git diff HEAD -- piker/log.py piker/service/_daemon.py piker/data/_daemon.py piker/brokers/_daemon.py piker/clearing/_ems.py
|
||||||
|
---
|
||||||
|
|
||||||
|
## Captured response
|
||||||
|
|
||||||
|
Found it: downstream `c07e3cbd` (“Preserve exact `piker`
|
||||||
|
logger namespaces”) removes this assertion and the equivalent
|
||||||
|
ones in data, broker and EMS startup. It also fixes the logger
|
||||||
|
prefix handling.
|
||||||
|
|
||||||
|
That compatibility patch was present in our earlier evaluation
|
||||||
|
stack but is absent from this base. I’ll apply its code and
|
||||||
|
existing regression tests here as an unstaged patch.
|
||||||
|
|
||||||
|
## Patch provenance
|
||||||
|
|
||||||
|
The five production-file changes and tests/test_logging.py reproduce
|
||||||
|
the code/test changes from c07e3cbde21807a4e193b3527ef8686a22cf4d96.
|
||||||
|
This is a working-tree transplant, not a new commit or cherry-pick.
|
||||||
|
The test file's Git blob is 437554461de44833940b24d77a565160fc3ac6e0,
|
||||||
|
matching the original commit. piker/log.py matches that commit.
|
||||||
|
|
||||||
|
## Verification output
|
||||||
|
|
||||||
|
Logger tests with --noconftest: 4 passed in 0.36s.
|
||||||
|
Normal pytest startup failed before collection because both Piker and
|
||||||
|
modern Tractor register --ll. The logger tests use no project fixtures.
|
||||||
|
An external disposable-registrar smoke script exercised open_pikerd(),
|
||||||
|
maybe_spawn_datad('kraken'), registration and teardown successfully:
|
||||||
|
Data daemon startup: OK
|
||||||
|
|
||||||
|
## Follow-up response
|
||||||
|
|
||||||
|
Yep—the traceback shows the window’s `closeEvent()` explicitly
|
||||||
|
sending SIGINT to its own process, which raises `KeyboardInterrupt`.
|
||||||
|
Continuing a post-mortem REPL lets the original assertion unwind;
|
||||||
|
it doesn’t resume successful startup. The resulting window close
|
||||||
|
then adds that KBI. It’s secondary shutdown behaviour, and it
|
||||||
|
makes the original failure harder to read.
|
||||||
|
|
@ -77,12 +77,11 @@ async def _setup_persistent_brokerd(
|
||||||
# any further (level) configuration on their own B)
|
# any further (level) configuration on their own B)
|
||||||
actor: tractor.Actor = tractor.current_actor()
|
actor: tractor.Actor = tractor.current_actor()
|
||||||
tll: str = actor.loglevel
|
tll: str = actor.loglevel
|
||||||
log = get_console_log(
|
get_console_log(
|
||||||
level=loglevel or tll,
|
level=loglevel or tll,
|
||||||
name=f'{_util.subsys}.{brokername}',
|
name=f'{_util.subsys}.{brokername}',
|
||||||
with_tractor_log=bool(tll),
|
with_tractor_log=bool(tll),
|
||||||
)
|
)
|
||||||
assert log.name == _util.subsys
|
|
||||||
|
|
||||||
# unblock caller
|
# unblock caller
|
||||||
await ctx.started()
|
await ctx.started()
|
||||||
|
|
|
||||||
|
|
@ -810,11 +810,10 @@ async def _setup_persistent_emsd(
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
if loglevel:
|
if loglevel:
|
||||||
_log = get_console_log(
|
get_console_log(
|
||||||
level=loglevel,
|
level=loglevel,
|
||||||
name=subsys,
|
name=subsys,
|
||||||
)
|
)
|
||||||
assert _log.name == 'piker.clearing'
|
|
||||||
|
|
||||||
global _router
|
global _router
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,12 +86,11 @@ async def _setup_persistent_datad(
|
||||||
# their own B)
|
# their own B)
|
||||||
actor: tractor.Actor = tractor.current_actor()
|
actor: tractor.Actor = tractor.current_actor()
|
||||||
tll: str = actor.loglevel
|
tll: str = actor.loglevel
|
||||||
log = get_console_log(
|
get_console_log(
|
||||||
level=loglevel or tll,
|
level=loglevel or tll,
|
||||||
name=f'{_util.subsys}.{brokername}',
|
name=f'{_util.subsys}.{brokername}',
|
||||||
with_tractor_log=bool(tll),
|
with_tractor_log=bool(tll),
|
||||||
)
|
)
|
||||||
assert log.name == _util.subsys
|
|
||||||
|
|
||||||
# XXX: ALSO enable console logging for the provider
|
# XXX: ALSO enable console logging for the provider
|
||||||
# backend's mod subtree (eg. `piker.brokers.ib.*`)
|
# backend's mod subtree (eg. `piker.brokers.ib.*`)
|
||||||
|
|
|
||||||
33
piker/log.py
33
piker/log.py
|
|
@ -36,6 +36,15 @@ from pygments import (
|
||||||
_proj_name: str = 'piker'
|
_proj_name: str = 'piker'
|
||||||
|
|
||||||
|
|
||||||
|
def _relative_name(
|
||||||
|
name: str|None,
|
||||||
|
) -> str|None:
|
||||||
|
if name:
|
||||||
|
return name.removeprefix(f'{_proj_name}.')
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_logger(
|
def get_logger(
|
||||||
name: str|None = None,
|
name: str|None = None,
|
||||||
**tractor_log_kwargs,
|
**tractor_log_kwargs,
|
||||||
|
|
@ -47,17 +56,9 @@ def get_logger(
|
||||||
See `tractor.log.get_logger()` for details.
|
See `tractor.log.get_logger()` for details.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
pkg_name: str = _proj_name
|
|
||||||
if (
|
|
||||||
name
|
|
||||||
and
|
|
||||||
pkg_name in name
|
|
||||||
):
|
|
||||||
name: str = name.lstrip(f'{_proj_name}.')
|
|
||||||
|
|
||||||
return tractor.log.get_logger(
|
return tractor.log.get_logger(
|
||||||
name=name,
|
name=_relative_name(name),
|
||||||
pkg_name=pkg_name,
|
pkg_name=_proj_name,
|
||||||
**tractor_log_kwargs,
|
**tractor_log_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -81,14 +82,6 @@ def get_console_log(
|
||||||
You do it.. Bp
|
You do it.. Bp
|
||||||
|
|
||||||
'''
|
'''
|
||||||
pkg_name: str = _proj_name
|
|
||||||
if (
|
|
||||||
name
|
|
||||||
and
|
|
||||||
pkg_name in name
|
|
||||||
):
|
|
||||||
name: str = name.lstrip(f'{_proj_name}.')
|
|
||||||
|
|
||||||
tll: str|None = None
|
tll: str|None = None
|
||||||
if (
|
if (
|
||||||
with_tractor_log is not False
|
with_tractor_log is not False
|
||||||
|
|
@ -111,8 +104,8 @@ def get_console_log(
|
||||||
|
|
||||||
return tractor.log.get_console_log(
|
return tractor.log.get_console_log(
|
||||||
level=level,
|
level=level,
|
||||||
name=name,
|
name=_relative_name(name),
|
||||||
pkg_name=pkg_name,
|
pkg_name=_proj_name,
|
||||||
**tractor_log_kwargs,
|
**tractor_log_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ async def maybe_spawn_daemon(
|
||||||
level=loglevel,
|
level=loglevel,
|
||||||
name=__name__,
|
name=__name__,
|
||||||
)
|
)
|
||||||
assert log.name == 'piker.service'
|
|
||||||
|
|
||||||
# serialize access to this section to avoid
|
# serialize access to this section to avoid
|
||||||
# 2 or more tasks racing to create a daemon
|
# 2 or more tasks racing to create a daemon
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
'''
|
||||||
|
Package logger namespace regression tests.
|
||||||
|
|
||||||
|
'''
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from piker.log import (
|
||||||
|
get_console_log,
|
||||||
|
get_logger,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'factory',
|
||||||
|
[
|
||||||
|
get_logger,
|
||||||
|
get_console_log,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'name',
|
||||||
|
[
|
||||||
|
'piker.service._daemon',
|
||||||
|
'piker.paper',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_package_logger_name(
|
||||||
|
factory,
|
||||||
|
name: str,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
`str.lstrip('piker.')` treated the package prefix as a set of
|
||||||
|
removable characters. A submodule beginning with any of those
|
||||||
|
characters, such as `piker.paper`, was silently renamed to
|
||||||
|
`piker.aper`, while service code asserted a stale parent name.
|
||||||
|
|
||||||
|
Exercise both logger factories with service and prefix-sensitive
|
||||||
|
submodule names, proving they retain the exact requested package
|
||||||
|
namespace.
|
||||||
|
|
||||||
|
'''
|
||||||
|
log = factory(name=name)
|
||||||
|
|
||||||
|
assert log.name == name
|
||||||
Loading…
Reference in New Issue