Skip to content

Commit

Permalink
http: add support for metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
nadiamoe committed Aug 2, 2023
1 parent 258f9ef commit 064a5a6
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
9 changes: 8 additions & 1 deletion pkg/agent/protocol/http/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type proxy struct {
config ProxyConfig
disruption Disruption
srv *http.Server
metrics protocol.MetricMap
}

// NewProxy return a new Proxy for HTTP requests
Expand Down Expand Up @@ -85,6 +86,7 @@ type httpHandler struct {
upstreamURL url.URL
disruption Disruption
client httpClient
metrics *protocol.MetricMap
}

// isExcluded checks whether a request should be proxied through without any kind of modification whatsoever.
Expand Down Expand Up @@ -145,7 +147,10 @@ func (h *httpHandler) fault(rw http.ResponseWriter, wait <-chan time.Time) {
}

func (h *httpHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
h.metrics.Inc(protocol.MetricRequests)

if h.isExcluded(req) {
h.metrics.Inc(protocol.MetricRequestsExcluded)
//nolint:contextcheck // Unclear which context the linter requires us to propagate here.
h.proxy(rw, req, time.After(0))
return
Expand All @@ -160,6 +165,7 @@ func (h *httpHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
responseTimer := time.After(delay)

if h.disruption.ErrorRate > 0 && rand.Float32() <= h.disruption.ErrorRate {
h.metrics.Inc(protocol.MetricRequestsFaulted)
h.fault(rw, responseTimer)
return
}
Expand All @@ -179,6 +185,7 @@ func (p *proxy) Start() error {
upstreamURL: *upstreamURL,
disruption: p.disruption,
client: http.DefaultClient,
metrics: &p.metrics,
}

p.srv = &http.Server{
Expand All @@ -203,7 +210,7 @@ func (p *proxy) Stop() error {

// Metrics returns runtime metrics for the proxy.
func (p *proxy) Metrics() map[string]uint {
return nil
return p.metrics.Map()
}

// Force stops the proxy without waiting for connections to drain
Expand Down
69 changes: 69 additions & 0 deletions pkg/agent/protocol/http/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/grafana/xk6-disruptor/pkg/agent/protocol"
)

// fakeHTTPClient mocks the execution of a request returning the predefines
Expand Down Expand Up @@ -415,3 +416,71 @@ func Test_ProxyHandler(t *testing.T) {
})
}
}

// TODO: This test covers metrics generated by the handler, but not the proxy. The reason for this is that the proxy is
// currently not easily testable, as it coupled with `http.ListenAndServe`.
func Test_Metrics(t *testing.T) {
t.Parallel()

for _, tc := range []struct {
name string
config Disruption
endpoints []string
expectedMetrics map[string]uint
}{
{
name: "no requests",
expectedMetrics: map[string]uint{},
},
{
name: "requests",
config: Disruption{
Excluded: []string{"/excluded"},
ErrorRate: 1.0,
ErrorCode: http.StatusTeapot,
},
endpoints: []string{"/included", "/excluded"},
expectedMetrics: map[string]uint{
protocol.MetricRequests: 2,
protocol.MetricRequestsExcluded: 1,
protocol.MetricRequestsFaulted: 1,
},
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

upstreamServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
}))

upstreamURL, err := url.Parse(upstreamServer.URL)
if err != nil {
t.Fatalf("error parsing httptest url")
}

metrics := protocol.MetricMap{}

handler := &httpHandler{
upstreamURL: *upstreamURL,
disruption: tc.config,
client: http.DefaultClient,
metrics: &metrics,
}

proxyServer := httptest.NewServer(handler)

for _, endpoint := range tc.endpoints {
_, err = http.Get(proxyServer.URL + endpoint)
if err != nil {
t.Fatalf("requesting %s: %v", endpoint, err)
}
}

if diff := cmp.Diff(tc.expectedMetrics, metrics.Map()); diff != "" {
t.Fatalf("expected metrics do not match output:\n%s", diff)
}
})
}
}

0 comments on commit 064a5a6

Please sign in to comment.