slog-gorm provides a slog adapter, highly configurable, for gorm logger
to have homogeneous logs between your application / script and gorm.
- compatible with any
slog.Handler, which allows you to keep control on the format of your logs. - can define a threshold to identify and log the slow queries.
- can log all SQL messages or just the errors if you prefer.
- can define a custom
slog.Levelfor errors, slow queries or the other logs. - can log context values with each Gorm log.
golang >= 1.21
import (
"log/slog"
"os"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
slogGorm "github.com/orandin/slog-gorm"
)
// Create an slog-gorm instance
gormLogger := slogGorm.New() // use slog.Default() by default
// GORM: Globally mode
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
Logger: gormLogger,
})
// GORM: Continuous session mode
tx := db.Session(&Session{Logger: gormLogger})
tx.First(&user)
tx.Model(&user).Update("Age", 18)The following example shows you how to use a specific slog.Logger with slog-gorm:
// With your slog.Logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
// Also, you can set specific attributes to distinguish between your application logs and gorm logs
// logger = logger.With(slog.String("log_type", "database"))
gormLogger := slogGorm.New(
// slogGorm.WithLogger(logger), // Deprecated since v1.3.0, use `slogGorm.WithHandler(...)` instead.
slogGorm.WithHandler(logger.Handler()), // since v1.3.0
slogGorm.WithTraceAll(), // trace all messages
slogGorm.SetLogLevel(DefaultLogType, slog.Level(32)), // Define the default logging level
)As some loggers (e.g. syslog) have their own logging levels, slog-gorm lets you
use them to ensure the consistency of your logs and make them easier to understand.
You can set the logging level for these log types:
| Type | Description | Default |
|---|---|---|
slogGorm.ErrorLogType |
For SQL errors | slog.LevelError |
slogGorm.SlowQueryLogType |
For slow queries | slog.LevelWarn |
slogGorm.DefaultLogType |
For other messages (default level) | slog.LevelInfo |
Example:
const (
LOG_EMERG = slog.Level(0)
// ...
LOG_ERR = slog.Level(3)
LOG_WARNING = slog.Level(4)
LOG_NOTICE = slog.Level(5)
// ...
LOG_DEBUG = slog.Level(7)
)
logger := slog.New(syslogHandler)
gormLogger := slogGorm.New(
slogGorm.WithHandler(logger.Handler()),
// Set logging level for SQL errors
slogGorm.SetLogLevel(slogGorm.ErrorLogType, LOG_ERR)
// Set logging level for slow queries
slogGorm.SetLogLevel(slogGorm.SlowQueryLogType, LOG_NOTICE)
// Set logging level for other messages (default level)
slogGorm.SetLogLevel(slogGorm.DefaultLogType, LOG_DEBUG)
)customLogger := sloggorm.New(
slogGorm.WithSlowThreshold(500 * time.Millisecond), // to identify slow queries
slogGorm.WithRecordNotFoundError(), // don't ignore not found errors
slogGorm.WithSourceField("origin"), // instead of "file" (by default)
slogGorm.WithErrorField("err"), // instead of "error" (by default)
slogGorm.WithContextValue("slogAttrName1", "ctxKey"), // adds an slog.Attr if a value is found for this key in the Gorm's query context
slogGorm.WithContextFunc("slogAttrName2", func(ctx context.Context) (slog.Value, bool) {
v, ok := ctx.Value(ctxKey1).(time.Duration)
if !ok {
return slog.Value{}, false
}
return slog.DurationValue(v), true
}), // adds an slog.Attr if the given function returns an slog.Value and true
)By default, the slow queries and SQL errors are logged, but you can ignore all SQL messages with WithIgnoreTrace().
customLogger := sloggorm.New(
slogGorm.WithIgnoreTrace(), // disable the tracing of SQL queries by the logger.
)