You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中获取GORM查询(如插入)的执行时间

获取GORM查询执行时间的两种可行方案

方案一:自定义GORM Logger捕获执行时间

GORM的日志系统支持扩展,你可以实现gorm.Logger接口,在处理日志逻辑时直接拿到查询的执行耗时,再推送到外部监控系统。

示例代码:

import (
    "context"
    "time"

    "gorm.io/gorm"
    "gorm.io/gorm/logger"
)

type CustomLogger struct {
    logger.Interface
}

func (l CustomLogger) LogMode(level logger.LogLevel) logger.Interface {
    return CustomLogger{l.Interface.LogMode(level)}
}

func (l CustomLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
    // 保留原有日志输出逻辑
    l.Interface.Trace(ctx, begin, fc, err)
    
    // 计算执行耗时
    elapsed := time.Since(begin)
    sqlContent, rows := fc()
    
    // 此处将耗时、SQL语句、影响行数等信息发送到监控系统
    // 例如:sendToMonitor(elapsed, sqlContent, rows, err)
}

// 初始化DB时替换默认Logger
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
    Logger: CustomLogger{logger.Default.LogMode(logger.Info)},
})

这个方案能覆盖所有GORM操作(查询、插入、更新、删除等),无需为单个操作单独编写逻辑,适合全局监控需求。

方案二:利用Hook+上下文记录单操作耗时

如果只需要针对特定操作(比如插入)统计耗时,可以结合GORM的Before/After Hook与上下文实现:

示例代码:

import (
    "context"
    "time"

    "gorm.io/gorm"
)

// 定义上下文key,用于存储操作开始时间
type startTimeKey struct{}

// 执行插入前,通过WithContext传入开始时间
ctx := context.WithValue(context.Background(), startTimeKey{}, time.Now())
result := db.WithContext(ctx).Create(&User{Name: "test"})

// 为模型定义AfterCreate Hook
func (u *User) AfterCreate(tx *gorm.DB) error {
    if beginTime, ok := tx.ctx.Value(startTimeKey{}).(time.Time); ok {
        elapsed := time.Since(beginTime)
        // 将耗时发送到监控系统
        // sendToMonitor(elapsed, "INSERT", tx.Statement.SQL.String())
    }
    return nil
}

注意:该方案需要为每个需要统计的操作定义对应Hook(如AfterUpdate对应更新操作),适合针对性统计的场景。

补充说明

  • 两种方案获取的耗时与GORM日志中输出的毫秒级数据完全一致
  • 方案一适合全局统一统计所有SQL操作耗时,方案二更灵活,可聚焦特定操作

内容的提问来源于stack exchange,提问作者mehrdad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:12:48