@@ -17,11 +17,14 @@ limitations under the License.
1717package handlers
1818
1919import (
20+ "context"
2021 "strconv"
2122 "time"
2223
2324 configPb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
2425 extProcPb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
26+ "go.opentelemetry.io/otel"
27+ "go.opentelemetry.io/otel/propagation"
2528 "google.golang.org/protobuf/types/known/structpb"
2629
2730 "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metadata"
@@ -51,7 +54,7 @@ func (s *StreamingServer) HandleRequestHeaders(reqCtx *RequestContext, req *extP
5154 }
5255 reqCtx .TargetEndpoint = pod .GetIPAddress () + ":" + pod .GetPort ()
5356 reqCtx .RequestSize = 0
54- reqCtx .reqHeaderResp = s .generateRequestHeaderResponse (reqCtx )
57+ reqCtx .reqHeaderResp = s .generateRequestHeaderResponse (ctx , reqCtx )
5558 return nil
5659 }
5760
@@ -90,7 +93,7 @@ func (s *StreamingServer) generateRequestBodyResponses(requestBodyBytes []byte)
9093 return responses
9194}
9295
93- func (s * StreamingServer ) generateRequestHeaderResponse (reqCtx * RequestContext ) * extProcPb.ProcessingResponse {
96+ func (s * StreamingServer ) generateRequestHeaderResponse (ctx context. Context , reqCtx * RequestContext ) * extProcPb.ProcessingResponse {
9497 // The Endpoint Picker supports two approaches to communicating the target endpoint, as a request header
9598 // and as an unstructure ext-proc response metadata key/value pair. This enables different integration
9699 // options for gateway providers.
@@ -100,7 +103,7 @@ func (s *StreamingServer) generateRequestHeaderResponse(reqCtx *RequestContext)
100103 Response : & extProcPb.CommonResponse {
101104 ClearRouteCache : true ,
102105 HeaderMutation : & extProcPb.HeaderMutation {
103- SetHeaders : s .generateHeaders (reqCtx ),
106+ SetHeaders : s .generateHeaders (ctx , reqCtx ),
104107 },
105108 },
106109 },
@@ -109,7 +112,7 @@ func (s *StreamingServer) generateRequestHeaderResponse(reqCtx *RequestContext)
109112 }
110113}
111114
112- func (s * StreamingServer ) generateHeaders (reqCtx * RequestContext ) []* configPb.HeaderValueOption {
115+ func (s * StreamingServer ) generateHeaders (ctx context. Context , reqCtx * RequestContext ) []* configPb.HeaderValueOption {
113116 // can likely refactor these two bespoke headers to be updated in PostDispatch, to centralize logic.
114117 headers := []* configPb.HeaderValueOption {
115118 {
@@ -130,6 +133,19 @@ func (s *StreamingServer) generateHeaders(reqCtx *RequestContext) []*configPb.He
130133 })
131134 }
132135
136+ // Inject trace context headers for propagation to downstream services
137+ traceHeaders := make (map [string ]string )
138+ propagator := otel .GetTextMapPropagator ()
139+ propagator .Inject (ctx , propagation .MapCarrier (traceHeaders ))
140+ for key , value := range traceHeaders {
141+ headers = append (headers , & configPb.HeaderValueOption {
142+ Header : & configPb.HeaderValue {
143+ Key : key ,
144+ RawValue : []byte (value ),
145+ },
146+ })
147+ }
148+
133149 // Include any non-system-owned headers.
134150 for key , value := range reqCtx .Request .Headers {
135151 if request .IsSystemOwnedHeader (key ) {
0 commit comments