Skip to content

Commit d642159

Browse files
authored
contrib/envoyproxy: fix context propagation from envoy tracing (#3144)
1 parent 5996821 commit d642159

File tree

2 files changed

+69
-6
lines changed

2 files changed

+69
-6
lines changed

contrib/envoyproxy/go-control-plane/envoy_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
2424
"github.com/stretchr/testify/require"
2525
"google.golang.org/grpc"
26+
"google.golang.org/grpc/metadata"
2627
)
2728

2829
func TestAppSec(t *testing.T) {
@@ -273,6 +274,45 @@ func TestGeneratedSpan(t *testing.T) {
273274
require.Equal(t, "server", span.Tag("span.kind"))
274275
require.Equal(t, "Mistake Not...", span.Tag("http.useragent"))
275276
})
277+
278+
t.Run("span-with-injected-context", func(t *testing.T) {
279+
client, mt, cleanup := setup()
280+
defer cleanup()
281+
282+
ctx := context.Background()
283+
284+
// add metadata to the context
285+
ctx = metadata.AppendToOutgoingContext(ctx,
286+
"x-datadog-trace-id", "12345",
287+
"x-datadog-parent-id", "67890",
288+
)
289+
290+
stream, err := client.Process(ctx)
291+
require.NoError(t, err)
292+
293+
end2EndStreamRequest(t, stream, "/../../../resource-span/.?id=test", "GET", map[string]string{"user-agent": "Mistake Not...", "test-key": "test-value"}, map[string]string{"response-test-key": "response-test-value"}, false)
294+
295+
err = stream.CloseSend()
296+
require.NoError(t, err)
297+
stream.Recv() // to flush the spans
298+
299+
finished := mt.FinishedSpans()
300+
require.Len(t, finished, 1)
301+
302+
// Check for tags
303+
span := finished[0]
304+
require.Equal(t, "http.request", span.OperationName())
305+
require.Equal(t, "https://datadoghq.com/../../../resource-span/.?id=test", span.Tag("http.url"))
306+
require.Equal(t, "GET", span.Tag("http.method"))
307+
require.Equal(t, "datadoghq.com", span.Tag("http.host"))
308+
require.Equal(t, "GET /resource-span", span.Tag("resource.name"))
309+
require.Equal(t, "server", span.Tag("span.kind"))
310+
require.Equal(t, "Mistake Not...", span.Tag("http.useragent"))
311+
312+
// Check for trace context
313+
require.Equal(t, uint64(12345), span.Context().TraceID())
314+
require.Equal(t, uint64(67890), span.ParentID())
315+
})
276316
}
277317

278318
func TestXForwardedForHeaderClientIp(t *testing.T) {

contrib/envoyproxy/go-control-plane/fakehttp.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,28 @@ func splitPseudoHeaders(receivedHeaders []*corev3.HeaderValue) (headers map[stri
7676
return headers, pseudoHeaders
7777
}
7878

79+
// mergeMetadataHeaders merges the metadata headers of the grpc connection into the http headers of the request
80+
// - Skip pseudo headers and headers that are already set
81+
// - Set headers keys to be canonical
82+
func mergeMetadataHeaders(md metadata.MD, headers http.Header) {
83+
for k, v := range md {
84+
if strings.HasPrefix(k, ":") {
85+
continue
86+
}
87+
88+
// Skip the content-type header of the grpc request
89+
// Note: all envoy set headers are lower-case
90+
if k == "content-type" {
91+
continue
92+
}
93+
94+
k = http.CanonicalHeaderKey(k)
95+
if _, ok := headers[k]; !ok {
96+
headers[k] = v
97+
}
98+
}
99+
}
100+
79101
func createFakeResponseWriter(w http.ResponseWriter, res *extproc.ProcessingRequest_ResponseHeaders) error {
80102
headers, pseudoHeaders := splitPseudoHeaders(res.ResponseHeaders.GetHeaders().GetHeaders())
81103

@@ -103,6 +125,13 @@ func newRequest(ctx context.Context, req *extproc.ProcessingRequest_RequestHeade
103125
return nil, err
104126
}
105127

128+
var remoteAddr string
129+
md, ok := metadata.FromIncomingContext(ctx)
130+
if ok {
131+
mergeMetadataHeaders(md, headers)
132+
remoteAddr = getRemoteAddr(md)
133+
}
134+
106135
parsedURL, err := url.Parse(fmt.Sprintf("%s://%s%s", pseudoHeaders[":scheme"], pseudoHeaders[":authority"], pseudoHeaders[":path"]))
107136
if err != nil {
108137
return nil, fmt.Errorf(
@@ -113,12 +142,6 @@ func newRequest(ctx context.Context, req *extproc.ProcessingRequest_RequestHeade
113142
err)
114143
}
115144

116-
var remoteAddr string
117-
md, ok := metadata.FromIncomingContext(ctx)
118-
if ok {
119-
remoteAddr = getRemoteAddr(md)
120-
}
121-
122145
var tlsState *tls.ConnectionState
123146
if pseudoHeaders[":scheme"] == "https" {
124147
tlsState = &tls.ConnectionState{}

0 commit comments

Comments
 (0)