gorm/gin: 传递gin.context给gorm,记录异常发生时的信息
一,安装第三方库:
$ go get -u gorm.io/gorm
go: added github.com/jinzhu/inflection v1.0.0
go: added github.com/jinzhu/now v1.1.5
go: added gorm.io/gorm v1.25.12
$ go get -u gorm.io/driver/mysql
go: added filippo.io/edwards25519 v1.1.0
go: added github.com/go-sql-driver/mysql v1.8.1
go: added gorm.io/driver/mysql v1.5.7
二,代码:
1,global/dblink.go
package global
import (
"fmt"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"runtime"
"runtime/debug"
"time"
)
var (
DBLink *gorm.DB
)
func SetupDBLink() (error) {
var err error
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s&parseTime=%t&loc=Local",
"root",
"rootpassword",
"127.0.0.1:3306",
"gysy",
"utf8",
true, )
DBLink, err = gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Info),})
if err != nil {
return err
}
sqlDB, _ := DBLink.DB()
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量
sqlDB.SetMaxOpenConns(30)
// SetConnMaxLifetime 设置了连接可复用的最大时间
sqlDB.SetConnMaxLifetime(time.Hour)
//"query:before"
DBLink.Callback().Create().Register("create:before", func(db *gorm.DB) {
fmt.Println("==================create:create======================")
c, ok := db.Statement.Context.(*gin.Context)
if ok {
fmt.Println("转换成功")
}
url:=c.Request.URL.String()
fmt.Println("url:",url)
timeStr := time.Now().Format("2006-01-02 15:04:05")
fmt.Println("当前时间:", timeStr)
fmt.Println("当前访问path:", c.FullPath())
fmt.Println("当前完整地址:", c.Request.URL.String())
fmt.Println("当前协议:", c.Request.Proto)
fmt.Println("当前get参数:",GetAllGetParams(c))
fmt.Println("当前post参数:",GetAllPostParams(c))
fmt.Println("当前访问方法:", c.Request.Method)
fmt.Println("当前访问Host:", c.Request.Host)
fmt.Println("当前IP:",c.ClientIP())
fmt.Println("当前浏览器:",c.Request.UserAgent())
if db.Error == nil { // 只打印成功的查询
//db.Statement.SQL.
sql, values := db.Statement.SQL.String(), db.Statement.Vars
fmt.Println("sql:",sql)
fmt.Println("values:",values)
} else {
var pc [1]uintptr
runtime.Callers(4, pc[:]) // 获取调用者的位置,4 表示跳过 logError 和当前函数本身
f := runtime.FuncForPC(pc[0])
file, line := f.FileLine(pc[0])
fmt.Printf("Error at %s:%d - %v\n", file, line, db.Error)
sql, values := db.Statement.SQL.String(), db.Statement.Vars
fmt.Println("sql:",sql)
fmt.Println("values:",values)
fmt.Println("dblink中:查询前发生错误:",db.Error)
fmt.Println("dblink:stack打印开始")
fmt.Println(string(debug.Stack()))
fmt.Println("dblink:stack打印结束")
}
})
DBLink.Callback().Query().Register("query:before", func(db *gorm.DB) {
fmt.Println("==================query:before======================")
c, ok := db.Statement.Context.(*gin.Context)
if ok {
fmt.Println("转换成功")
}
url:=c.Request.URL.String()
fmt.Println("url:",url)
timeStr := time.Now().Format("2006-01-02 15:04:05")
fmt.Println("当前时间:", timeStr)
fmt.Println("当前访问path:", c.FullPath())
fmt.Println("当前完整地址:", c.Request.URL.String())
fmt.Println("当前协议:", c.Request.Proto)
fmt.Println("当前get参数:",GetAllGetParams(c))
fmt.Println("当前post参数:",GetAllPostParams(c))
fmt.Println("当前访问方法:", c.Request.Method)
fmt.Println("当前访问Host:", c.Request.Host)
fmt.Println("当前IP:",c.ClientIP())
fmt.Println("当前浏览器:",c.Request.UserAgent())
fmt.Println("报错:",db.Error)
if db.Error == nil { // 只打印成功的查询
//db.Statement.SQL.
sql, values := db.Statement.SQL.String(), db.Statement.Vars
fmt.Println("sql:",sql)
fmt.Println("values:",values)
} else {
var pc [1]uintptr
runtime.Callers(4, pc[:]) // 获取调用者的位置,4 表示跳过 logError 和当前函数本身
f := runtime.FuncForPC(pc[0])
file, line := f.FileLine(pc[0])
fmt.Printf("Error at %s:%d - %v\n", file, line, db.Error)
sql, values := db.Statement.SQL.String(), db.Statement.Vars
fmt.Println("sql:",sql)
fmt.Println("values:",values)
fmt.Println("dblink中:查询前发生错误:",db.Error)
fmt.Println("dblink:stack打印开始")
fmt.Println(string(debug.Stack()))
fmt.Println("dblink:stack打印结束")
}
})
DBLink.Callback().Update().Register("update:before", func(db *gorm.DB) {
fmt.Println("==================update:before======================")
c, ok := db.Statement.Context.(*gin.Context)
if ok {
fmt.Println("转换成功")
}
url:=c.Request.URL.String()
fmt.Println("url:",url)
timeStr := time.Now().Format("2006-01-02 15:04:05")
fmt.Println("当前时间:", timeStr)
fmt.Println("当前访问path:", c.FullPath())
fmt.Println("当前完整地址:", c.Request.URL.String())
fmt.Println("当前协议:", c.Request.Proto)
fmt.Println("当前get参数:",GetAllGetParams(c))
fmt.Println("当前post参数:",GetAllPostParams(c))
fmt.Println("当前访问方法:", c.Request.Method)
fmt.Println("当前访问Host:", c.Request.Host)
fmt.Println("当前IP:",c.ClientIP())
fmt.Println("当前浏览器:",c.Request.UserAgent())
if db.Error == nil { // 只打印成功的查询
//db.Statement.SQL.
sql, values := db.Statement.SQL.String(), db.Statement.Vars
fmt.Println("sql:",sql)
fmt.Println("values:",values)
} else {
var pc [1]uintptr
runtime.Callers(4, pc[:]) // 获取调用者的位置,4 表示跳过 logError 和当前函数本身
f := runtime.FuncForPC(pc[0])
file, line := f.FileLine(pc[0])
fmt.Printf("Error at %s:%d - %v\n", file, line, db.Error)
sql, values := db.Statement.SQL.String(), db.Statement.Vars
fmt.Println("sql:",sql)
fmt.Println("values:",values)
fmt.Println("dblink中:查询前发生错误:",db.Error)
fmt.Println("dblink:stack打印开始")
fmt.Println(string(debug.Stack()))
fmt.Println("dblink:stack打印结束")
}
})
return nil
}
2,service/articleService.go
注意用 withContext传递*gin.Context
package service
import (
"fmt"
"github.com/gin-gonic/gin"
"imagebank/global"
"imagebank/model"
)
//select一个article
func GetOneArticleById(c *gin.Context,id int) (*model.ArticleModel, error) {
fields := []string{"id", "title","demo","content1"}
articleOne:=&model.ArticleModel{}
err := global.DBLink.WithContext(c).Select(fields).Where("id=?",id).First(&articleOne).Error
if (err != nil) {
fmt.Println("service:发生了错误:")
fmt.Println(err)
return nil,err
} else {
return articleOne,nil
}
}
//add一个article
func InsertOneArticle(c *gin.Context,articleOne model.ArticleModel) (uint,error) {
result := global.DBLink.WithContext(c).Create(&articleOne)
return articleOne.Id,result.Error
}
三,测试效果:
新加一行数据:
转换成功
url: /image/add
当前时间: 2025-02-02 12:32:46
当前访问path: /image/add
当前完整地址: /image/add
当前协议: HTTP/1.1
当前get参数:
当前post参数: key:cid,value:123
key:title,value:12
当前访问方法: POST
当前访问Host: 192.168.219.3:8080
当前IP: 192.168.219.1
当前浏览器: PostmanRuntime/7.43.0
Error at /data/goapp/imagebank/service/articleService.go:28 - Error 1062 (23000): Duplicate entry '1000' for key 'zr_article.PRIMARY'
sql: INSERT INTO `zr_article` (`title`,`demo`,`content`,`id`) VALUES (?,?,?,?)
values: [aaaa bbbb cccc 1000]
dblink中:查询前发生错误: Error 1062 (23000): Duplicate entry '1000' for key 'zr_article.PRIMARY'
dblink:stack打印开始
12:32:46 app | goroutine 6 [running]:
runtime/debug.Stack()
/usr/local/soft/go/src/runtime/debug/stack.go:26 +0x5e
imagebank/global.SetupDBLink.func1(0xc000277ef0)
/data/goapp/imagebank/global/dblink.go:82 +0xaab
gorm.io/gorm.(*processor).Execute(0xc0002426e0, 0xc000277b00?)
/data/gopath/pkg/mod/gorm.io/gorm@v1.25.12/callbacks.go:130 +0x3cb
gorm.io/gorm.(*DB).Create(0xc000162eb8?, {0x983d60, 0xc00024ab80})
/data/gopath/pkg/mod/gorm.io/gorm@v1.25.12/finisher_api.go:24 +0xa8
imagebank/service.InsertOneArticle(0xc000146600, {0x3e8, {0xa27a30, 0x4}, {0xa27a34, 0x4}, {0xa27a38, 0x4}})
/data/goapp/imagebank/service/articleService.go:27 +0xbc
imagebank/controller.(*ImageController).Add(0xc000162fe0?, 0xc000146600)
/data/goapp/imagebank/controller/ImageController.go:47 +0x90
github.com/gin-gonic/gin.(*Context).Next(0xc000146600)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x2b
imagebank/routes.Routes.AccessLog.func2(0xc000146600)
/data/goapp/imagebank/middleware/accesslog.go:84 +0x2ba
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
imagebank/routes.Recover(0xc000146600)
/data/goapp/imagebank/routes/routes.go:87 +0x5c
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
github.com/gin-gonic/gin.CustomRecoveryWithWriter.func1(0xc000146600)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/recovery.go:102 +0x6f
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
github.com/gin-gonic/gin.LoggerWithConfig.func1(0xc000146600)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/logger.go:249 +0xe5
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0xc0000a6000, 0xc000146600)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x892
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc0000a6000, {0xb1c030, 0xc00019e1c0}, 0xc0000c4000)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x1b2
net/http.serverHandler.ServeHTTP({0xb19f30?}, {0xb1c030?, 0xc00019e1c0?}, 0x6?)
/usr/local/soft/go/src/net/http/server.go:3210 +0x8e
net/http.(*conn).serve(0xc0000be000, {0xb1d070, 0xc000096390})
/usr/local/soft/go/src/net/http/server.go:2092 +0x5d0
created by net/http.(*Server).Serve in goroutine 1
/usr/local/soft/go/src/net/http/server.go:3360 +0x485
12:32:46 app | dblink:stack打印结束
查询数据:
12:29:33 app | ==================query:before======================
转换成功
url: /image/detail?id=123
当前时间: 2025-02-02 12:29:33
当前访问path: /image/detail
当前完整地址: /image/detail?id=123
当前协议: HTTP/1.1
当前get参数: key:id,value:123
当前post参数:
当前访问方法: GET
当前访问Host: 192.168.219.3:8080
当前IP: 192.168.219.1
当前浏览器: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
报错: Error 1054 (42S22): Unknown column 'content1' in 'field list'
Error at /data/goapp/imagebank/service/articleService.go:14 - Error 1054 (42S22): Unknown column 'content1' in 'field list'
sql: SELECT `id`,`title`,`demo`,content1 FROM `zr_article` WHERE id=? ORDER BY `zr_article`.`id` LIMIT ?
values: [21 1]
dblink中:查询前发生错误: Error 1054 (42S22): Unknown column 'content1' in 'field list'
dblink:stack打印开始
12:29:33 app | goroutine 5 [running]:
runtime/debug.Stack()
/usr/local/soft/go/src/runtime/debug/stack.go:26 +0x5e
imagebank/global.SetupDBLink.func1(0xc0000942d0)
/data/goapp/imagebank/global/dblink.go:124 +0xb2b
gorm.io/gorm.(*processor).Execute(0xc000242730, 0xc000277b00?)
/data/gopath/pkg/mod/gorm.io/gorm@v1.25.12/callbacks.go:130 +0x3cb
gorm.io/gorm.(*DB).First(0xc000094240?, {0x9608a0, 0xc00005a010}, {0x0, 0x0, 0x0})
/data/gopath/pkg/mod/gorm.io/gorm@v1.25.12/finisher_api.go:129 +0x1b2
imagebank/service.GetOneArticleById(0xc00009a500, 0x15)
/data/goapp/imagebank/service/articleService.go:14 +0x1b1
imagebank/controller.(*ImageController).Detail(0xc00015efe0?, 0xc00009a500)
/data/goapp/imagebank/controller/ImageController.go:79 +0x27
github.com/gin-gonic/gin.(*Context).Next(0xc00009a500)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185 +0x2b
imagebank/routes.Routes.AccessLog.func2(0xc00009a500)
/data/goapp/imagebank/middleware/accesslog.go:84 +0x2ba
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
imagebank/routes.Recover(0xc00009a500)
/data/goapp/imagebank/routes/routes.go:87 +0x5c
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
github.com/gin-gonic/gin.CustomRecoveryWithWriter.func1(0xc00009a500)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/recovery.go:102 +0x6f
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
github.com/gin-gonic/gin.LoggerWithConfig.func1(0xc00009a500)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/logger.go:249 +0xe5
github.com/gin-gonic/gin.(*Context).Next(...)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go:185
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0xc000167040, 0xc00009a500)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:633 +0x892
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc000167040, {0xb1bb90, 0xc0000b0000}, 0xc00009e000)
/data/gopath/pkg/mod/github.com/gin-gonic/gin@v1.10.0/gin.go:589 +0x1b2
net/http.serverHandler.ServeHTTP({0xc0000940c0?}, {0xb1bb90?, 0xc0000b0000?}, 0x6?)
/usr/local/soft/go/src/net/http/server.go:3210 +0x8e
net/http.(*conn).serve(0xc000096000, {0xb1cbd0, 0xc0002d6120})
/usr/local/soft/go/src/net/http/server.go:2092 +0x5d0
created by net/http.(*Server).Serve in goroutine 1
/usr/local/soft/go/src/net/http/server.go:3360 +0x485
dblink:stack打印结束
浙公网安备 33010602011771号