Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 24 additions & 20 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,23 @@ import (
)

type Request struct {
alias string
chainCallback Callback
hostURL *url.URL
metrics Metrics
restyRequest *resty.Request
startTime time.Time
alias string
chainCallback Callback
hostURL *url.URL
metrics Metrics
additionalAttrs map[string]string
restyRequest *resty.Request
startTime time.Time
}

// NewRequest creates a request for the specified HTTP method.
func (c *HTTPClient) NewRequest() *Request {
return &Request{
restyRequest: c.resty.NewRequest(),
chainCallback: c.callbackChain,
metrics: c.metrics,
hostURL: c.hostURL,
restyRequest: c.resty.NewRequest(),
chainCallback: c.callbackChain,
metrics: c.metrics,
hostURL: c.hostURL,
additionalAttrs: map[string]string{},
}
}

Expand All @@ -36,6 +38,11 @@ func (r *Request) HostURL() *url.URL {
return r.hostURL
}

func (r *Request) SetMetricsAttrs(attrs map[string]string) *Request {
r.additionalAttrs = attrs
return r
}

// SetHostURL sets the host url for the request.
func (r *Request) SetHostURL(url *url.URL) *Request {
r.hostURL = url
Expand Down Expand Up @@ -142,35 +149,32 @@ func (r *Request) Execute(method string, url string) (*Response, error) {
}

return r.chainCallback(execute)
})
}, r.additionalAttrs)
}

func registerMetrics(key string, metrics Metrics, f func() (*Response, error)) (*Response, error) {
func registerMetrics(key string, metrics Metrics, f func() (*Response, error), additionalAttrs map[string]string) (*Response, error) {
resp, err := f()

if metrics != nil {
go func(resp *Response, err error) {
attrs := map[string]string{}
if resp != nil {
attrs = map[string]string{
"host": resp.Request().HostURL().Host,
"path": resp.Request().HostURL().Path,
}
additionalAttrs["host"] = resp.Request().HostURL().Host
additionalAttrs["path"] = resp.Request().HostURL().Path
metrics.PushToSeries(fmt.Sprintf("%s.%s", key, "response_time"), resp.ResponseTime().Seconds())
if resp.statusCode != 0 {
metrics.IncrCounter(fmt.Sprintf("%s.status.%d", key, resp.StatusCode()))
attrs["status"] = fmt.Sprintf("%d", resp.StatusCode())
additionalAttrs["status"] = fmt.Sprintf("%d", resp.StatusCode())
}
}
if err != nil {
if errors.Is(err, ErrCircuitOpen) {
metrics.IncrCounter(fmt.Sprintf("%s.%s", key, "circuit_open"))
} else {
metrics.IncrCounter(fmt.Sprintf("%s.%s", key, "errors"))
attrs["error"] = err.Error()
additionalAttrs["error"] = err.Error()
}
}
metrics.IncrCounterWithAttrs(fmt.Sprintf("%s.%s", key, "total"), attrs)
metrics.IncrCounterWithAttrs(fmt.Sprintf("%s.%s", key, "total"), additionalAttrs)
}(resp, err)
}

Expand Down
29 changes: 29 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http/httptest"
"net/url"
"testing"
"time"

"github.com/globocom/httpclient"

Expand Down Expand Up @@ -160,3 +161,31 @@ func testSetHostURL(target *httpclient.Request) func(*testing.T) {
assert.Nil(t, target.HostURL())
}
}

func TestSetMetricsAttrs_PropagatesToMetrics(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(handleFunc))
defer server.Close()

metrics := &mockMetrics{}
client := httpclient.NewHTTPClient(
&httpclient.LoggerAdapter{Writer: io.Discard},
httpclient.WithHostURL(server.URL),
httpclient.WithMetrics(metrics),
)
request := client.NewRequest()

attrs := map[string]string{"foo": "bar", "baz": "qux"}
request.SetMetricsAttrs(attrs)
_, _ = request.Get("/")

time.Sleep(100 * time.Millisecond)

found := false
for _, calledAttrs := range metrics.incrCounterWithAttrsCalls {
if calledAttrs.attrs["foo"] == "bar" && calledAttrs.attrs["baz"] == "qux" {
found = true
break
}
}
assert.True(t, found, "Attributes passed to SetMetricsAttrs must be propagated to IncrCounterWithAttrs")
}
Loading