11package main
22
33import (
4+ "bytes"
45 "cmp"
56 "encoding/json"
67 "io"
@@ -13,6 +14,8 @@ import (
1314 "time"
1415
1516 "github.com/mccutchen/go-httpbin/v2/httpbin"
17+ io_prometheus_client "github.com/prometheus/client_model/go"
18+ "github.com/prometheus/common/expfmt"
1619 "github.com/stretchr/testify/require"
1720)
1821
@@ -35,8 +38,8 @@ func TestIntegration(t *testing.T) {
3538 // Create a directory for the access logs to be written to.
3639 accessLogsDir := cwd + "/access_logs"
3740 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 ))
4043
4144 cmd := exec .Command (
4245 "docker" ,
@@ -328,4 +331,77 @@ func TestIntegration(t *testing.T) {
328331 })
329332 }
330333 })
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+ })
331407}
0 commit comments