Warning: This is a fork of https://github.com/samber/slog-gin with custom behaviour as DEXPRO requires it. You should depend on the original project.
We may try to contribute changes made in this fork at some point in time, if the changes seem worth in the main project. Until then, we use this fork to test our ideas.
Gin middleware to log http requests using slog.
See also:
- slog-multi:
slog.Handler
chaining, fanout, routing, failover, load balancing... - slog-formatter:
slog
attribute formatting - slog-sampling:
slog
sampling policy - slog-gin: Gin middleware for
slog
logger - slog-echo: Echo middleware for
slog
logger - slog-fiber: Fiber middleware for
slog
logger - slog-chi: Chi middleware for
slog
logger - slog-datadog: A
slog
handler forDatadog
- slog-rollbar: A
slog
handler forRollbar
- slog-sentry: A
slog
handler forSentry
- slog-syslog: A
slog
handler forSyslog
- slog-logstash: A
slog
handler forLogstash
- slog-fluentd: A
slog
handler forFluentd
- slog-graylog: A
slog
handler forGraylog
- slog-loki: A
slog
handler forLoki
- slog-slack: A
slog
handler forSlack
- slog-telegram: A
slog
handler forTelegram
- slog-mattermost: A
slog
handler forMattermost
- slog-microsoft-teams: A
slog
handler forMicrosoft Teams
- slog-webhook: A
slog
handler forWebhook
- slog-kafka: A
slog
handler forKafka
- slog-nats: A
slog
handler forNATS
- slog-parquet: A
slog
handler forParquet
+Object Storage
- slog-zap: A
slog
handler forZap
- slog-zerolog: A
slog
handler forZerolog
- slog-logrus: A
slog
handler forLogrus
- slog-channel: A
slog
handler for Go channels
go get github.com/samber/slog-gin
Compatibility: go >= 1.21
No breaking changes will be made to exported APIs before v2.0.0.
import (
"github.com/gin-gonic/gin"
sloggin "github.com/samber/slog-gin"
"log/slog"
)
// Create a slog logger, which:
// - Logs to stdout.
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
router := gin.New()
// Add the sloggin middleware to all routes.
// The middleware will log all requests attributes.
router.Use(sloggin.New(logger))
router.Use(gin.Recovery())
// Example pong request.
router.GET("/pong", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
router.Run(":1234")
// output:
// time=2023-10-15T20:32:58.926+02:00 level=INFO msg="Incoming request" env=production request.time=2023-10-15T20:32:58.626+02:00 request.method=GET request.path=/ request.query="" request.route="" request.ip=127.0.0.1:63932 request.length=0 response.time=2023-10-15T20:32:58.926+02:00 response.latency=100ms response.status=200 response.length=7 id=""
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
config := sloggin.Config{
WithSpanID: true,
WithTraceID: true,
}
router := gin.New()
router.Use(sloggin.NewWithConfig(logger, config))
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
config := sloggin.Config{
DefaultLevel: slog.LevelInfo,
ClientErrorLevel: slog.LevelWarn,
ServerErrorLevel: slog.LevelError,
}
router := gin.New()
router.Use(sloggin.NewWithConfig(logger, config))
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
config := sloggin.Config{
WithRequestBody: true,
WithResponseBody: true,
WithRequestHeader: true,
WithResponseHeader: true,
}
router := gin.New()
router.Use(sloggin.NewWithConfig(logger, config))
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
router := gin.New()
router.Use(
sloggin.NewWithFilters(
logger,
sloggin.Accept(func (c *gin.Context) bool {
return xxx
}),
sloggin.IgnoreStatus(401, 404),
),
)
Available filters:
- Accept / Ignore
- AcceptMethod / IgnoreMethod
- AcceptStatus / IgnoreStatus
- AcceptStatusGreaterThan / IgnoreStatusLessThan
- AcceptStatusGreaterThanOrEqual / IgnoreStatusLessThanOrEqual
- AcceptPath / IgnorePath
- AcceptPathContains / IgnorePathContains
- AcceptPathPrefix / IgnorePathPrefix
- AcceptPathSuffix / IgnorePathSuffix
- AcceptPathMatch / IgnorePathMatch
- AcceptHost / IgnoreHost
- AcceptHostContains / IgnoreHostContains
- AcceptHostPrefix / IgnoreHostPrefix
- AcceptHostSuffix / IgnoreHostSuffix
- AcceptHostMatch / IgnoreHostMatch
import (
"github.com/gin-gonic/gin"
sloggin "github.com/samber/slog-gin"
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),
),
)
router := gin.New()
// Add the sloggin middleware to all routes.
// The middleware will log all requests attributes.
router.Use(sloggin.New(logger))
router.Use(gin.Recovery())
// Example pong request.
router.GET("/pong", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
router.Run(":1234")
// output:
// time=2023-10-15T20:32:58.926+02:00 level=INFO msg="Incoming request" env=production request.time=2023-10-15T20:32:58Z request.method=GET request.path=/ request.query="" request.route="" request.ip=127.0.0.1:63932 request.length=0 response.time=2023-10-15T20:32:58Z response.latency=100ms response.status=200 response.length=7 id=""
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
router := gin.New()
// Add the sloggin middleware to all routes.
// The middleware will log all requests attributes under a "http" group.
router.Use(sloggin.New(logger.WithGroup("http")))
router.Use(gin.Recovery())
// Example pong request.
router.GET("/pong", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
router.Run(":1234")
// output:
// time=2023-10-15T20:32:58.926+02:00 level=INFO msg="Incoming request" env=production http.request.time=2023-10-15T20:32:58.626+02:00 http.request.method=GET http.request.path=/ request.query="" http.request.route="" http.request.ip=127.0.0.1:63932 http.request.length=0 http.response.time=2023-10-15T20:32:58.926+02:00 http.response.latency=100ms http.response.status=200 http.response.length=7 http.id=""
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
router := gin.New()
router.Use(gin.Recovery())
// Example pong request.
// Add the sloggin middleware to a single routes.
router.GET("/pong", sloggin.New(logger), func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
router.Run(":1234")
logger := slog.New(slog.NewTextHandler(os.Stdout, nil)).
With("environment", "production").
With("server", "gin/1.9.0").
With("server_start_time", time.Now()).
With("gin_mode", gin.EnvGinMode)
router := gin.New()
// Add the sloggin middleware to all routes.
// The middleware will log all requests attributes.
router.Use(sloggin.New(logger))
router.Use(gin.Recovery())
// Example pong request.
router.GET("/pong", func(c *gin.Context) {
// Add an attribute to a single log entry.
sloggin.AddCustomAttributes(c, slog.String("foo", "bar"))
c.String(http.StatusOK, "pong")
})
router.Run(":1234")
// output:
// time=2023-10-15T20:32:58.926+02:00 level=INFO msg="Incoming request" environment=production server=gin/1.9.0 gin_mode=release request.time=2023-10-15T20:32:58.626+02:00 request.method=GET request.path=/ request.query="" request.route="" request.ip=127.0.0.1:63932 request.length=0 response.time=2023-10-15T20:32:58.926+02:00 response.latency=100ms response.status=200 response.length=7 id="" foo=bar
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
router := gin.New()
// Add the sloggin middleware to all routes.
// The middleware will log all requests attributes.
router.Use(sloggin.New(logger))
router.Use(gin.Recovery())
// Example pong request.
router.GET("/pong", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
router.Run(":1234")
// output:
// {"time":"2023-10-15T20:32:58.926+02:00","level":"INFO","msg":"Incoming request","gin_mode":"GIN_MODE","env":"production","http":{"request":{"time":"2023-10-15T20:32:58.626+02:00","method":"GET","path":"/","query":"","route":"","ip":"127.0.0.1:55296","length":0},"response":{"time":"2023-10-15T20:32:58.926+02:00","latency":100000,"status":200,"length":7},"id":""}}
- Ping me on twitter @samuelberthe (DMs, mentions, whatever :))
- Fork the project
- Fix open issues or request new features
Don't hesitate ;)
# Install some dev dependencies
make tools
# Run tests
make test
# or
make watch-test
Give a ⭐️ if this project helped you!
Copyright © 2023 Samuel Berthe.
This project is MIT licensed.