Skip to content

feat(dev): ship runner module logs to dispatch (log pipeline)#36

Merged
I-am-nothing merged 1 commit into
mainfrom
feat/dev-runner-log-shipper
Jun 29, 2026
Merged

feat(dev): ship runner module logs to dispatch (log pipeline)#36
I-am-nothing merged 1 commit into
mainfrom
feat/dev-runner-log-shipper

Conversation

@I-am-nothing

Copy link
Copy Markdown
Contributor

What

Slice 3 of the module log pipeline — the dev runner's write path. The in-container dev --all runner already line-reads each module's stdout/stderr (spawn_forwarder); now it also ships each line to dispatch's ingest (#275), which buffers it into the per-module ring the developer console (#94) reads.

  • log_shipper::parse_line turns a line into {ts, level, msg, app_id} — extracting the SDK's structured JSON (slog) level/msg/time/app_id, falling back to the stream (stderr→warn, stdout→info) with the raw line for non-JSON output.
  • A per-module background thread batches entries (cap 200 / ~1s) and POSTs them to {MS_DISPATCH_URL}/internal/modules/{id}/logs with X-MS-Service-Secret == MS_INTERNAL_SECRET — the host-minted per-session secret the ingest binds to (confirmed: the host injects it into the compose env, so the runner's value == the session's registered InternalSecret).
  • Best-effort throughout: a failed or unconfigured (MS_DISPATCH_URL/secret unset) ship never blocks the module — logs just stay in the terminal as before.

app_id rides each entry so the app-side console (the logs:read work) can filter a shared dev module's logs per app. Dispatch ignores the field until the Go Entry.AppID follow-up.

Verification

cargo check clean; cargo test log_shipper — 5 tests green (JSON parse incl. app_id, message-alias + error level, non-JSON stream fallback, level normalization, shipping-disabled-without-config); cargo fmt clean.

🤖 Generated with Claude Code

Slice 3 of the module log pipeline — the dev runner's write path. The
in-container `dev --all` runner already line-reads each module's stdout/stderr
(spawn_forwarder); now it also parses each line and ships it to dispatch's
ingest, which buffers it into the per-module ring the developer console reads.

- log_shipper: parse_line turns a line into {ts,level,msg,app_id} — extracting
  the SDK's structured JSON (slog) fields, falling back to the stream
  (stderr→warn, stdout→info) for non-JSON lines. A per-module background thread
  batches entries (cap 200 / ~1s) and POSTs them to
  {MS_DISPATCH_URL}/internal/modules/{id}/logs with X-MS-Service-Secret ==
  MS_INTERNAL_SECRET (the host-minted per-session secret the ingest binds to).
  Best-effort: a failed or unconfigured ship never blocks the module.
- app_id rides each entry so the app-side console can filter a shared dev
  module's logs per app (dispatch ignores the field until the Go Entry.AppID
  follow-up).

Verified: cargo check + cargo test (5 log_shipper tests) green; cargo fmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant