Skip to content

feat(observability): export gateway traces over OTLP - #2534

Merged
krishicks merged 1 commit into
mainfrom
hicks/push-xkzytkpxvnru
Jul 30, 2026
Merged

feat(observability): export gateway traces over OTLP#2534
krishicks merged 1 commit into
mainfrom
hicks/push-xkzytkpxvnru

Conversation

@krishicks

@krishicks krishicks commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add an opt-in OTLP/gRPC trace exporter to the gateway. Export is enabled by the presence of an [openshell.gateway.otlp] table with an endpoint; there is no separate toggle.

image

Related Issue

#2507

Changes

Instrumented:

  • Inbound request server spans, named for the RPC ($service/$method) or {method} {path} for plain HTTP. They continue valid W3C traceparent context when present and start a new trace otherwise. gRPC spans also carry rpc.system, rpc.service, rpc.method, and trailer-derived rpc.grpc.status_code.
  • Compute driver calls (create, delete, list, get, validate, watch) as client spans anchored on the ComputeDriver contract.
  • Store reads and writes as children of the current request or loop span.
  • Work with no inbound request: the sandbox reconcile sweep, provider credential refresh tick, and driver watch events. Each roots one operation trace so its store calls do not arrive as anonymous single-span traces.

This is deliberately not exhaustive. Auth, policy evaluation, and middleware remain uninstrumented, as do store lifecycle calls (ping, close) that a readiness poll would turn into a span per tick. The aim is a useful trace tree at a reviewable size; coverage can grow against real traces.

Design notes:

  • The TOML table owns whether and where to export. The SDK OTEL_* variables own how; sampling, batching, and limits are not mirrored into gateway config.
  • The OpenTelemetry layer exports spans only. Existing tracing events remain on the stdout and sandbox-log paths and are not copied into trace payloads.
  • Telemetry never blocks the gateway. A malformed endpoint logs an error and disables export rather than failing startup, and buffered spans are drained during graceful shutdown.
  • Failed spans carry error status without a separate error.type attribute. Request spans use HTTP status and gRPC response trailers; driver spans use the returned gRPC status; autonomous loop spans record failed results explicitly. Store spans exempt UniqueViolation and Conflict, because those errors report expected contention such as a held lease or an optimistic-concurrency retry.
  • The compute driver is reachable only through TracedDriver::call, so a call cannot skip its span. This is the client half of a client/server pair and the single place to inject context if drivers move out of process.
  • Tests share one process-wide subscriber and in-memory exporter because tracing caches callsite interest globally.

Inbound W3C trace context is propagated into gateway request spans. Context is not yet injected into outbound driver calls, so a future out-of-process driver would still need propagation at the TracedDriver seam.

The Helm chart is intentionally unchanged, so OTLP export cannot yet be enabled on a chart-deployed gateway.

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@github-actions

Copy link
Copy Markdown

Comment thread crates/openshell-server/src/tracing_bus.rs Outdated
Comment thread docs/reference/gateway-config.mdx Outdated
@krishicks
krishicks force-pushed the hicks/push-xkzytkpxvnru branch from db0eb97 to 93400ae Compare July 29, 2026 15:54
@copy-pr-bot

copy-pr-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@krishicks
krishicks force-pushed the hicks/push-xkzytkpxvnru branch 4 times, most recently from ada1a79 to 33f6b95 Compare July 30, 2026 00:30
Comment thread crates/openshell-server/src/grpc/sandbox.rs
Comment thread crates/openshell-server/src/multiplex.rs Outdated
@krishicks
krishicks force-pushed the hicks/push-xkzytkpxvnru branch 2 times, most recently from 916764d to 4be1bc9 Compare July 30, 2026 14:35
Comment thread crates/openshell-server/src/persistence/mod.rs
Add an opt-in OTLP/gRPC trace exporter to the gateway. Export is enabled
by the presence of an `[openshell.gateway.otlp]` table with an endpoint;
there is no separate toggle.

Instrumented:

- Inbound request server spans, named for the RPC (`$service/$method`) or
  `{method} {path}` for plain HTTP. They continue valid W3C `traceparent`
  context when present and start a new trace otherwise. gRPC spans also
  carry `rpc.system`, `rpc.service`, `rpc.method`, and trailer-derived
  `rpc.grpc.status_code`.
- Compute driver calls (create, delete, list, get, validate, watch) as
  client spans anchored on the `ComputeDriver` contract.
- Store reads and writes as children of the current request or loop span.
- Work with no inbound request: compute driver initialization, the sandbox
  reconcile sweep, provider credential refresh tick, and driver watch events.
  Each roots one operation trace so its child work does not arrive as anonymous
  single-span traces.

This is deliberately not exhaustive. Auth, policy evaluation, and
middleware remain uninstrumented, as do store lifecycle calls (`ping`,
`close`) that a readiness poll would turn into a span per tick. The aim is
a useful trace tree at a reviewable size; coverage can grow against real
traces.

Design notes:

- The TOML table owns whether and where to export. The SDK `OTEL_*`
  variables own how; sampling, batching, and limits are not mirrored into
  gateway config.
- The OpenTelemetry layer exports spans only. Existing `tracing` events
  remain on the stdout and sandbox-log paths and are not copied into trace
  payloads.
- Telemetry never blocks the gateway. A malformed endpoint logs an error
  and disables export rather than failing startup, and buffered spans are
  drained during graceful shutdown.
- Failed spans carry error status without a separate `error.type` attribute.
  Request spans use HTTP status and gRPC response trailers; driver spans use
  the returned gRPC status; autonomous loop spans record failed results
  explicitly. Store spans exempt `UniqueViolation` and `Conflict`, because
  those errors report expected contention such as a held lease or an
  optimistic-concurrency retry.
- The compute driver is reachable only through `TracedDriver::call`, so a
  call cannot skip its span. This is the client half of a client/server pair
  and the single place to inject context if drivers move out of process.
- Tests share one process-wide subscriber and in-memory exporter because
  `tracing` caches callsite interest globally.

Inbound W3C trace context is propagated into gateway request spans. Context
is not yet injected into outbound driver calls, so a future out-of-process
driver would still need propagation at the `TracedDriver` seam.

The Helm chart is intentionally unchanged, so OTLP export cannot yet be
enabled on a chart-deployed gateway.

Refs #2507

Signed-off-by: Kris Hicks <khicks@nvidia.com>
@krishicks
krishicks force-pushed the hicks/push-xkzytkpxvnru branch from fd3374c to 22b36a6 Compare July 30, 2026 17:07
@krishicks
krishicks enabled auto-merge July 30, 2026 17:17

@pimlock pimlock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I left couple comments, but these can be follow ups.

Comment thread docs/reference/gateway-config.mdx
Comment thread crates/openshell-server/src/provider_refresh.rs
@krishicks
krishicks added this pull request to the merge queue Jul 30, 2026
Merged via the queue into main with commit fa24299 Jul 30, 2026
31 checks passed
@krishicks
krishicks deleted the hicks/push-xkzytkpxvnru branch July 30, 2026 20:41
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.

3 participants