@@ -197,6 +197,7 @@ type LoggerConfig struct {
197197 template * fasttemplate.Template
198198 colorer * color.Color
199199 pool * sync.Pool
200+ timeNow func () time.Time
200201}
201202
202203// DefaultLoggerConfig is the default Logger middleware config.
@@ -208,6 +209,7 @@ var DefaultLoggerConfig = LoggerConfig{
208209 `,"bytes_in":${bytes_in},"bytes_out":${bytes_out}}` + "\n " ,
209210 CustomTimeFormat : "2006-01-02 15:04:05.00000" ,
210211 colorer : color .New (),
212+ timeNow : time .Now ,
211213}
212214
213215// Logger returns a middleware that logs HTTP requests using the default configuration.
@@ -235,6 +237,8 @@ var DefaultLoggerConfig = LoggerConfig{
235237// "bytes_in":0,"bytes_out":42}
236238//
237239// For custom configurations, use LoggerWithConfig instead.
240+ //
241+ // Deprecated: please use middleware.RequestLogger or middleware.RequestLoggerWithConfig instead.
238242func Logger () echo.MiddlewareFunc {
239243 return LoggerWithConfig (DefaultLoggerConfig )
240244}
@@ -259,6 +263,8 @@ func Logger() echo.MiddlewareFunc {
259263// return c.Request().URL.Path == "/health"
260264// },
261265// }))
266+ //
267+ // Deprecated: please use middleware.RequestLoggerWithConfig instead.
262268func LoggerWithConfig (config LoggerConfig ) echo.MiddlewareFunc {
263269 // Defaults
264270 if config .Skipper == nil {
@@ -267,9 +273,18 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
267273 if config .Format == "" {
268274 config .Format = DefaultLoggerConfig .Format
269275 }
276+ writeString := func (buf * bytes.Buffer , in string ) (int , error ) { return buf .WriteString (in ) }
277+ if config .Format [0 ] == '{' { // format looks like JSON, so we need to escape invalid characters
278+ writeString = writeJSONSafeString
279+ }
280+
270281 if config .Output == nil {
271282 config .Output = DefaultLoggerConfig .Output
272283 }
284+ timeNow := DefaultLoggerConfig .timeNow
285+ if config .timeNow != nil {
286+ timeNow = config .timeNow
287+ }
273288
274289 config .template = fasttemplate .New (config .Format , "${" , "}" )
275290 config .colorer = color .New ()
@@ -305,49 +320,47 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
305320 }
306321 return config .CustomTagFunc (c , buf )
307322 case "time_unix" :
308- return buf .WriteString (strconv .FormatInt (time . Now ().Unix (), 10 ))
323+ return buf .WriteString (strconv .FormatInt (timeNow ().Unix (), 10 ))
309324 case "time_unix_milli" :
310- // go 1.17 or later, it supports time#UnixMilli()
311- return buf .WriteString (strconv .FormatInt (time .Now ().UnixNano ()/ 1000000 , 10 ))
325+ return buf .WriteString (strconv .FormatInt (timeNow ().UnixMilli (), 10 ))
312326 case "time_unix_micro" :
313- // go 1.17 or later, it supports time#UnixMicro()
314- return buf .WriteString (strconv .FormatInt (time .Now ().UnixNano ()/ 1000 , 10 ))
327+ return buf .WriteString (strconv .FormatInt (timeNow ().UnixMicro (), 10 ))
315328 case "time_unix_nano" :
316- return buf .WriteString (strconv .FormatInt (time . Now ().UnixNano (), 10 ))
329+ return buf .WriteString (strconv .FormatInt (timeNow ().UnixNano (), 10 ))
317330 case "time_rfc3339" :
318- return buf .WriteString (time . Now ().Format (time .RFC3339 ))
331+ return buf .WriteString (timeNow ().Format (time .RFC3339 ))
319332 case "time_rfc3339_nano" :
320- return buf .WriteString (time . Now ().Format (time .RFC3339Nano ))
333+ return buf .WriteString (timeNow ().Format (time .RFC3339Nano ))
321334 case "time_custom" :
322- return buf .WriteString (time . Now ().Format (config .CustomTimeFormat ))
335+ return buf .WriteString (timeNow ().Format (config .CustomTimeFormat ))
323336 case "id" :
324337 id := req .Header .Get (echo .HeaderXRequestID )
325338 if id == "" {
326339 id = res .Header ().Get (echo .HeaderXRequestID )
327340 }
328- return buf . WriteString ( id )
341+ return writeString ( buf , id )
329342 case "remote_ip" :
330- return buf . WriteString ( c .RealIP ())
343+ return writeString ( buf , c .RealIP ())
331344 case "host" :
332- return buf . WriteString ( req .Host )
345+ return writeString ( buf , req .Host )
333346 case "uri" :
334- return buf . WriteString ( req .RequestURI )
347+ return writeString ( buf , req .RequestURI )
335348 case "method" :
336- return buf . WriteString ( req .Method )
349+ return writeString ( buf , req .Method )
337350 case "path" :
338351 p := req .URL .Path
339352 if p == "" {
340353 p = "/"
341354 }
342- return buf . WriteString ( p )
355+ return writeString ( buf , p )
343356 case "route" :
344- return buf . WriteString ( c .Path ())
357+ return writeString ( buf , c .Path ())
345358 case "protocol" :
346- return buf . WriteString ( req .Proto )
359+ return writeString ( buf , req .Proto )
347360 case "referer" :
348- return buf . WriteString ( req .Referer ())
361+ return writeString ( buf , req .Referer ())
349362 case "user_agent" :
350- return buf . WriteString ( req .UserAgent ())
363+ return writeString ( buf , req .UserAgent ())
351364 case "status" :
352365 n := res .Status
353366 s := config .colorer .Green (n )
@@ -377,17 +390,17 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
377390 if cl == "" {
378391 cl = "0"
379392 }
380- return buf . WriteString ( cl )
393+ return writeString ( buf , cl )
381394 case "bytes_out" :
382395 return buf .WriteString (strconv .FormatInt (res .Size , 10 ))
383396 default :
384397 switch {
385398 case strings .HasPrefix (tag , "header:" ):
386- return buf . Write ([] byte ( c .Request ().Header .Get (tag [7 :]) ))
399+ return writeString ( buf , c .Request ().Header .Get (tag [7 :]))
387400 case strings .HasPrefix (tag , "query:" ):
388- return buf . Write ([] byte ( c .QueryParam (tag [6 :]) ))
401+ return writeString ( buf , c .QueryParam (tag [6 :]))
389402 case strings .HasPrefix (tag , "form:" ):
390- return buf . Write ([] byte ( c .FormValue (tag [5 :]) ))
403+ return writeString ( buf , c .FormValue (tag [5 :]))
391404 case strings .HasPrefix (tag , "cookie:" ):
392405 cookie , err := c .Cookie (tag [7 :])
393406 if err == nil {
0 commit comments