Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use http.RoundTripper for client side logging #152

Merged
merged 1 commit into from
Oct 21, 2022
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
4 changes: 2 additions & 2 deletions example/weather/services/forecaster/cmd/forecaster/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ func main() {
ctx = metrics.Context(ctx, genforecaster.ServiceName)

// 4. Create clients
c := &http.Client{Transport: trace.Client(ctx, http.DefaultTransport)}
wc := weathergov.New(log.Client(c))
c := &http.Client{Transport: log.Client(trace.Client(ctx, http.DefaultTransport))}
wc := weathergov.New(c)

// 5. Create service & endpoints
svc := forecaster.New(wc)
Expand Down
4 changes: 2 additions & 2 deletions example/weather/services/locator/cmd/locator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ func main() {
ctx = metrics.Context(ctx, genlocator.ServiceName)

// 4. Create clients
c := &http.Client{Transport: trace.Client(ctx, http.DefaultTransport)}
ipc := ipapi.New(log.Client(c))
c := &http.Client{Transport: log.Client(trace.Client(ctx, http.DefaultTransport))}
ipc := ipapi.New(c)

// 5. Create service & endpoints
svc := locator.New(ipc)
Expand Down
24 changes: 10 additions & 14 deletions log/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ import (
)

type (
// Doer is a client that can execute HTTP requests.
Doer interface {
Do(*http.Request) (*http.Response, error)
}

// HTTPLogOption is a function that applies a configuration option to log
// HTTP middleware.
HTTPLogOption func(*httpLogOptions)
Expand All @@ -30,9 +25,10 @@ type (
httpClientOptions struct {
iserr func(int) bool
}
// client wraps an HTTP client and logs requests and responses.

// client wraps an HTTP roundtripper and logs requests and responses.
client struct {
Doer
http.RoundTripper
options *httpClientOptions
}
)
Expand Down Expand Up @@ -62,16 +58,16 @@ func HTTP(logCtx context.Context, opts ...HTTPLogOption) func(http.Handler) http
}
}

// Client returns a HTTP client that wraps the given doer and log requests and
// responses using the clue logger stored in the request context.
func Client(doer Doer, opts ...HTTPClientLogOption) Doer {
// Client wraps the given roundtripper and log requests and responses using the
// clue logger stored in the request context.
func Client(t http.RoundTripper, opts ...HTTPClientLogOption) http.RoundTripper {
options := &httpClientOptions{
iserr: func(status int) bool { return status >= 400 },
}
for _, o := range opts {
o(options)
}
return &client{Doer: doer, options: options}
return &client{RoundTripper: t, options: options}
}

// WithPathFilter adds a path filter to the HTTP middleware. Requests whose path
Expand All @@ -91,14 +87,14 @@ func WithErrorStatus(status int) HTTPClientLogOption {
}
}

// Do executes the given HTTP request and logs the request and response. The
// RoundTrip executes the given HTTP request and logs the request and response. The
// request context must be initialized with a clue logger.
func (c *client) Do(req *http.Request) (resp *http.Response, err error) {
func (c *client) RoundTrip(req *http.Request) (resp *http.Response, err error) {
msgKV := KV{K: MessageKey, V: "finished client HTTP request"}
methKV := KV{K: HTTPMethodKey, V: req.Method}
urlKV := KV{K: HTTPURLKey, V: req.URL.String()}
then := timeNow()
resp, err = c.Doer.Do(req)
resp, err = c.RoundTripper.RoundTrip(req)
if err != nil {
Error(req.Context(), err, msgKV, methKV, urlKV)
return
Expand Down
12 changes: 7 additions & 5 deletions log/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func TestClient(t *testing.T) {
{"no logger", true, nil, nil, ""},
{"success", false, nil, nil, successLogs},
{"error", false, fmt.Errorf("error"), nil, errorLogs},
{"error with status", false, fmt.Errorf("error"), WithErrorStatus(200), statusLogs},
{"error with status", false, nil, WithErrorStatus(200), statusLogs},
}
now := timeNow
timeNow = func() time.Time { return time.Date(2022, time.January, 9, 20, 29, 45, 0, time.UTC) }
Expand All @@ -77,12 +77,14 @@ func TestClient(t *testing.T) {
}
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { rw.Write([]byte(`OK`)) }))
defer server.Close()
client := Client(server.Client())
client := server.Client()
if c.clientErr != nil {
client = Client(&errorClient{err: c.clientErr})
client.Transport = &errorClient{err: c.clientErr}
}
if c.opt != nil {
client = Client(server.Client(), c.opt)
client.Transport = Client(client.Transport, c.opt)
} else {
client.Transport = Client(client.Transport)
}

req, _ := http.NewRequest("GET", server.URL, nil)
Expand Down Expand Up @@ -120,6 +122,6 @@ type errorClient struct {
err error
}

func (c *errorClient) Do(req *http.Request) (*http.Response, error) {
func (c *errorClient) RoundTrip(req *http.Request) (*http.Response, error) {
return nil, c.err
}