go gorm error 的疑惑

12 小时 21 分钟前
 aababc

这一段时间在使用 gorm 的时候有一个疑惑,在 gorm 中查询可能会返回一个 error ,我希望在出错的时候记录具体的执行的 SQL 语句是什么,但是我看 gorm 返回的 error 中并没有提供相关的获取 SQL 的信息,反而在 Logger 中可以通过 Trace 的方式来记录 Error 信息以及执行的 SQL 。

我疑惑的点在于是否应该通过 error 返回的时候携带具体执行的 SQL 语句更合适呢,这样在记录错误信息的时候也就能记录上相关出错的 SQL ,而通过 gorm 自身 Logger 的方法,就需要通过上下文关联才能定位到具体出错的 SQL 语句。

希望大家帮忙分析一下那个更合适

908 次点击
所在节点    程序员
13 条回复
Immortal
12 小时 19 分钟前
很多都是一层层 return err,等下 err 直接到 response 了
我反而有点疑惑你的思路...目前 Gorm 这样我反而觉得是最合理最方便的
aababc
12 小时 5 分钟前
@Immortal #1 我的想法是在最上层的错误处理器里统一处理 error 并记录相关的错误信息而后返回 response ,但是我再使用 gorm 的时候,我希望在查询出错的时候能记录到 error 和执行的 SQL ,但是 gorm 返回的错误并没有携带 SQL 语句,如果要记录 gorm error 时执行的 SQL 就需要使用 gorm 自己的 Logger ,这样感觉就会把错误信息切分成两部分,我的错误处理器中记录一部分,如果要查询具体的 SQL 就需要去 gorm 的日志中查看
Div1ne
11 小时 53 分钟前
你自己写一个 logger trace ,类似
func (l SQLLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
sql, rows := fc()
if err != nil {
log.Errorf("[DB Error] %v | SQL: %s | Rows: %d", err, sql, rows)
}
}

然后创建 gorm 的时候,把这个传给 config: &gorm.Config{
Logger: SQLLogger{logger.Default.LogMode(logger.Info)},
}
Div1ne
11 小时 52 分钟前
gorm 本身是为了让关注点分离:sql 打印这些属于上下文,由 trace 负责。error 只负责管理错误。
aababc
11 小时 32 分钟前
@Div1ne #3 gorm 现在都已经实现了这些功能,不需要自己再实现一遍,有基于 logger 和 slog 的两种实现
rarpainting
11 小时 30 分钟前
如果你是打算特定位置特定格式来记录,可以在 if err!=nil 里用 dryrun
如果你是在事务里的话,gorm 的 Transaction 给的太灵活了,不会有官方手段的,项目内部规定一个 error 格式就好

总体来说你的问题虽然奇怪,但是解决方法还是足够的
Immortal
11 小时 27 分钟前
@aababc #2
现代框架的方案一边都是在 Server 收到 Request 的时候,为每个 Request 创建一个 TraceID 在 Context 中,所有后续的 Log 都会打印出这个 TraceID 来追踪整个 Request 的处理情况.这样就不会出现你说的 DB 和逻辑日志分离了.

具体处理可以试试在 Gorm 的 DB 实例中注入这个 TraceID,类似
traceCtx := context.WithValue(context.Background(),traceKey,traceID)
db := db.WithContext(traceCtx)
如果日志中没有可以像 3L 说的这样注入一个自定义的 TraceLogger 在打印的时候也打印出 TraceID.
wogogoing
11 小时 23 分钟前
这应该是 Gorm 的设计理念。返回 error 是业务级别的,而 logtrace 则是日志级别的,并且支持自定义实现,这样让使用者可以更加的自由。

你可以看一下我在 go-sail 中对 trace 的自定义实现:
https://github.com/keepchen/go-sail/blob/main/lib/db/logger.go

这样,可以开发者可以自行做很多事情,灵活度更高。
aababc
11 小时 16 分钟前
@Immortal #7 咋说呢,我们现在的场景也有 traceID 上下文也能关联起来,现在使用的是 slog ,添加这个 traceID 也是挺恶心的,不单需要重新赋值 request ,还需要自己实现 slog 的 handler
Immortal
10 小时 43 分钟前
@aababc #9
不用动 Request 吧,把处理后的 slog 和 db 可以直接放在入口的 ctx 里,实际逻辑和日志用自定义的 Ctx 去处理,就能统一注入 TraceID 了?
veni2023
10 小时 11 分钟前
请求进来时 gorm 和 slog 都关联对应的请求 traceID ,不就可以了吗?这两应该都支持接入 OpenTelemetry
iyaozhen
10 小时 3 分钟前
你的想法不能算错,但有些问题你没考虑到

1. sql 是不能随便显示的,如果混在 error 中,就可能打印在日志(这在大公司是不允许的),甚至返回给用户
2. 日志打印还是有技巧的,既不能多也不能少,你应该靠业务中的日志定位问题,而不是 sql 。类似打印 request 请求体、sql 原文,是不合规的

你的诉求 gorm 应该能实现,但我没这样需求,具体没弄过
Sendya
9 小时 51 分钟前
我这是通过 gorm plugin 和 gorm hooks 增加 gorm 的执行 before,after 的流程,在里面处理想要记录的信息,虽然我这边是记录上报给 opentelemetry, 你想记录日志也是同理的,这样还不用入侵你原始业务代码

https://github.com/omalloc/contrib/blob/main/kratos/orm/gorm_tracing_callbacks.go#L81

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1164153

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX