connectrpc / connectrpc/connect-rust
Observability: per-RPC tracing spans and OpenTelemetry integration
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 recordsrpc.grpc.status_codeon completion - a client-side interceptor that propagates W3C
traceparent/tracestate(andgrpc-trace-binfor 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 aSpecstruct) so a user-written tower layer can at least get the labels right by reading extensions - a
TracingLayerthat wraps the existing HTTP-level path in a span namedpkg.Service/Methodrather thanPOST /pkg.Service/Method
Scope
- depends on typed interceptor surface (separate issue)
connectrpc-otelcrate orotelfeature, server + client interceptors- example showing OTLP export end to end
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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