@@ -17,6 +17,8 @@ package test
17
17
import (
18
18
"bytes"
19
19
"context"
20
+ "go.opentelemetry.io/otel/sdk/metric"
21
+ semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
20
22
"io"
21
23
"net"
22
24
"net/http"
@@ -27,15 +29,12 @@ import (
27
29
"strings"
28
30
"testing"
29
31
32
+ "github.com/stretchr/testify/assert"
33
+ "github.com/stretchr/testify/require"
30
34
"go.opentelemetry.io/otel/attribute"
31
35
"go.opentelemetry.io/otel/sdk/instrumentation"
32
- "go.opentelemetry.io/otel/sdk/metric"
33
36
"go.opentelemetry.io/otel/sdk/metric/metricdata"
34
37
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
35
- semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
36
-
37
- "github.com/stretchr/testify/assert"
38
- "github.com/stretchr/testify/require"
39
38
40
39
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
41
40
"go.opentelemetry.io/otel/codes"
@@ -250,64 +249,139 @@ func TestWithHTTPTrace(t *testing.T) {
250
249
}
251
250
252
251
func TestTransportMetrics (t * testing.T ) {
253
- reader := metric .NewManualReader ()
254
- meterProvider := metric .NewMeterProvider (metric .WithReader (reader ))
255
252
253
+ requestBody := []byte ("john" )
256
254
responseBody := []byte ("Hello, world!" )
257
255
258
- ts := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
259
- w .WriteHeader (http .StatusOK )
260
- if _ , err := w .Write (responseBody ); err != nil {
256
+ t .Run ("make http request and read entire response at once" , func (t * testing.T ) {
257
+ reader := metric .NewManualReader ()
258
+ meterProvider := metric .NewMeterProvider (metric .WithReader (reader ))
259
+
260
+ ts := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
261
+ w .WriteHeader (http .StatusOK )
262
+ if _ , err := w .Write (responseBody ); err != nil {
263
+ t .Fatal (err )
264
+ }
265
+ }))
266
+ defer ts .Close ()
267
+
268
+ r , err := http .NewRequest (http .MethodGet , ts .URL , bytes .NewReader (requestBody ))
269
+ if err != nil {
261
270
t .Fatal (err )
262
271
}
263
- }))
264
- defer ts .Close ()
265
272
266
- requestBody := []byte ("john" )
267
- r , err := http .NewRequest (http .MethodGet , ts .URL , bytes .NewReader (requestBody ))
268
- if err != nil {
269
- t .Fatal (err )
270
- }
273
+ tr := otelhttp .NewTransport (
274
+ http .DefaultTransport ,
275
+ otelhttp .WithMeterProvider (meterProvider ),
276
+ )
271
277
272
- tr := otelhttp .NewTransport (
273
- http .DefaultTransport ,
274
- otelhttp .WithMeterProvider (meterProvider ),
275
- )
278
+ c := http.Client {Transport : tr }
279
+ res , err := c .Do (r )
280
+ if err != nil {
281
+ t .Fatal (err )
282
+ }
276
283
277
- c := http.Client {Transport : tr }
278
- res , err := c .Do (r )
279
- if err != nil {
280
- t .Fatal (err )
281
- }
284
+ // Must read the body or else we won't get response metrics
285
+ bodyBytes , err := io .ReadAll (res .Body )
286
+ if err != nil {
287
+ t .Fatal (err )
288
+ }
289
+ require .Len (t , bodyBytes , 13 )
290
+ require .NoError (t , res .Body .Close ())
282
291
283
- // Must read the body or else we won't get response metrics
284
- bodyBytes , err := io .ReadAll (res .Body )
285
- if err != nil {
286
- t .Fatal (err )
287
- }
288
- require .Len (t , bodyBytes , 13 )
289
- require .NoError (t , res .Body .Close ())
292
+ host , portStr , _ := net .SplitHostPort (r .Host )
293
+ if host == "" {
294
+ host = "127.0.0.1"
295
+ }
296
+ port , err := strconv .Atoi (portStr )
297
+ if err != nil {
298
+ port = 0
299
+ }
290
300
291
- host , portStr , _ := net .SplitHostPort (r .Host )
292
- if host == "" {
293
- host = "127.0.0.1"
294
- }
295
- port , err := strconv .Atoi (portStr )
296
- if err != nil {
297
- port = 0
298
- }
301
+ rm := metricdata.ResourceMetrics {}
302
+ err = reader .Collect (context .Background (), & rm )
303
+ require .NoError (t , err )
304
+ require .Len (t , rm .ScopeMetrics , 1 )
305
+ attrs := attribute .NewSet (
306
+ semconv .NetPeerName (host ),
307
+ semconv .NetPeerPort (port ),
308
+ semconv .HTTPMethod ("GET" ),
309
+ semconv .HTTPStatusCode (200 ),
310
+ )
311
+ assertClientScopeMetrics (t , rm .ScopeMetrics [0 ], attrs )
312
+ })
313
+
314
+ t .Run ("make http request and buffer response" , func (t * testing.T ) {
315
+ reader := metric .NewManualReader ()
316
+ meterProvider := metric .NewMeterProvider (metric .WithReader (reader ))
317
+
318
+ ts := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
319
+ w .WriteHeader (http .StatusOK )
320
+ if _ , err := w .Write (responseBody ); err != nil {
321
+ t .Fatal (err )
322
+ }
323
+ }))
324
+ defer ts .Close ()
325
+
326
+ r , err := http .NewRequest (http .MethodGet , ts .URL , bytes .NewReader (requestBody ))
327
+ if err != nil {
328
+ t .Fatal (err )
329
+ }
330
+
331
+ tr := otelhttp .NewTransport (
332
+ http .DefaultTransport ,
333
+ otelhttp .WithMeterProvider (meterProvider ),
334
+ )
335
+
336
+ c := http.Client {Transport : tr }
337
+ res , err := c .Do (r )
338
+ if err != nil {
339
+ t .Fatal (err )
340
+ }
341
+
342
+ // Must read the body or else we won't get response metrics
343
+ var buf []byte
344
+ smallBuf := make ([]byte , 10 )
345
+
346
+ // Read first 10 bytes
347
+ bc , err := res .Body .Read (smallBuf )
348
+ if err != nil {
349
+ t .Fatal (err )
350
+ }
351
+ require .Equal (t , 10 , bc )
352
+ buf = append (buf , smallBuf ... )
353
+
354
+ // reset byte array
355
+ // Read last 3 bytes
356
+ bc , err = res .Body .Read (smallBuf )
357
+ require .Equal (t , io .EOF , err )
358
+ require .Equal (t , 3 , bc )
359
+ buf = append (buf , smallBuf [:bc ]... )
360
+
361
+ require .NoError (t , res .Body .Close ())
362
+
363
+ host , portStr , _ := net .SplitHostPort (r .Host )
364
+ if host == "" {
365
+ host = "127.0.0.1"
366
+ }
367
+ port , err := strconv .Atoi (portStr )
368
+ if err != nil {
369
+ port = 0
370
+ }
371
+
372
+ rm := metricdata.ResourceMetrics {}
373
+ err = reader .Collect (context .Background (), & rm )
374
+ require .NoError (t , err )
375
+ require .Len (t , rm .ScopeMetrics , 1 )
376
+ attrs := attribute .NewSet (
377
+ semconv .NetPeerName (host ),
378
+ semconv .NetPeerPort (port ),
379
+ semconv .HTTPMethod ("GET" ),
380
+ semconv .HTTPStatusCode (200 ),
381
+ )
382
+ assertClientScopeMetrics (t , rm .ScopeMetrics [0 ], attrs )
383
+ })
299
384
300
- rm := metricdata.ResourceMetrics {}
301
- err = reader .Collect (context .Background (), & rm )
302
- require .NoError (t , err )
303
- require .Len (t , rm .ScopeMetrics , 1 )
304
- attrs := attribute .NewSet (
305
- semconv .NetPeerName (host ),
306
- semconv .NetPeerPort (port ),
307
- semconv .HTTPMethod ("GET" ),
308
- semconv .HTTPStatusCode (200 ),
309
- )
310
- assertClientScopeMetrics (t , rm .ScopeMetrics [0 ], attrs )
311
385
}
312
386
313
387
func assertClientScopeMetrics (t * testing.T , sm metricdata.ScopeMetrics , attrs attribute.Set ) {
0 commit comments