@@ -2,10 +2,14 @@ package metrics
22
33import (
44 "net/http"
5+ "net/http/httptest"
56 "net/url"
67
78 . "github.com/onsi/ginkgo/v2"
89 . "github.com/onsi/gomega"
10+ "github.com/prometheus/client_golang/prometheus"
11+ "github.com/prometheus/client_golang/prometheus/testutil"
12+ dto "github.com/prometheus/client_model/go"
913)
1014
1115var _ = Describe ("Metrics" , func () {
@@ -22,4 +26,148 @@ var _ = Describe("Metrics", func() {
2226 Entry ("get load-balancers" , "GET" , "/v2/projects/6-a-4-8-c/regions/eu01/load-balancers" , "get_load-balancers" ),
2327 Entry ("get load-balancers instance" , "GET" , "/v2/projects/6-a-4-8-c/regions/eu01/load-balancers/id" , "get_load-balancers_instance" ),
2428 )
29+
30+ Describe ("InstrumentedRoundTripper" , func () {
31+ It ("increments HTTPRequestCount for responses" , func () {
32+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
33+ w .WriteHeader (http .StatusOK )
34+ }))
35+ defer server .Close ()
36+
37+ labels := prometheus.Labels {
38+ apiLabel : "test" ,
39+ methodLabel : "GET" ,
40+ operationLabel : "get_request-count-test" ,
41+ codeLabel : "200" ,
42+ }
43+ before := testutil .ToFloat64 (HTTPRequestCount .With (labels ))
44+
45+ client := NewInstrumentedHTTPClient ("test" )
46+
47+ response , err := client .Get (server .URL + "/request-count-test" )
48+ Expect (err ).NotTo (HaveOccurred ())
49+ defer response .Body .Close ()
50+
51+ after := testutil .ToFloat64 (HTTPRequestCount .With (labels ))
52+ Expect (after - before ).To (Equal (float64 (1 )))
53+ })
54+
55+ It ("records HTTPRequestDurationHistogram observations for responses" , func () {
56+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
57+ w .WriteHeader (http .StatusOK )
58+ }))
59+ defer server .Close ()
60+
61+ labels := prometheus.Labels {
62+ apiLabel : "test" ,
63+ methodLabel : "GET" ,
64+ operationLabel : "get_request-duration-test" ,
65+ codeLabel : "200" ,
66+ }
67+ before := histogramSampleCount (HTTPRequestDurationHistogram .With (labels ))
68+
69+ client := NewInstrumentedHTTPClient ("test" )
70+
71+ response , err := client .Get (server .URL + "/request-duration-test" )
72+ Expect (err ).NotTo (HaveOccurred ())
73+ defer response .Body .Close ()
74+
75+ after := histogramSampleCount (HTTPRequestDurationHistogram .With (labels ))
76+ Expect (after - before ).To (Equal (uint64 (1 )))
77+ })
78+
79+ It ("increments HTTPErrorCount for error responses (400, 404, 500)" , func () {
80+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
81+ if r .Method == http .MethodPost {
82+ w .WriteHeader (http .StatusInternalServerError )
83+ return
84+ }
85+ if r .URL .Path == "/404" {
86+ w .WriteHeader (http .StatusNotFound )
87+ return
88+ }
89+ w .WriteHeader (http .StatusBadRequest )
90+ }))
91+ defer server .Close ()
92+
93+ labels400 := prometheus.Labels {
94+ apiLabel : "test" ,
95+ methodLabel : http .MethodGet ,
96+ operationLabel : "get_" ,
97+ codeLabel : "400" ,
98+ }
99+ labels404 := prometheus.Labels {
100+ apiLabel : "test" ,
101+ methodLabel : http .MethodGet ,
102+ operationLabel : "get_404" ,
103+ codeLabel : "404" ,
104+ }
105+ labels500 := prometheus.Labels {
106+ apiLabel : "test" ,
107+ methodLabel : http .MethodPost ,
108+ operationLabel : "post_" ,
109+ codeLabel : "500" ,
110+ }
111+ before400 := testutil .ToFloat64 (HTTPErrorCount .With (labels400 ))
112+ before404 := testutil .ToFloat64 (HTTPErrorCount .With (labels404 ))
113+ before500 := testutil .ToFloat64 (HTTPErrorCount .With (labels500 ))
114+
115+ client := NewInstrumentedHTTPClient ("test" )
116+
117+ response1 , err := client .Get (server .URL )
118+ Expect (err ).NotTo (HaveOccurred ())
119+ defer response1 .Body .Close ()
120+
121+ response2 , err := client .Get (server .URL + "/404" )
122+ Expect (err ).NotTo (HaveOccurred ())
123+ defer response2 .Body .Close ()
124+
125+ response3 , err := client .Post (server .URL , "application/json" , nil )
126+ Expect (err ).NotTo (HaveOccurred ())
127+ defer response3 .Body .Close ()
128+
129+ after400 := testutil .ToFloat64 (HTTPErrorCount .With (labels400 ))
130+ after404 := testutil .ToFloat64 (HTTPErrorCount .With (labels404 ))
131+ after500 := testutil .ToFloat64 (HTTPErrorCount .With (labels500 ))
132+
133+ Expect (after400 - before400 ).To (Equal (float64 (1 )))
134+ Expect (after404 - before404 ).To (Equal (float64 (1 )))
135+ Expect (after500 - before500 ).To (Equal (float64 (1 )))
136+ Expect ((after400 - before400 ) + (after404 - before404 ) + (after500 - before500 )).To (Equal (float64 (3 )))
137+ })
138+
139+ It ("does not increment HTTPErrorCount for successful responses" , func () {
140+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
141+ w .WriteHeader (http .StatusOK )
142+ }))
143+ defer server .Close ()
144+
145+ labels := prometheus.Labels {
146+ apiLabel : "test" ,
147+ methodLabel : http .MethodGet ,
148+ operationLabel : "get_" ,
149+ codeLabel : "200" ,
150+ }
151+ before := testutil .ToFloat64 (HTTPErrorCount .With (labels ))
152+
153+ client := NewInstrumentedHTTPClient ("test" )
154+
155+ response , err := client .Get (server .URL )
156+ Expect (err ).NotTo (HaveOccurred ())
157+ defer response .Body .Close ()
158+
159+ after := testutil .ToFloat64 (HTTPErrorCount .With (labels ))
160+ Expect (after - before ).To (Equal (float64 (0 )))
161+ })
162+ })
25163})
164+
165+ func histogramSampleCount (observer prometheus.Observer ) uint64 {
166+ metric , ok := observer .(prometheus.Metric )
167+ Expect (ok ).To (BeTrue ())
168+
169+ dtoMetric := & dto.Metric {}
170+ Expect (metric .Write (dtoMetric )).To (Succeed ())
171+
172+ return dtoMetric .GetHistogram ().GetSampleCount ()
173+ }
0 commit comments