Overview of slog-echo
mainslog library. It allows you to integrate structured logging directly into your Echo application lifecycle.repository·main·Indexed 41 days ago
https://github.com/samber/slog-echoMiddleware for the Echo web framework that enables structured HTTP request logging using Go's standard slog library. Supports customizable log levels for different HTTP status categories, OpenTelemetry SpanID and TraceID integration, and extensive request/response filtering based on method, status, path, and host.
slog library. It allows you to integrate structured logging directly into your Echo application lifecycle.You can use slogecho.NewWithFilters to include or exclude logs based on specific criteria. Filters can inspect the echo.Context and the error returned by the handler.
Commonly used filter functions include:
Accept / Ignore (can inspect error)AcceptMethod / IgnoreMethodAcceptStatus / IgnoreStatusAcceptStatusGreaterThan / IgnoreStatusGreaterThanAcceptStatusLessThan / IgnoreStatusLessThanAcceptStatusGreaterThanOrEqual / IgnoreStatusGreaterThanOrEqualAcceptStatusLessThanOrEqual / IgnoreStatusLessThanOrEqualAcceptPath / IgnorePathAcceptPathContains / IgnorePathContainsAcceptPathPrefix / IgnorePathPrefixAcceptPathSuffix / IgnorePathSuffixAcceptPathMatch / IgnorePathMatchAcceptHost / IgnoreHostAcceptHostContains / IgnoreHostContainsAcceptHostPrefix / IgnoreHostPrefixAcceptHostSuffix / IgnoreHostSuffixAcceptHostMatch / IgnoreHostMatche.Use(
slogecho.NewWithFilters(
logger,
slogecho.Accept(func(c *echo.Context, err error) bool {
return err != nil
}),
slogecho.IgnoreStatus(401, 404),
),
)Install the middleware using go get depending on your version of the Echo framework.
v2 module path.Compatibility Requirements:
>= 1.25# echo v5 (current)
go get github.com/samber/slog-echo/v2
# echo v4 (legacy)
go get github.com/samber/slog-echoA Filter is a function type used to decide whether a request should be logged or ignored by the middleware. It takes an *echo.Context and an error and returns a bool. If the filter returns true, the request is accepted (logged); if false, it is ignored.
Basic utility functions allow you to wrap existing filters:
Accept(filter Filter): Returns the filter as-is.Ignore(filter Filter): Returns a filter that negates the result of the provided filter.type Filter func(ctx *echo.Context, err error) boolThe slogecho.Config struct allows you to customize the middleware behavior. You can control log levels for different HTTP status categories, toggle the inclusion of specific request/response attributes (like headers, body, or trace IDs), and provide custom filters or message generators.
Key configuration fields:
DefaultLevel: The log level for successful requests.ClientErrorLevel: The log level for client errors (4xx).ServerErrorLevel: The log level for server errors (5xx).WithUserAgent, WithRequestID, WithRequestBody, WithRequestHeader, WithResponseBody, WithResponseHeader, WithSpanID, WithTraceID, WithClientIP: Boolean flags to include these attributes in the log payload.WithCustomMessage: A function func(c *echo.Context, err error) string to customize the log message.Filters: A slice of slogecho.Filter to include/exclude specific requests.type Config struct {
DefaultLevel slog.Level
ClientErrorLevel slog.Level
ServerErrorLevel slog.Level
WithUserAgent bool
WithRequestID bool
WithRequestBody bool
WithRequestHeader bool
WithResponseBody bool
WithResponseHeader bool
WithSpanID bool
WithTraceID bool
WithClientIP bool
WithCustomMessage func(c *echo.Context, err error) string
Filters []Filter
}You can define different slog.Level values for successful requests, client errors (4xx), and server errors (5xx) using the Config struct.
config := slogecho.Config{
DefaultLevel: slog.LevelInfo,
ClientErrorLevel: slog.LevelWarn,
ServerErrorLevel: slog.LevelError,
}
e.Use(slogecho.NewWithConfig(logger, config))Instead of applying the middleware globally via e.Use(), you can pass slogecho.New(logger) as a middleware argument to a specific route definition.
e.GET("/", func(c *echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
}, slogecho.New(logger))To use slogecho with minimal configuration, create a standard slog.Logger and pass it to slogecho.New(logger). This will log basic request/response metadata like method, path, status, and latency.
import (
"log"
"net/http"
"os"
"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
slogecho "github.com/samber/slog-echo"
"log/slog"
)
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
e := echo.New()
e.Use(slogecho.New(logger))
e.Use(middleware.Recover())
e.GET("/", func(c *echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
log.Fatal(e.Start(":4242"))To log full request/response details, set the following flags in slogecho.Config to true:
WithRequestBodyWithResponseBodyWithRequestHeaderWithResponseHeaderconfig := slogecho.Config{
WithRequestBody: true,
WithResponseBody: true,
WithRequestHeader: true,
WithResponseHeader: true,
}
e.Use(slogecho.NewWithConfig(logger, config))To include OpenTelemetry SpanID and TraceID in your logs, use slogecho.NewWithConfig with the corresponding boolean flags set to true in the slogecho.Config.
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
config := slogecho.Config{
WithSpanID: true,
WithTraceID: true,
}
e := echo.New()
e.Use(slogecho.NewWithConfig(logger, config))You can add persistent attributes to all logs via the logger itself using logger.With(...), or add attributes to a specific request's log entry using slogecho.AddCustomAttributes(c, ...) within a handler.
// Add to all logs via the logger
logger = logger.With("env", "production")
// Inside a route handler, add to the specific request log
e.GET("/", func(c *echo.Context) error {
slogecho.AddCustomAttributes(c, slog.String("foo", "bar"))
return c.String(http.StatusOK, "Hello, World!")
})The Config struct allows you to customize how requests are logged.
DefaultLevel: The level used for successful requests (default: slog.LevelInfo).ClientErrorLevel: The level used for 4xx status codes (default: slog.LevelWarn).ServerErrorLevel: The level used for 5xx status codes (default: slog.LevelError).Set these to true to include specific data in the logs:
WithUserAgent: Include the User-Agent header.WithRequestID: Include the Request ID (uses echo.HeaderXRequestID).WithRequestBody: Include the request body (limited to RequestBodyMaxSize, default 64KB).WithRequestHeader: Include request headers (sensitive headers like Authorization and Cookie are automatically hidden).WithResponseBody: Include the response body (limited to ResponseBodyMaxSize, default 64KB).WithResponseHeader: Include response headers (sensitive headers like Set-Cookie are automatically hidden).WithSpanID: Include the OpenTelemetry Span ID.WithTraceID: Include the OpenTelemetry Trace ID.WithClientIP: Include the client IP address.WithCustomMessage: A function func(c *echo.Context, err error) string to override the default log message.Filters: A slice of Filter functions to skip logging for specific requests.config := slogecho.Config{
DefaultLevel: slog.LevelInfo,
ClientErrorLevel: slog.LevelWarn,
ServerErrorLevel: slog.LevelError,
WithRequestID: true,
WithTraceID: true,
WithSpanID: true,
WithRequestBody: true,
}
middleware := slogecho.NewWithConfig(slog.Default(), config)