|
6 | 6 | "log/slog" |
7 | 7 | "os" |
8 | 8 | "strings" |
| 9 | + "time" |
| 10 | + |
| 11 | + "github.com/go-resty/resty/v2" |
9 | 12 | ) |
10 | 13 |
|
11 | 14 | // Logger is the interface used for logging by flagsmith client. This interface defines the methods |
@@ -118,3 +121,55 @@ func createLogger() *slog.Logger { |
118 | 121 | Level: slog.LevelDebug, |
119 | 122 | })) |
120 | 123 | } |
| 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