slog: Echo middleware

Echo middleware to log http requests using slog.
See also:
🚀 Install
go get github.com/samber/slog-echo
Compatibility: go >= 1.21
No breaking changes will be made to exported APIs before v2.0.0.
💡 Usage
Minimal
import (
"net/http"
"os"
"time"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
slogecho "github.com/samber/slog-echo"
"log/slog"
)
// Create a slog logger, which:
// - Logs to stdout.
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
// Echo instance
e := echo.New()
// Middleware
e.Use(slogecho.New(logger))
e.Use(middleware.Recover())
// Routes
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.GET("/error", func(c echo.Context) error {
return echo.NewHTTPError(http.StatusInternalServerError, "I'm angry")
})
// Start server
e.Logger.Fatal(e.Start(":4242"))
// output:
// time=2023-04-10T14:00:00Z level=INFO msg="Success" status=200 method=GET path=/ ip=::1 latency=25.958µs user-agent=curl/7.77.0 time=2023-04-10T14:00:00Z request-id=229c7fc8-64f5-4467-bc4a-940700503b0d
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
slogecho "github.com/samber/slog-echo"
slogformatter "github.com/samber/slog-formatter"
"log/slog"
)
// Create a slog logger, which:
// - Logs to stdout.
// - RFC3339 with UTC time format.
logger := slog.New(
slogformatter.NewFormatterHandler(
slogformatter.TimezoneConverter(time.UTC),
slogformatter.TimeFormatter(time.DateTime, nil),
)(
slog.NewTextHandler(os.Stdout, nil),
),
)
// Echo instance
e := echo.New()
// Middleware
e.Use(slogecho.New(logger))
e.Use(middleware.Recover())
// Routes
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.GET("/error", func(c echo.Context) error {
return echo.NewHTTPError(http.StatusInternalServerError, "I'm angry")
})
// Start server
e.Logger.Fatal(e.Start(":4242"))
// output:
// time=2023-04-10T14:00:00Z level=INFO msg="Success" status=200 method=GET path=/ ip=::1 latency=25.958µs user-agent=curl/7.77.0 time=2023-04-10T14:00:00Z request-id=229c7fc8-64f5-4467-bc4a-940700503b0d
Using custom logger sub-group
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
slogecho "github.com/samber/slog-echo"
"log/slog"
)
// Create a slog logger, which:
// - Logs to stdout.
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
// Echo instance
e := echo.New()
// Middleware
e.Use(slogecho.New(logger.WithGroup("http")))
e.Use(middleware.Recover())
// Routes
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.GET("/error", func(c echo.Context) error {
return echo.NewHTTPError(http.StatusInternalServerError, "I'm angry")
})
// Start server
e.Logger.Fatal(e.Start(":4242"))
// output:
// time=2023-04-10T14:00:00Z level=INFO msg="Success" http.status=200 http.method=GET http.path=/ http.ip=::1 http.latency=25.958µs http.user-agent=curl/7.77.0 http.time=2023-04-10T14:00:00Z http.request-id=229c7fc8-64f5-4467-bc4a-940700503b0d
Add logger to a single route
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
slogecho "github.com/samber/slog-echo"
"log/slog"
)
// Create a slog logger, which:
// - Logs to stdout.
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
// Echo instance
e := echo.New()
// Middleware
e.Use(middleware.Recover())
// Routes
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
}, slogecho.New(logger))
// Start server
e.Logger.Fatal(e.Start(":4242"))
// output:
// time=2023-04-10T14:00:00Z level=INFO msg="Success" status=200 method=GET path=/ ip=::1 latency=25.958µs user-agent=curl/7.77.0 time=2023-04-10T14:00:00Z request-id=229c7fc8-64f5-4467-bc4a-940700503b0d
Adding custom attributes
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
slogecho "github.com/samber/slog-echo"
"log/slog"
)
// Create a slog logger, which:
// - Logs to stdout.
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
// Add an attribute to all log entries made through this logger.
logger = logger.With("env", "production")
// Echo instance
e := echo.New()
// Middleware
e.Use(slogecho.New(logger))
e.Use(middleware.Recover())
// Routes
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
// Start server
e.Logger.Fatal(e.Start(":4242"))
// output:
// time=2023-04-10T14:00:00Z level=INFO msg="Success" env=production status=200 method=GET path=/ ip=::1 latency=25.958µs user-agent=curl/7.77.0 time=2023-04-10T14:00:00Z request-id=229c7fc8-64f5-4467-bc4a-940700503b0d
JSON output
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
slogecho "github.com/samber/slog-echo"
"log/slog"
)
// Create a slog logger, which:
// - Logs to stdout.
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
// Echo instance
e := echo.New()
// Middleware
e.Use(slogecho.New(logger))
e.Use(middleware.Recover())
// Routes
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
// Start server
e.Logger.Fatal(e.Start(":4242"))
// output:
// {"time":"2023-04-10T14:00:00Z","level":"INFO","msg":"Success","env":"production","status":200,"method":"GET","path":"/","ip":"::1","latency":"25.958µs","user-agent":"curl/7.77.0","time":"2023-04-10T14:00:00Z","request-id":"04201917-d7ba-4b20-a3bb-2fffba5f2bd9"}
🤝 Contributing
Don't hesitate ;)
# Install some dev dependencies
make tools
# Run tests
make test
# or
make watch-test
👤 Contributors

💫 Show your support
Give a ⭐️ if this project helped you!

📝 License
Copyright © 2023 Samuel Berthe.
This project is MIT licensed.