@@ -14,6 +14,7 @@ import (
14
14
"encoding/base64"
15
15
"encoding/json"
16
16
"fmt"
17
+ "io"
17
18
"net/http"
18
19
"os"
19
20
"reflect"
@@ -97,7 +98,14 @@ func (em *ExtensionManager) checkAgentRunning() {
97
98
// Tell the extension not to create an execution span if universal instrumentation is disabled
98
99
if ! em .isUniversalInstrumentation {
99
100
req , _ := http .NewRequest (http .MethodGet , em .helloRoute , nil )
100
- if response , err := em .httpClient .Do (req ); err == nil && response .StatusCode == 200 {
101
+ response , err := em .httpClient .Do (req )
102
+ if response != nil && response .Body != nil {
103
+ defer func () {
104
+ _ , _ = io .Copy (io .Discard , response .Body )
105
+ response .Body .Close ()
106
+ }()
107
+ }
108
+ if err == nil && response .StatusCode == 200 {
101
109
logger .Debug ("Hit the extension /hello route" )
102
110
} else {
103
111
logger .Debug ("Will use the API since the Serverless Agent was detected but the hello route was unreachable" )
@@ -111,7 +119,15 @@ func (em *ExtensionManager) SendStartInvocationRequest(ctx context.Context, even
111
119
body := bytes .NewBuffer (eventPayload )
112
120
req , _ := http .NewRequest (http .MethodPost , em .startInvocationUrl , body )
113
121
114
- if response , err := em .httpClient .Do (req ); err == nil && response .StatusCode == 200 {
122
+ response , err := em .httpClient .Do (req )
123
+ if response != nil && response .Body != nil {
124
+ defer func () {
125
+ _ , _ = io .Copy (io .Discard , response .Body )
126
+ response .Body .Close ()
127
+ }()
128
+ }
129
+ if err == nil && response .StatusCode == 200 {
130
+
115
131
// Propagate dd-trace context from the extension response if found in the response headers
116
132
traceId := response .Header .Get (string (DdTraceId ))
117
133
if traceId != "" {
@@ -172,11 +188,21 @@ func (em *ExtensionManager) SendEndInvocationRequest(ctx context.Context, functi
172
188
if priority , ok := spanContext .SamplingPriority (); ok {
173
189
req .Header .Set (string (DdSamplingPriority ), fmt .Sprint (priority ))
174
190
} else {
175
- logger .Error (fmt .Errorf ("could not get sampling priority from spanContext.SamplingPriority()" ))
191
+ if priority , ok := getSamplingPriority (functionExecutionSpan ); ok {
192
+ req .Header .Set (string (DdSamplingPriority ), fmt .Sprint (priority ))
193
+ } else {
194
+ logger .Error (fmt .Errorf ("could not get sampling priority from getSamplingPriority()" ))
195
+ }
176
196
}
177
197
}
178
198
179
199
resp , err := em .httpClient .Do (req )
200
+ if resp != nil && resp .Body != nil {
201
+ defer func () {
202
+ _ , _ = io .Copy (io .Discard , resp .Body )
203
+ resp .Body .Close ()
204
+ }()
205
+ }
180
206
if err != nil || resp .StatusCode != 200 {
181
207
logger .Error (fmt .Errorf ("could not send end invocation payload to the extension: %v" , err ))
182
208
}
@@ -225,7 +251,14 @@ func (em *ExtensionManager) IsExtensionRunning() bool {
225
251
226
252
func (em * ExtensionManager ) Flush () error {
227
253
req , _ := http .NewRequest (http .MethodGet , em .flushRoute , nil )
228
- if response , err := em .httpClient .Do (req ); err != nil {
254
+ response , err := em .httpClient .Do (req )
255
+ if response != nil && response .Body != nil {
256
+ defer func () {
257
+ _ , _ = io .Copy (io .Discard , response .Body )
258
+ response .Body .Close ()
259
+ }()
260
+ }
261
+ if err != nil {
229
262
err := fmt .Errorf ("was not able to reach the Agent to flush: %s" , err )
230
263
logger .Error (err )
231
264
return err
@@ -236,3 +269,40 @@ func (em *ExtensionManager) Flush() error {
236
269
}
237
270
return nil
238
271
}
272
+
273
+
274
+ // The SamplingPriority method is directly available in dd-trace-go <=v1.73.1 or dd-trace-go v2.
275
+ // But for dd-trace-go v1.74.x, reflection is needed to access the SamplingPriority method because
276
+ // the method hidden in the v2 SpanContextV2Adapter struct.
277
+ func getSamplingPriority (span ddtrace.Span ) (int , bool ) {
278
+ // Get the span context
279
+ ctx := span .Context ()
280
+
281
+ // Use reflection to access the underlying v2 SpanContext
282
+ ctxValue := reflect .ValueOf (ctx )
283
+ if ctxValue .Type ().String () != "internal.SpanContextV2Adapter" {
284
+ return 0 , false
285
+ }
286
+
287
+ // Get the Ctx field (the underlying v2.SpanContext)
288
+ ctxField := ctxValue .FieldByName ("Ctx" )
289
+ if ! ctxField .IsValid () {
290
+ return 0 , false
291
+ }
292
+
293
+ // Call SamplingPriority() on the underlying v2 SpanContext
294
+ method := ctxField .MethodByName ("SamplingPriority" )
295
+ if ! method .IsValid () {
296
+ return 0 , false
297
+ }
298
+
299
+ results := method .Call ([]reflect.Value {})
300
+ if len (results ) != 2 {
301
+ return 0 , false
302
+ }
303
+
304
+ priority := int (results [0 ].Int ())
305
+ ok := results [1 ].Bool ()
306
+ return priority , ok
307
+ }
308
+
0 commit comments