@@ -26,6 +26,7 @@ import (
2626 basepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
2727 extProcPb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
2828 "github.com/google/go-cmp/cmp"
29+ "go.opentelemetry.io/otel/trace"
2930 "google.golang.org/protobuf/testing/protocmp"
3031 metricsutils "k8s.io/component-base/metrics/testutil"
3132 crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
@@ -170,6 +171,85 @@ func TestHandleRequestHeaders(t *testing.T) {
170171 }
171172}
172173
174+ func TestHandleRequestHeaders_InjectsTraceContext (t * testing.T ) {
175+ withTraceContextPropagator (t )
176+
177+ traceID , err := trace .TraceIDFromHex (testTraceID )
178+ if err != nil {
179+ t .Fatalf ("failed to parse trace ID: %v" , err )
180+ }
181+ spanID , err := trace .SpanIDFromHex (testSpanID )
182+ if err != nil {
183+ t .Fatalf ("failed to parse span ID: %v" , err )
184+ }
185+ ctx := trace .ContextWithSpanContext (context .Background (), trace .NewSpanContext (trace.SpanContextConfig {
186+ TraceID : traceID ,
187+ SpanID : spanID ,
188+ TraceFlags : trace .FlagsSampled ,
189+ }))
190+
191+ wantTraceparent := "00-" + testTraceID + "-" + testSpanID + "-01"
192+
193+ t .Run ("records traceparent as a header mutation" , func (t * testing.T ) {
194+ server := newServerForTest (newTestProfiles ())
195+ reqCtx := & RequestContext {Request : requesthandling .NewInferenceRequest ()}
196+
197+ resp := server .HandleRequestHeaders (ctx , reqCtx , & extProcPb.HttpHeaders {
198+ Headers : & basepb.HeaderMap {Headers : []* basepb.HeaderValue {}},
199+ })
200+ if resp != nil {
201+ t .Fatalf ("expected deferred response, got %v" , resp )
202+ }
203+ if got := reqCtx .Request .MutatedHeaders ()["traceparent" ]; got != wantTraceparent {
204+ t .Errorf ("mutated traceparent = %q, want %q" , got , wantTraceparent )
205+ }
206+ })
207+
208+ t .Run ("end of stream response carries the traceparent mutation" , func (t * testing.T ) {
209+ server := newServerForTest (newTestProfiles ())
210+ reqCtx := & RequestContext {Request : requesthandling .NewInferenceRequest ()}
211+
212+ resp := server .HandleRequestHeaders (ctx , reqCtx , & extProcPb.HttpHeaders {
213+ Headers : & basepb.HeaderMap {Headers : []* basepb.HeaderValue {}},
214+ EndOfStream : true ,
215+ })
216+ if len (resp ) != 1 {
217+ t .Fatalf ("expected a single response, got %d" , len (resp ))
218+ }
219+ mutation := resp [0 ].GetRequestHeaders ().GetResponse ().GetHeaderMutation ()
220+ if mutation == nil {
221+ t .Fatal ("expected a header mutation in the end-of-stream response" )
222+ }
223+ var got string
224+ for _ , h := range mutation .GetSetHeaders () {
225+ if h .GetHeader ().GetKey () == "traceparent" {
226+ got = string (h .GetHeader ().GetRawValue ())
227+ }
228+ }
229+ if got != wantTraceparent {
230+ t .Errorf ("traceparent in header mutation = %q, want %q" , got , wantTraceparent )
231+ }
232+ })
233+
234+ t .Run ("upstream traceparent matching current context is not re-set" , func (t * testing.T ) {
235+ server := newServerForTest (newTestProfiles ())
236+ reqCtx := & RequestContext {Request : requesthandling .NewInferenceRequest ()}
237+
238+ resp := server .HandleRequestHeaders (ctx , reqCtx , & extProcPb.HttpHeaders {
239+ Headers : & basepb.HeaderMap {Headers : []* basepb.HeaderValue {
240+ {Key : "traceparent" , RawValue : []byte (wantTraceparent )},
241+ }},
242+ EndOfStream : true ,
243+ })
244+ if len (resp ) != 1 {
245+ t .Fatalf ("expected a single response, got %d" , len (resp ))
246+ }
247+ if mutation := resp [0 ].GetRequestHeaders ().GetResponse ().GetHeaderMutation (); mutation != nil {
248+ t .Errorf ("expected no header mutation, got %v" , mutation )
249+ }
250+ })
251+ }
252+
173253// === Request Body Tests (built-in plugins) ===
174254
175255func TestHandleRequestBody_BuiltInPlugins (t * testing.T ) {
0 commit comments