Logger

Logger middleware logs the information about each HTTP request.

Echo has 2 different logger middlewares:

  • Older string template based logger Logger - easy to start with but has limited capabilities
  • Newer customizable function based logger RequestLogger - allows developer fully to customize what is logged and how it is logged. Suitable for usage with 3rd party logger libraries.

String Template

Usage

  1. e.Use(middleware.Logger())

Sample output

  1. {"time":"2017-01-12T08:58:07.372015644-08:00","remote_ip":"::1","host":"localhost:1323","method":"GET","uri":"/","status":200,"error":"","latency":14743,"latency_human":"14.743µs","bytes_in":0,"bytes_out":2}

Custom Configuration

Usage

  1. e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
  2. Format: "method=${method}, uri=${uri}, status=${status}\n",
  3. }))

Example above uses a Format which logs request method and request URI.

Sample output

  1. method=GET, uri=/, status=200

Configuration

  1. // LoggerConfig defines the config for Logger middleware.
  2. LoggerConfig struct {
  3. // Skipper defines a function to skip middleware.
  4. Skipper Skipper
  5. // Tags to construct the logger format.
  6. //
  7. // - time_unix
  8. // - time_unix_milli
  9. // - time_unix_micro
  10. // - time_unix_nano
  11. // - time_rfc3339
  12. // - time_rfc3339_nano
  13. // - time_custom
  14. // - id (Request ID)
  15. // - remote_ip
  16. // - uri
  17. // - host
  18. // - method
  19. // - path
  20. // - protocol
  21. // - referer
  22. // - user_agent
  23. // - status
  24. // - error
  25. // - latency (In nanoseconds)
  26. // - latency_human (Human readable)
  27. // - bytes_in (Bytes received)
  28. // - bytes_out (Bytes sent)
  29. // - header:<NAME>
  30. // - query:<NAME>
  31. // - form:<NAME>
  32. //
  33. // Example "${remote_ip} ${status}"
  34. //
  35. // Optional. Default value DefaultLoggerConfig.Format.
  36. Format string `yaml:"format"`
  37. // Optional. Default value DefaultLoggerConfig.CustomTimeFormat.
  38. CustomTimeFormat string `yaml:"custom_time_format"`
  39. // Output is a writer where logs in JSON format are written.
  40. // Optional. Default value os.Stdout.
  41. Output io.Writer
  42. }

Default Configuration

  1. DefaultLoggerConfig = LoggerConfig{
  2. Skipper: DefaultSkipper,
  3. Format: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}",` +
  4. `"host":"${host}","method":"${method}","uri":"${uri}","user_agent":"${user_agent}",` +
  5. `"status":${status},"error":"${error}","latency":${latency},"latency_human":"${latency_human}"` +
  6. `,"bytes_in":${bytes_in},"bytes_out":${bytes_out}}` + "\n",
  7. CustomTimeFormat: "2006-01-02 15:04:05.00000",
  8. }

Customizable Function

RequestLogger middleware allows developer fully to customize what is logged and how it is logged and is more suitable for usage with 3rd party (structured logging) libraries.

See RequestLoggerConfig structure fields for values that logger knows to extract.

Examples

Example for naive fmt.Printf

  1. e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
  2. LogStatus: true,
  3. LogURI: true,
  4. BeforeNextFunc: func(c echo.Context) {
  5. c.Set("customValueFromContext", 42)
  6. },
  7. LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
  8. value, _ := c.Get("customValueFromContext").(int)
  9. fmt.Printf("REQUEST: uri: %v, status: %v, custom-value: %v\n", v.URI, v.Status, value)
  10. return nil
  11. },
  12. }))

Example for Zerolog (https://github.com/rs/zerolog)

  1. logger := zerolog.New(os.Stdout)
  2. e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
  3. LogURI: true,
  4. LogStatus: true,
  5. LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
  6. logger.Info().
  7. Str("URI", v.URI).
  8. Int("status", v.Status).
  9. Msg("request")
  10. return nil
  11. },
  12. }))

Example for Zap (https://github.com/uber-go/zap)

  1. logger, _ := zap.NewProduction()
  2. e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
  3. LogURI: true,
  4. LogStatus: true,
  5. LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
  6. logger.Info("request",
  7. zap.String("URI", v.URI),
  8. zap.Int("status", v.Status),
  9. )
  10. return nil
  11. },
  12. }))

Example for Logrus (https://github.com/sirupsen/logrus)

  1. log := logrus.New()
  2. e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
  3. LogURI: true,
  4. LogStatus: true,
  5. LogValuesFunc: func(c echo.Context, values middleware.RequestLoggerValues) error {
  6. log.WithFields(logrus.Fields{
  7. "URI": values.URI,
  8. "status": values.Status,
  9. }).Info("request")
  10. return nil
  11. },
  12. }))