1
1
package main
2
2
3
3
import (
4
+ "bytes"
4
5
"cmp"
5
6
"encoding/json"
6
7
"io"
@@ -13,6 +14,8 @@ import (
13
14
"time"
14
15
15
16
"github.com/mccutchen/go-httpbin/v2/httpbin"
17
+ io_prometheus_client "github.com/prometheus/client_model/go"
18
+ "github.com/prometheus/common/expfmt"
16
19
"github.com/stretchr/testify/require"
17
20
)
18
21
@@ -35,8 +38,8 @@ func TestIntegration(t *testing.T) {
35
38
// Create a directory for the access logs to be written to.
36
39
accessLogsDir := cwd + "/access_logs"
37
40
require .NoError (t , os .RemoveAll (accessLogsDir ))
38
- require .NoError (t , os .Mkdir (accessLogsDir , 0700 ))
39
- require .NoError (t , os .Chmod (accessLogsDir , 0777 ))
41
+ require .NoError (t , os .Mkdir (accessLogsDir , 0o700 ))
42
+ require .NoError (t , os .Chmod (accessLogsDir , 0o777 ))
40
43
41
44
cmd := exec .Command (
42
45
"docker" ,
@@ -328,4 +331,77 @@ func TestIntegration(t *testing.T) {
328
331
})
329
332
}
330
333
})
334
+
335
+ t .Run ("http_metrics" , func (t * testing.T ) {
336
+ // Send test request
337
+ require .Eventually (t , func () bool {
338
+ req , err := http .NewRequest ("GET" , "http://localhost:1062/uuid" , nil )
339
+ require .NoError (t , err )
340
+
341
+ resp , err := http .DefaultClient .Do (req )
342
+ if err != nil {
343
+ t .Logf ("Envoy not ready yet: %v" , err )
344
+ return false
345
+ }
346
+ defer func () {
347
+ require .NoError (t , resp .Body .Close ())
348
+ }()
349
+ body , err := io .ReadAll (resp .Body )
350
+ if err != nil {
351
+ t .Logf ("Envoy not ready yet: %v" , err )
352
+ return false
353
+ }
354
+ t .Logf ("response: status=%d body=%s" , resp .StatusCode , string (body ))
355
+ return resp .StatusCode == 200
356
+ }, 30 * time .Second , 200 * time .Millisecond )
357
+
358
+ // Check the metrics endpoint
359
+ lastStatsOutput := ""
360
+ t .Cleanup (func () {
361
+ t .Logf ("last stats output:\n %s" , lastStatsOutput )
362
+ })
363
+ require .Eventually (t , func () bool {
364
+ req , err := http .NewRequest ("GET" , "http://localhost:9901/stats/prometheus" , nil )
365
+ require .NoError (t , err )
366
+
367
+ resp , err := http .DefaultClient .Do (req )
368
+ require .NoError (t , err )
369
+ defer func () {
370
+ require .NoError (t , resp .Body .Close ())
371
+ }()
372
+
373
+ // Check that the route_latency_ms metric is present
374
+ body , err := io .ReadAll (resp .Body )
375
+ require .NoError (t , err )
376
+ lastStatsOutput = string (body )
377
+
378
+ decoder := expfmt .NewDecoder (bytes .NewReader (body ), expfmt .NewFormat (expfmt .TypeTextPlain ))
379
+ for {
380
+ var metricFamily io_prometheus_client.MetricFamily
381
+ err := decoder .Decode (& metricFamily )
382
+ if err == io .EOF {
383
+ break
384
+ }
385
+ require .NoError (t , err )
386
+
387
+ if metricFamily .GetName () != "route_latency_ms" {
388
+ continue
389
+ }
390
+ for _ , metric := range metricFamily .GetMetric () {
391
+ hist := metric .GetHistogram ()
392
+ require .NotNil (t , hist )
393
+ labels := make (map [string ]string )
394
+ for _ , label := range metric .GetLabel () {
395
+ labels [label .GetName ()] = label .GetValue ()
396
+ }
397
+ require .Equal (t , map [string ]string {"version" : "v1.0.0" , "route_name" : "catch_all" }, labels )
398
+ if hist .GetSampleCount () > 0 {
399
+ return true
400
+ }
401
+ }
402
+ }
403
+ t .Logf ("route_latency_ms metric not found or no samples yet" )
404
+ return false
405
+ }, 5 * time .Second , 200 * time .Millisecond )
406
+ })
331
407
}
0 commit comments