Skip to content

Commit 8cb2f87

Browse files
committed
add HTTP logging middleware
1 parent 6029d59 commit 8cb2f87

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

client.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ func NewClient(apiKey string, options ...Option) *Client {
7171
opt(c)
7272
}
7373
}
74-
c.client.SetLogger(newSlogToRestyAdapter(c.log))
74+
c.client = c.client.
75+
SetLogger(newSlogToRestyAdapter(c.log)).
76+
OnBeforeRequest(newRestyLogRequestMiddleware(c.log)).
77+
OnAfterResponse(newRestyLogResponseMiddleware(c.log))
7578

7679
c.log.Debug("initialising Flagsmith client",
7780
"base_url", c.config.baseURL,

logger.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import (
66
"log/slog"
77
"os"
88
"strings"
9+
"time"
10+
11+
"github.com/go-resty/resty/v2"
912
)
1013

1114
// Logger is the interface used for logging by flagsmith client. This interface defines the methods
@@ -118,3 +121,55 @@ func createLogger() *slog.Logger {
118121
Level: slog.LevelDebug,
119122
}))
120123
}
124+
125+
const (
126+
contextLoggerKey contextKey = contextKey("logger")
127+
contextStartTimeKey contextKey = contextKey("startTime")
128+
)
129+
130+
// restySlogLogger implements a [resty.Logger] using a [slog.Logger].
131+
type restySlogLogger struct {
132+
logger *slog.Logger
133+
}
134+
135+
func newRestyLogRequestMiddleware(logger *slog.Logger) resty.RequestMiddleware {
136+
return func(c *resty.Client, req *resty.Request) error {
137+
// Create a child logger with request metadata
138+
reqLogger := logger.WithGroup("http").With(
139+
"method", req.Method,
140+
"url", req.URL,
141+
)
142+
reqLogger.Debug("request")
143+
144+
// Store the logger in this request's context, and use it in the response
145+
req.SetContext(context.WithValue(req.Context(), contextLoggerKey, reqLogger))
146+
147+
// Time the current request
148+
req.SetContext(context.WithValue(req.Context(), contextStartTimeKey, time.Now()))
149+
150+
return nil
151+
}
152+
}
153+
154+
func newRestyLogResponseMiddleware(logger *slog.Logger) resty.ResponseMiddleware {
155+
return func(client *resty.Client, resp *resty.Response) error {
156+
// Retrieve the logger and start time from context
157+
reqLogger, _ := resp.Request.Context().Value(contextLoggerKey).(*slog.Logger)
158+
startTime, _ := resp.Request.Context().Value(contextStartTimeKey).(time.Time)
159+
160+
if reqLogger == nil {
161+
reqLogger = logger
162+
}
163+
reqLogger = reqLogger.With(
164+
slog.Int("status", resp.StatusCode()),
165+
slog.Duration("duration", time.Since(startTime)),
166+
slog.Int64("content_length", resp.Size()),
167+
)
168+
if resp.IsError() {
169+
reqLogger.Error("error response")
170+
} else {
171+
reqLogger.Debug("response")
172+
}
173+
return nil
174+
}
175+
}

0 commit comments

Comments
 (0)