Skip to content

Commit 93aaabb

Browse files
Merge pull request #10 from globocom/add-attrs-on-metrics-support
Add new attributes on metrics register
2 parents c32f558 + f00866b commit 93aaabb

File tree

7 files changed

+120
-10
lines changed

7 files changed

+120
-10
lines changed

context.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import (
44
"context"
55
)
66

7-
const contextRequestIDKey = "request.id"
7+
const ContextRequestIDKey = "request.id"
88

99
// requestID returns a request present on context.
10-
func requestID(ctx context.Context) string {
11-
value := ctx.Value(contextRequestIDKey)
10+
func RequestID(ctx context.Context) string {
11+
value := ctx.Value(ContextRequestIDKey)
1212
if value == nil {
1313
return ""
1414
}

context_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
package httpclient
1+
package httpclient_test
22

33
import (
44
"context"
55

6+
"github.com/globocom/httpclient"
67
. "github.com/onsi/ginkgo"
78
. "github.com/onsi/gomega"
89
)
910

1011
var _ = Describe("requestID", func() {
1112
It("returns the request id included within the values", func() {
12-
ctx := context.WithValue(context.Background(), contextRequestIDKey, "42")
13+
ctx := context.WithValue(context.Background(), httpclient.ContextRequestIDKey, "42")
1314

14-
id := requestID(ctx)
15+
id := httpclient.RequestID(ctx)
1516

1617
Expect(id).To(Equal("42"))
1718
})
1819

1920
It("returns blank string if request id is not present on the context", func() {
2021
ctx := context.Background()
2122

22-
id := requestID(ctx)
23+
id := httpclient.RequestID(ctx)
2324

2425
Expect(id).To(Equal(""))
2526
})

register_metrics_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package httpclient_test
2+
3+
import (
4+
"io"
5+
"net/http"
6+
"net/http/httptest"
7+
"sync"
8+
"testing"
9+
"time"
10+
11+
"github.com/globocom/httpclient"
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
type mockMetrics struct {
16+
pushToSeriesCalls []string
17+
incrCounterCalls []string
18+
incrCounterWithAttrsCalls []struct {
19+
key string
20+
attrs map[string]string
21+
}
22+
lock sync.Mutex
23+
}
24+
25+
func (m *mockMetrics) PushToSeries(key string, value float64) {
26+
m.lock.Lock()
27+
defer m.lock.Unlock()
28+
m.pushToSeriesCalls = append(m.pushToSeriesCalls, key)
29+
}
30+
31+
func (m *mockMetrics) IncrCounter(key string) {
32+
m.lock.Lock()
33+
defer m.lock.Unlock()
34+
m.incrCounterCalls = append(m.incrCounterCalls, key)
35+
}
36+
37+
func (m *mockMetrics) IncrCounterWithAttrs(key string, attrs map[string]string) {
38+
m.lock.Lock()
39+
defer m.lock.Unlock()
40+
m.incrCounterWithAttrsCalls = append(m.incrCounterWithAttrsCalls, struct {
41+
key string
42+
attrs map[string]string
43+
}{key, attrs})
44+
}
45+
46+
func TestHTTPClient_MetricsIntegration(t *testing.T) {
47+
metrics := &mockMetrics{}
48+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
49+
rw.WriteHeader(http.StatusOK)
50+
rw.Write([]byte("OK"))
51+
}))
52+
defer server.Close()
53+
54+
client := httpclient.NewHTTPClient(
55+
&httpclient.LoggerAdapter{Writer: io.Discard},
56+
httpclient.WithHostURL(server.URL),
57+
httpclient.WithMetrics(metrics),
58+
)
59+
60+
req := client.NewRequest()
61+
resp, err := req.Get("/")
62+
assert.NoError(t, err)
63+
assert.NotNil(t, resp)
64+
65+
assert.Eventually(t, func() bool {
66+
metrics.lock.Lock()
67+
defer metrics.lock.Unlock()
68+
return len(metrics.pushToSeriesCalls) > 0 && len(metrics.incrCounterCalls) > 0 && len(metrics.incrCounterWithAttrsCalls) > 0
69+
}, time.Second, 100*time.Millisecond)
70+
}

request.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ func (r *Request) HostURL() *url.URL {
3636
return r.hostURL
3737
}
3838

39+
// SetHostURL sets the host url for the request.
40+
func (r *Request) SetHostURL(url *url.URL) *Request {
41+
r.hostURL = url
42+
return r
43+
}
44+
3945
// SetAlias sets the alias to replace the hostname in metrics.
4046
func (r *Request) SetAlias(alias string) *Request {
4147
r.alias = alias
@@ -144,8 +150,12 @@ func registerMetrics(key string, metrics Metrics, f func() (*Response, error)) (
144150

145151
if metrics != nil {
146152
go func(resp *Response, err error) {
147-
attrs := map[string]string{}
153+
var attrs map[string]string
148154
if resp != nil {
155+
attrs = map[string]string{
156+
"host": resp.Request().HostURL().Host,
157+
"path": resp.Request().HostURL().Path,
158+
}
149159
metrics.PushToSeries(fmt.Sprintf("%s.%s", key, "response_time"), resp.ResponseTime().Seconds())
150160
if resp.statusCode != 0 {
151161
metrics.IncrCounter(fmt.Sprintf("%s.status.%d", key, resp.StatusCode()))

request_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"io"
55
"net/http"
66
"net/http/httptest"
7+
"net/url"
78
"testing"
89

910
"github.com/globocom/httpclient"
@@ -30,6 +31,7 @@ func TestRequest(t *testing.T) {
3031
"SetBody": testSetBody,
3132
"SetHeader": testSetHeader,
3233
"SetBasicAuth": testSetBasicAuth,
34+
"SetHostURL": testSetHostURL,
3335
"Get": testGet,
3436
"Post": testPost,
3537
"Put": testPut,
@@ -131,3 +133,30 @@ func testDelete(target *httpclient.Request) func(*testing.T) {
131133
assert.Equal(t, "DELETE", gReq.Method)
132134
}
133135
}
136+
137+
func testSetHostURL(target *httpclient.Request) func(*testing.T) {
138+
return func(t *testing.T) {
139+
// Create a new URL to set
140+
newURL, err := url.Parse("https://example.com:8080")
141+
assert.NoError(t, err)
142+
143+
// Test setting the host URL
144+
result := target.SetHostURL(newURL)
145+
146+
// Verify the method returns the request instance (for chaining)
147+
assert.Equal(t, target, result)
148+
149+
// Verify the host URL was set correctly
150+
hostURL := target.HostURL()
151+
assert.NotNil(t, hostURL)
152+
assert.Equal(t, "https://example.com:8080", hostURL.String())
153+
assert.Equal(t, "example.com", hostURL.Hostname())
154+
assert.Equal(t, "8080", hostURL.Port())
155+
assert.Equal(t, "https", hostURL.Scheme)
156+
157+
// Test with nil URL
158+
result2 := target.SetHostURL(nil)
159+
assert.Equal(t, target, result2)
160+
assert.Nil(t, target.HostURL())
161+
}
162+
}

suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package httpclient
1+
package httpclient_test
22

33
import (
44
"testing"

transport.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
2424
}
2525

2626
func (t *Transport) setRequestIDHeader(ctx context.Context, req *http.Request) {
27-
rID := requestID(ctx)
27+
rID := RequestID(ctx)
2828
if rID == "" {
2929
return
3030
}

0 commit comments

Comments
 (0)