Repository navigation
fix(trace): restore gRPC server spans and add HTTP server spans - #3450
Conversation
Security Checks — ✅ 8 passing✅
|
| Status | Policy | Messages |
|---|---|---|
| ✅ Passed | secrets-detection |
- |
✅ sast-scan
| Status | Policy | Messages |
|---|---|---|
| ✅ Passed | owasp-top10-2025 |
- |
| ✅ Passed | sast |
- |
| ✅ Passed | cwe-top25 |
- |
| ✅ Passed | cwe-top26-40-cusp |
- |
PR info
| Status | Policy | Messages |
|---|---|---|
| ✅ Passed | pr-min-approvals |
- |
| ✅ Passed | pr-description-required |
- |
| ✅ Passed | pr-user-story-linked |
- |
⏭️ 3 scans not applied
| Scan | Reason |
|---|---|
vulnerability-scan |
ran, but its output is not attested yet |
github-actions-scan |
no workflow files changed |
iac-scan |
no IaC files changed |
Powered by Chainloop and Chainloop Trace
There was a problem hiding this comment.
All reported issues were addressed across 3 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
5ea7ff9 to
d75c189
Compare
|
Addressed the review feedback in d75c189: P2 — gRPC test now exercises P2 — HTTP test now exercises the production middleware list: the chain construction was extracted into P3 — comment accuracy: the comment on 🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri |
d75c189 to
dd39bc7
Compare
kratos' grpc.Options assigns s.grpcOpts instead of appending, so the second grpc.Options(grpcLib.MaxRecvMsgSize(...)) call in NewGRPCServer silently wiped the otelgrpc stats handler whenever max_recv_msg_size was configured, dropping all gRPC server spans. Pass all raw grpc-go server options in a single grpc.Options call. Also add kratos tracing.Server() as the outermost middleware of the HTTP server so transcoded REST requests produce a transport-level server span instead of rooting traces at the first middleware span. Fixes chainloop-dev#3448 Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
dd39bc7 to
cc25bad
Compare
|
Assessment of the review round, plus a follow-up fix in cc25bad:
No false positives in this round; each finding pointed at a real weakness. 🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri |
Problem
With tracing enabled, traces rooted at middleware spans (
WithCurrentMembershipsMiddleware,WithCurrentAPITokenAndOrgMiddleware, ...) instead of transport-level server spans — for both gRPC and HTTP entrypoints. See #3448.Root causes
grpc.Optionsassignss.grpcOptsinstead of appending (kratos/v2@v2.9.2/transport/grpc/server.go:124).NewGRPCServerpassedgrpc.Options(grpcLib.StatsHandler(otelgrpc.NewServerHandler()))and then, whenmax_recv_msg_sizewas configured (Helmcontrolplane.grpcMaxRecvMsgSize), a secondgrpc.Options(grpcLib.MaxRecvMsgSize(...))— silently wiping the stats handler and with it all gRPC server spans.tracing.Server()middleware, nootelhttp), so transcoded REST requests started their trace at the first middleware span, with notraceparentextraction.Fix
grpc.go: pass all raw grpc-go server options in a singlegrpc.Options(...)call, with a comment explaining the assignment semantics so it doesn't regress.http.go: prepend kratostracing.Server()as the outermost HTTP middleware. It uses the global tracer provider and extracts W3C tracecontext by default. gRPC is untouched there (already covered by the stats handler, so no double spans).Verification
New regression tests in
app/controlplane/internal/server/otel_test.gospin up real Kratos servers with an in-memory exporter:TestGRPCServerSpanWithMaxRecvMsgSize— gRPC server spangrpc.health.v1.Health/Checkis produced withMaxRecvMsgSizeset. During development the split-grpc.Optionsvariant was confirmed to produce zero spans, reproducing the bug.TestHTTPServerSpanFromTracingMiddleware— HTTP request produces a server span named after the route (/ping).go build ./app/controlplane/... ./app/artifact-cas/...,go vet, andgo test ./app/controlplane/internal/server/all pass. artifact-cas checked: only onegrpc.Optionscall, unaffected.Fixes #3448
🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri