参考 gorm 文档:https://gorm.io/zh_CN/docs/logger.html
Gorm
有一个 默认 logger 实现,默认情况下,它会打印慢 SQL 和错误。如果想要全部或部分打印 SQL 的话可以通过设置日志级别和使用 Logger
接口来实现自定义处理。以下是一些方法来实现这个功能。
1. 使用 Debug 方法
GORM 提供了一个 Debug
方法,可以在链式调用中打印出生成的 SQL 语句和执行时间。
一般用于开发或者是线上排查某个问题时使用。
Debug 单个操作时,会将当前操作的 log 级别调整为
logger.Info
代码示例:
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID int
Name string
}
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
var users []User
// 使用 Debug() 方法
db.Debug().Where("name = ?", "John").Find(&users)
fmt.Println(users)
}
2. 全局设置日志级别
在 GORM 配置中设置 Logger
,可以全局打印 SQL 语句。可以使用 gorm/logger
包来设置日志级别。
GORM 定义了这些日志级别:
Silent
:不打印任何日志。Error
:仅打印错误日志。Warn
:打印警告和错误日志。Info
:打印所有日志(包括 SQL 语句和运行时间)
代码示例:
package main
import (
"log"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type User struct {
ID int
Name string
}
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(log.Writer(), "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // 日志级别
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误
Colorful: true, // 启用彩色打印
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic("failed to connect database")
}
var users []User
db.Where("name = ?", "John").Find(&users)
fmt.Println(users)
}
3. 自定义 Logger
如果需要更复杂的日志逻辑,可以实现 gorm/logger
包中的 Interface
接口,来自定义 Logger。
参考 GORM 的 默认 logger 来定义您自己的 logger
代码示例:
package main
import (
"log"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/utils"
)
type CustomLogger struct {
logger.Interface
}
func (c *CustomLogger) Info(ctx context.Context, msg string, data ...interface{}) {
log.Printf("[INFO] "+msg, data...)
}
func (c *CustomLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
log.Printf("[WARN] "+msg, data...)
}
func (c *CustomLogger) Error(ctx context.Context, msg string, data ...interface{}) {
log.Printf("[ERROR] "+msg, data...)
}
// 追踪并输出 sql 的详细信息:sql 语句、绑定的参数、执行时间等。
func (c *CustomLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
elapsed := time.Since(begin)
sql, rows := fc()
log.Printf("[SQL] %s [rows:%d] [elapsed:%s] [error:%v]\n", sql, rows, elapsed, err)
}
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
customLogger := &CustomLogger{}
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: customLogger,
})
if err != nil {
panic("failed to connect database")
}
var users []User
db.Where("name = ?", "John").Find(&users)
fmt.Println(users)
}
4. 总结
通过上述方法,可以在 GORM 中实现 SQL 语句的打印,从而方便调试和监控数据库操作。根据具体需求,可以选择使用 Debug
模式、全局设置日志级别或者自定义 Logger
。