V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
aababc
V2EX  ›  Go 编程语言

go gorm error 的疑惑

  •  
  •   aababc · 22 天前 · 1794 次点击

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

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

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

    第 1 条附言  ·  22 天前
    简单点来说,gorm 库是否应该(或者说可能)在执行 SQL 出错的时候在 error 里携带上 SQL 语句本身,这样对于错误处理来说更友好
    第 2 条附言  ·  22 天前
    我大概举个例子,比如现在拿到了一个错误 Error 1054 (42S22): Unknown column 'defs' in 'field list' 不结合上下文根本就没有办法看出来这里哪里的错误,必须要结合 gorm 中的 Trace 中的 Error 日志,所以我就在想能不能丰富一下 error 的信息
    13 条回复    2025-10-10 16:00:30 +08:00
    Immortal
        1
    Immortal  
       22 天前
    很多都是一层层 return err,等下 err 直接到 response 了
    我反而有点疑惑你的思路...目前 Gorm 这样我反而觉得是最合理最方便的
    aababc
        2
    aababc  
    OP
       22 天前
    @Immortal #1 我的想法是在最上层的错误处理器里统一处理 error 并记录相关的错误信息而后返回 response ,但是我再使用 gorm 的时候,我希望在查询出错的时候能记录到 error 和执行的 SQL ,但是 gorm 返回的错误并没有携带 SQL 语句,如果要记录 gorm error 时执行的 SQL 就需要使用 gorm 自己的 Logger ,这样感觉就会把错误信息切分成两部分,我的错误处理器中记录一部分,如果要查询具体的 SQL 就需要去 gorm 的日志中查看
    Div1ne
        3
    Div1ne  
       22 天前
    你自己写一个 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
        4
    Div1ne  
       22 天前   ❤️ 1
    gorm 本身是为了让关注点分离:sql 打印这些属于上下文,由 trace 负责。error 只负责管理错误。
    aababc
        5
    aababc  
    OP
       22 天前   ❤️ 1
    @Div1ne #3 gorm 现在都已经实现了这些功能,不需要自己再实现一遍,有基于 logger 和 slog 的两种实现
    rarpainting
        6
    rarpainting  
       22 天前
    如果你是打算特定位置特定格式来记录,可以在 if err!=nil 里用 dryrun
    如果你是在事务里的话,gorm 的 Transaction 给的太灵活了,不会有官方手段的,项目内部规定一个 error 格式就好

    总体来说你的问题虽然奇怪,但是解决方法还是足够的
    Immortal
        7
    Immortal  
       22 天前
    @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
        8
    wogogoing  
    PRO
       22 天前
    这应该是 Gorm 的设计理念。返回 error 是业务级别的,而 logtrace 则是日志级别的,并且支持自定义实现,这样让使用者可以更加的自由。

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

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

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

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

    https://github.com/omalloc/contrib/blob/main/kratos/orm/gorm_tracing_callbacks.go#L81
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   868 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 22:22 · PVG 06:22 · LAX 15:22 · JFK 18:22
    ♥ Do have faith in what you're doing.