Skip to content

[feature] Record request origin in the durable routing log #640

Description

@ferrantejake

Problem

The per-request routing JSONL (--routing-log-file, crates/switchyard-server/src/routing_log.rs) records task, trial_id, and session_id, but nothing that identifies who/what sent the request. A gateway serving several harnesses (Claude Code, Codex CLI, custom agents, direct API callers) can't answer "which client produced this traffic?" from the durable log alone.

Downstream consumers tail the JSONL and can only show fields that exist in the record — origin cannot be recovered after the fact, because request headers aren't persisted anywhere durable.

Proposed change

Add an optional origin field to RoutingRecord, extracted in RoutingLogContext::from_metadata exactly like the existing task/trial_id headers:

  • Primary source: new x-switchyard-origin request header.
  • Fallback (optional, mirrors the LEGACY_SESSION_ID_HEADER precedent): derive a coarse origin from User-Agent when the header is absent — e.g. claude-code, codex-cli, openai-sdk.

RoutingRecord already uses #[serde(default)], so old and new records coexist on read (snapshot()) with no migration.

const ORIGIN_HEADER: &str = "x-switchyard-origin";

// in RoutingLogContext:
origin: Option<String>,

// in from_metadata:
origin: headers
    .and_then(|headers| nonempty_header(headers, ORIGIN_HEADER))
    .map(str::to_string),

Why this is cheap

RoutingLogContext::from_metadata (routing_log.rs, commit c665174) already plucks x-switchyard-intake-task / x-switchyard-trial-id out of metadata.http_headers — origin is the same pattern one line over. The field rides into the record in RoutingLog::append; no new plumbing beyond that.

Consumers

At least one known consumer: switchyard-studio tails this JSONL into SQLite for a routing-visibility console. It parses a field allowlist, so an additive field is ignored by existing readers and picked up with a small parse change on the consumer side.

We run the routing log enabled in production (x-switchyard-session-id already flows end-to-end), so we can validate the field live immediately after it lands, and are happy to test a prototype build.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions