connectrpc / connectrpc/connect-rust

Observability: per-RPC tracing spans and OpenTelemetry integration

Open
#87 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
509
Forks
66
Avg merge
2d 8h
Merged PRs (30d)
10

Description

There is currently no per-RPC observability hook. The runtime emits tracing events at debug/trace level for connection state and envelope decoding, but no span scoped to an individual RPC. Users who want a span carrying rpc.system, rpc.service, rpc.method, and rpc.grpc.status_code (the OpenTelemetry RPC semantic conventions) have nowhere to put it.

The recommended middleware pattern (tower_http::trace::TraceLayer::new_for_http() from the middleware example) produces HTTP spans (POST /pkg.Service/Method 200), not RPC spans. The HTTP layer doesn't know the RPC kind, can't see the Connect/gRPC error code (which is in the trailer or JSON body, not the HTTP status for most codes), and doesn't compose with downstream services that propagate W3C trace context through metadata.

For comparison: connect-go ships connectrpc.com/otelconnect (an Interceptor that creates spans and metrics per the OTel RPC conventions and propagates trace context); tonic users reach for tonic-tracing-opentelemetry's OtelGrpcLayer. Both depend on having a typed RPC-level interception point.

Proposed direction

Once a typed RPC-level interceptor surface exists (tracked separately), ship a connectrpc-otel companion crate (or a feature-gated module) providing:

  • a server-side interceptor that opens a span per RPC with rpc.system = "connect_rpc" (or "grpc"/"grpc_web" depending on the negotiated protocol), rpc.service, rpc.method, and records rpc.grpc.status_code on completion
  • a client-side interceptor that propagates W3C traceparent/tracestate (and grpc-trace-bin for gRPC peers) via request headers and opens a client span
  • optional metrics (request count, duration histogram, message size histogram) keyed by service/method/code

Even before the interceptor work lands, two cheap improvements are possible:

  • expose service name, method name, and negotiated protocol on RequestContext (or a Spec struct) so a user-written tower layer can at least get the labels right by reading extensions
  • a TracingLayer that wraps the existing HTTP-level path in a span named pkg.Service/Method rather than POST /pkg.Service/Method

Scope

  • depends on typed interceptor surface (separate issue)
  • connectrpc-otel crate or otel feature, server + client interceptors
  • example showing OTLP export end to end

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the middleware example using tower_http::trace::TraceLayer and the existing HTTP-level tracing path. Review RequestContext or Spec for the proposed metadata and confirm how the separate typed interceptor surface affects the design. Done would require an agreed server/client interceptor scope, protocol-specific spans and propagation, metrics, and an end-to-end OTLP example.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design, observability
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.