Skip to content

Commit ba06af6

Browse files
authoredAug 16, 2022
Merge pull request #121 from foomo/add-telemetry-option
add http client telemetry option
2 parents 7067385 + e6dfd8e commit ba06af6

File tree

6 files changed

+112
-18
lines changed

6 files changed

+112
-18
lines changed
 

‎example/roundtripwares/requestid/main.go

+3
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,11 @@ func main() {
5353

5454
svr.AddService(
5555
keel.NewServiceHTTP(l, "demo", "localhost:8080", svs,
56+
// add middleware
5657
middleware.RequestID(),
58+
// add middleware
5759
middleware.SessionID(),
60+
// add middleware
5861
middleware.TrackingID(),
5962
),
6063
)

‎net/http/client.go

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/url"
99
"time"
1010

11+
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
1112
"go.uber.org/zap"
1213

1314
"github.com/foomo/keel/net/http/roundtripware"
@@ -225,6 +226,12 @@ func HTTPClientWithRoundTripware(l *zap.Logger, roundTripware ...roundtripware.R
225226
}
226227
}
227228

229+
func HTTPClientWithTelemetry(opts ...otelhttp.Option) HTTPClientOption {
230+
return func(v *http.Client) {
231+
v.Transport = otelhttp.NewTransport(v.Transport, opts...)
232+
}
233+
}
234+
228235
func NewHTTPClient(opts ...HTTPClientOption) *http.Client {
229236
transport := &http.Transport{
230237
Proxy: http.ProxyFromEnvironment,

‎net/http/middleware/requestid.go

+7-13
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,28 @@ package middleware
33
import (
44
"net/http"
55

6-
"github.com/google/uuid"
76
"go.uber.org/zap"
87

98
keelhttpcontext "github.com/foomo/keel/net/http/context"
9+
"github.com/foomo/keel/net/http/provider"
1010
)
1111

1212
type (
1313
RequestIDOptions struct {
14-
Generator RequestIDGenerator
14+
Provider provider.RequestID
1515
RequestHeader []string
1616
ResponseHeader string
1717
SetRequestHeader bool
1818
SetResponseHeader bool
1919
SetContext bool
2020
}
21-
RequestIDOption func(*RequestIDOptions)
22-
RequestIDGenerator func() string
21+
RequestIDOption func(*RequestIDOptions)
2322
)
2423

25-
// DefaultRequestIDGenerator function
26-
func DefaultRequestIDGenerator() string {
27-
return uuid.New().String()
28-
}
29-
3024
// GetDefaultRequestIDOptions returns the default options
3125
func GetDefaultRequestIDOptions() RequestIDOptions {
3226
return RequestIDOptions{
33-
Generator: DefaultRequestIDGenerator,
27+
Provider: provider.DefaultRequestID,
3428
RequestHeader: []string{"X-Request-ID", "Cf-Ray"},
3529
ResponseHeader: "X-Request-ID",
3630
SetRequestHeader: true,
@@ -68,9 +62,9 @@ func RequestIDWithSetResponseHeader(v bool) RequestIDOption {
6862
}
6963

7064
// RequestIDWithGenerator middleware option
71-
func RequestIDWithGenerator(v RequestIDGenerator) RequestIDOption {
65+
func RequestIDWithGenerator(v provider.RequestID) RequestIDOption {
7266
return func(o *RequestIDOptions) {
73-
o.Generator = v
67+
o.Provider = v
7468
}
7569
}
7670

@@ -103,7 +97,7 @@ func RequestIDWithOptions(opts RequestIDOptions) Middleware {
10397
}
10498
}
10599
if requestID == "" {
106-
requestID = opts.Generator()
100+
requestID = opts.Provider()
107101
}
108102
if requestID != "" && opts.SetContext {
109103
r = r.WithContext(keelhttpcontext.SetRequestID(r.Context(), requestID))
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package provider
2+
3+
import (
4+
"github.com/google/uuid"
5+
)
6+
7+
type RequestID func() string
8+
9+
// DefaultRequestID function
10+
func DefaultRequestID() string {
11+
return uuid.New().String()
12+
}

‎net/http/roundtripware/requestid.go

+22-5
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,23 @@ import (
66
"go.uber.org/zap"
77

88
keelhttpcontext "github.com/foomo/keel/net/http/context"
9+
"github.com/foomo/keel/net/http/provider"
910
)
1011

1112
type (
1213
RequestIDOptions struct {
13-
Header string
14+
Header string
15+
Provider provider.RequestID
16+
SetHeader bool
1417
}
15-
RequestIDOption func(*RequestIDOptions)
16-
RequestIDGenerator func() string
18+
RequestIDOption func(*RequestIDOptions)
1719
)
1820

1921
// GetDefaultRequestIDOptions returns the default options
2022
func GetDefaultRequestIDOptions() RequestIDOptions {
2123
return RequestIDOptions{
22-
Header: "X-Request-ID",
24+
Header: "X-Request-ID",
25+
Provider: provider.DefaultRequestID,
2326
}
2427
}
2528

@@ -30,6 +33,13 @@ func RequestIDWithHeader(v string) RequestIDOption {
3033
}
3134
}
3235

36+
// RequestIDWithProvider middleware option
37+
func RequestIDWithProvider(v provider.RequestID) RequestIDOption {
38+
return func(o *RequestIDOptions) {
39+
o.Provider = v
40+
}
41+
}
42+
3343
// RequestID returns a RoundTripper which prints out the request & response object
3444
func RequestID(opts ...RequestIDOption) RoundTripware {
3545
o := GetDefaultRequestIDOptions()
@@ -41,8 +51,15 @@ func RequestID(opts ...RequestIDOption) RoundTripware {
4151
return func(l *zap.Logger, next Handler) Handler {
4252
return func(r *http.Request) (*http.Response, error) {
4353
if value := r.Header.Get(o.Header); value == "" {
54+
var requestID string
4455
if value, ok := keelhttpcontext.GetRequestID(r.Context()); ok && value != "" {
45-
r.Header.Set(o.Header, value)
56+
requestID = value
57+
}
58+
if requestID == "" {
59+
requestID = o.Provider()
60+
}
61+
if requestID != "" {
62+
r.Header.Set(o.Header, requestID)
4663
}
4764
}
4865
return next(r)
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package roundtripware_test
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
"go.uber.org/zap/zaptest"
12+
13+
keelhttp "github.com/foomo/keel/net/http"
14+
keelhttpcontext "github.com/foomo/keel/net/http/context"
15+
"github.com/foomo/keel/net/http/roundtripware"
16+
)
17+
18+
func TestRequestID(t *testing.T) {
19+
l := zaptest.NewLogger(t)
20+
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
21+
w.WriteHeader(http.StatusOK)
22+
}))
23+
defer svr.Close()
24+
25+
client := keelhttp.NewHTTPClient(
26+
keelhttp.HTTPClientWithRoundTripware(l,
27+
roundtripware.RequestID(),
28+
),
29+
)
30+
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, svr.URL, nil)
31+
require.NoError(t, err)
32+
assert.Empty(t, req.Header.Get(keelhttp.HeaderXRequestID))
33+
34+
resp, err := client.Do(req)
35+
require.NoError(t, err)
36+
defer resp.Body.Close()
37+
assert.NotEmpty(t, req.Header.Get(keelhttp.HeaderXRequestID))
38+
}
39+
40+
func TestRequestID_Context(t *testing.T) {
41+
l := zaptest.NewLogger(t)
42+
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
43+
w.WriteHeader(http.StatusOK)
44+
}))
45+
defer svr.Close()
46+
47+
client := keelhttp.NewHTTPClient(
48+
keelhttp.HTTPClientWithRoundTripware(l,
49+
roundtripware.RequestID(),
50+
),
51+
)
52+
ctx := keelhttpcontext.SetRequestID(context.Background(), "123456")
53+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, svr.URL, nil)
54+
require.NoError(t, err)
55+
assert.Empty(t, req.Header.Get(keelhttp.HeaderXRequestID))
56+
57+
resp, err := client.Do(req)
58+
require.NoError(t, err)
59+
defer resp.Body.Close()
60+
assert.Equal(t, "123456", req.Header.Get(keelhttp.HeaderXRequestID))
61+
}

0 commit comments

Comments
 (0)
Please sign in to comment.