FE-1221: Add structured correlated logging across the Petrinaut optimization pipeline#9059
FE-1221: Add structured correlated logging across the Petrinaut optimization pipeline#9059kube wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
PR SummaryMedium Risk Overview Correlation chain: NodeAPI forwards NodeAPI uses request-scoped logging for acceptance, validation failures (counts + bounded paths only), capacity/body rejections, stream lifecycle, and terminal outcomes ( petrinaut-opt adds JSON-lines logging ( petrinaut-cli emits bounded JSON stderr diagnostics after the unchanged ready handshake ( @local/petrinaut-optimizer-client now returns Logs intentionally omit manifests, user code, and raw bodies; tests assert redaction. Reviewed by Cursor Bugbot for commit f813baf. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2f81742. Configure here.
2f81742 to
e481051
Compare
…ization pipeline
One optimization is now traceable end to end: NodeAPI's x-hash-request-id
is forwarded upstream, the optimizer's run_id comes back as
X-Optimization-Run-ID and is logged on both sides, and the CLI receives
the run id at spawn as PETRINAUT_CORRELATION_ID.
- petrinaut-optimizer-client: openPetrinautOptimizationStream accepts a
requestId (sent as x-hash-request-id) and returns { events,
optimizationRunId } read from the X-Optimization-Run-ID header.
- hash-api: request-scoped child logger (Apollo pattern); logs request
acceptance, validation failures (issue counts and schema paths only),
capacity rejections, stream opening, and a terminal outcome with
durationMs (completed / timeout kind / upstream-error /
client-disconnected — disconnects no longer return silently).
- petrinaut-opt: stdlib JSON-lines logging to stdout (logging_config.py,
HASH_PETRINAUT_OPT_LOG_LEVEL, idempotent setup); inbound
x-hash-request-id and traceparent headers threaded into every study
lifecycle log (admission, capacity rejection, initialization,
study start/completion, per-trial outcomes, wall-clock ceiling,
disconnect, worker join timeout, CLI termination path, slot release).
CLI stderr is no longer discarded: each line is forwarded to a pn_cli
logger, truncated with a bounded pending buffer.
- petrinaut-cli: minimal JSON stderr diagnostics after the unchanged
ready handshake (bootstrap_completed, per-request id/method/durationMs/
outcome, stdin_eof), correlation id injected via cli.ts.
Logs never include manifests, user-authored code, or raw request bodies;
docs updated (README logging section, CLI stderr contract, threat model).
- Cap forwarded CLI stderr at 1000 lines/run (drain the rest) so a chatty or hostile CLI cannot flood the log pipeline; seed the drain thread with bytes read past the bootstrap handshake so an early CLI diagnostic is forwarded rather than dropped. - Truncate the per-trial pruned-error field and stop interpolating the raw CLI error into the log message; correct the docstring. - Log an error type and coarse category instead of the raw initialization error string, which can embed a user identifier or expression error; the full message still reaches the requester in the 500 detail. - Cap validation issue-path segments before they reach the 400 response or the log, since manifest keys are user-controlled and unbounded. - Capture the optimizer run id from a failed response so a pre-stream upstream failure still correlates end to end. - Charset-validate the traceparent trace id instead of int(..., 16), which accepted 0x-prefixed, underscored, and signed values. - Document the aggregate stderr cap and header validation in the threat model.
e481051 to
f813baf
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #9059 +/- ##
=======================================
Coverage 59.23% 59.24%
=======================================
Files 1391 1391
Lines 135181 135208 +27
Branches 6235 6242 +7
=======================================
+ Hits 80073 80100 +27
+ Misses 54145 54143 -2
- Partials 963 965 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|

🌟 What is the purpose of this PR?
Adds structured, correlated logging across the three Petrinaut optimization services so one optimization is traceable end to end — and surfaces the correlation ids to the browser. This is the observability needed to diagnose the intermittent staging
network error: the NodeAPI outcome log distinguishes a client disconnect from an upstream failure and records the request duration, and the run id now reaches the browser response.🔗 Related links
network error🚫 Blocked by
mainonce it merges)🔍 What does this change?
x-hash-request-id(NodeAPI) →run_id/X-Optimization-Run-ID(optimizer) →PETRINAUT_CORRELATION_ID(CLI spawn env) →correlationIdin CLI stderr diagnostics. NodeAPI now also setsX-Optimization-Run-IDon its own response (success and pre-stream-failure paths).logger.child({ requestId })logging request acceptance, validation failures (issue counts + bounded schema paths only), capacity rejections, stream-opened, and a terminal outcome withdurationMs— including the previously-silent client-disconnect case.logging_config.py(JSON-lines to stdout,HASH_PETRINAUT_OPT_LOG_LEVEL, charset-validatedtraceparentparsing); lifecycle events logged withrun_id/request_id/trace_id. CLI stderr is no longer discarded — each line is forwarded bounded per line (2000 chars), per pending buffer (16 KiB), and per run (1000 lines, then drained silently).diagnostics.tsJSON-per-line stderr logger; the ready-handshake line is unchanged as the exact first stderr line, followed bybootstrap_completed, one boundedrequestline per handled request, andstdin_eof.Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
🐾 Next steps
network erroronce and read the NodeAPIPetrinaut optimization finished/failedlog (durationMs,outcome,optimizationRunId) to confirm which hop resets the stream and at what duration.🛡 What tests cover this?
New/updated unit tests:
apps/petrinaut-opt(JSON formatter, log level, traceparent validation, correlation threading, CLI stderr forwarding/truncation/flood-cap/residue-seed, redaction of error strings, capacity/lifecycle logs),apps/hash-api(request-scoped logging, run-id header on success + failure, no manifest in logs),@local/petrinaut-optimizer-client(requestId header, run-id capture on success + error), andlibs/@hashintel/petrinaut-cli(stderr diagnostics shape, unchanged ready line).❓ How to test this?
cd apps/petrinaut-opt && uv run pytestturbo run test:unit --filter '@apps/hash-api' --filter '@local/petrinaut-optimizer-client' --filter '@hashintel/petrinaut-cli'