Repository navigation
feat(agent): correlate logs by cycle id across the whole call tree - #85
Merged
Merged
Conversation
Closes #84. The agent had no correlated logs: every module logged through a bare per-module stdlib logger, and the only id (the `cycle` int in main) was interpolated into the message string, process-local (collided across restarts), and never left main.py. A cycle's ~30 log lines across the diagnostic sub-agent, its tool calls, the report sub-agent, and escalation shared nothing tying them together, so overlapping cycles were unreconstructable. Add a shared logging_setup module that binds a per-cycle correlation id to a ContextVar (propagates across await within the task) and a logging.Filter that injects it onto every LogRecord. run_cycle sets a uuid-suffixed id (unique across restarts) at the top and resets it in finally; both entry points (agent main, MCP server) now configure logging through the shared helper so the format carries cid= for every line. Lines outside any cycle render a "-" sentinel. Tests: correlation propagation across module loggers, uniqueness across cycles, sentinel outside a cycle, idempotent configure, and run_cycle binding/reset end to end. Full suite 216 passed; ruff + mypy clean.
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.
Closes #84.
Problem
The agent had no correlated logs. Every module (
main,monitor,executor,escalation,tools/*) logged through a bare per-module stdlib logger. The only id, thecycleint inmain.run_loop, was interpolated into the message string (not a filterable field), process-local (reset to 1 on restart, so two runs' cycle-3 collided), and confined tomain.py. A cycle's ~30 log lines across the diagnostic sub-agent, its ~8 tool calls, the report sub-agent, and escalation shared nothing tying them together, so overlapping cycles or concurrent incidents were unreconstructable from the logs.Fix
New
logging_setupmodule:ContextVar(propagates acrossawaitwithin the asyncio task, so no threading through signatures);logging.Filterinjectscorrelation_idonto everyLogRecord(attached to the handler, so third-party loggers get it too);configure_logging()(idempotent) installs the format... [cid=%(correlation_id)s] ..., used by both entry points (agentmain, MCPserver);new_correlation_id()uses a uuid suffix so ids are unique across restarts.MonitorAgent.run_cyclesets the id at the top and resets it infinally. Lines outside any cycle render a-sentinel.Tests
test_logging_setup.py(7): propagation across module loggers, uniqueness across cycles, sentinel outside a cycle, reset restores previous, idempotent configure, format renders without a missing-attribute crash.test_monitor.py(+2):run_cyclebinds a realcyc-id during the cycle and clears it after; two cycles get distinct ids.Full suite 216 passed; ruff + mypy clean.
Follow-up (not here): JSON handler for prod per mb_observability. This delivers the correlation id, the load-bearing part.
https://claude.ai/code/session_01R5VygSzbGTggW7mHd3PVwE