|
4 | 4 | package middleware |
5 | 5 |
|
6 | 6 | import ( |
| 7 | + "context" |
7 | 8 | "errors" |
| 9 | + "log/slog" |
8 | 10 | "net/http" |
9 | 11 | "time" |
10 | 12 |
|
@@ -247,6 +249,72 @@ func RequestLoggerWithConfig(config RequestLoggerConfig) echo.MiddlewareFunc { |
247 | 249 | return mw |
248 | 250 | } |
249 | 251 |
|
| 252 | +// RequestLogger returns a RequestLogger middleware with default configuration which |
| 253 | +// uses default slog.slog logger. |
| 254 | +// |
| 255 | +// To customize slog output format replace slog default logger: |
| 256 | +// For JSON format: `slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))` |
| 257 | +func RequestLogger() echo.MiddlewareFunc { |
| 258 | + config := RequestLoggerConfig{ |
| 259 | + LogLatency: true, |
| 260 | + LogProtocol: false, |
| 261 | + LogRemoteIP: true, |
| 262 | + LogHost: true, |
| 263 | + LogMethod: true, |
| 264 | + LogURI: true, |
| 265 | + LogURIPath: false, |
| 266 | + LogRoutePath: false, |
| 267 | + LogRequestID: true, |
| 268 | + LogReferer: false, |
| 269 | + LogUserAgent: true, |
| 270 | + LogStatus: true, |
| 271 | + LogError: true, |
| 272 | + LogContentLength: true, |
| 273 | + LogResponseSize: true, |
| 274 | + LogHeaders: nil, |
| 275 | + LogQueryParams: nil, |
| 276 | + LogFormValues: nil, |
| 277 | + HandleError: true, // forwards error to the global error handler, so it can decide appropriate status code |
| 278 | + LogValuesFunc: func(c echo.Context, v RequestLoggerValues) error { |
| 279 | + if v.Error == nil { |
| 280 | + slog.LogAttrs(context.Background(), slog.LevelInfo, "REQUEST", |
| 281 | + slog.String("method", v.Method), |
| 282 | + slog.String("uri", v.URI), |
| 283 | + slog.Int("status", v.Status), |
| 284 | + slog.Duration("latency", v.Latency), |
| 285 | + slog.String("host", v.Host), |
| 286 | + slog.String("bytes_in", v.ContentLength), |
| 287 | + slog.Int64("bytes_out", v.ResponseSize), |
| 288 | + slog.String("user_agent", v.UserAgent), |
| 289 | + slog.String("remote_ip", v.RemoteIP), |
| 290 | + slog.String("request_id", v.RequestID), |
| 291 | + ) |
| 292 | + } else { |
| 293 | + slog.LogAttrs(context.Background(), slog.LevelError, "REQUEST_ERROR", |
| 294 | + slog.String("method", v.Method), |
| 295 | + slog.String("uri", v.URI), |
| 296 | + slog.Int("status", v.Status), |
| 297 | + slog.Duration("latency", v.Latency), |
| 298 | + slog.String("host", v.Host), |
| 299 | + slog.String("bytes_in", v.ContentLength), |
| 300 | + slog.Int64("bytes_out", v.ResponseSize), |
| 301 | + slog.String("user_agent", v.UserAgent), |
| 302 | + slog.String("remote_ip", v.RemoteIP), |
| 303 | + slog.String("request_id", v.RequestID), |
| 304 | + |
| 305 | + slog.String("error", v.Error.Error()), |
| 306 | + ) |
| 307 | + } |
| 308 | + return nil |
| 309 | + }, |
| 310 | + } |
| 311 | + mw, err := config.ToMiddleware() |
| 312 | + if err != nil { |
| 313 | + panic(err) |
| 314 | + } |
| 315 | + return mw |
| 316 | +} |
| 317 | + |
250 | 318 | // ToMiddleware converts RequestLoggerConfig into middleware or returns an error for invalid configuration. |
251 | 319 | func (config RequestLoggerConfig) ToMiddleware() (echo.MiddlewareFunc, error) { |
252 | 320 | if config.Skipper == nil { |
|
0 commit comments