177 lines
5.1 KiB
Go
177 lines
5.1 KiB
Go
package database
|
||
|
||
import (
|
||
"context"
|
||
"database/sql/driver"
|
||
"time"
|
||
|
||
"github.com/gogf/gf/v2/database/gdb"
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
"nl-video-api/utility/logger"
|
||
)
|
||
|
||
// SQLHook SQL执行钩子,用于记录SQL日志和错误
|
||
type SQLHook struct{}
|
||
|
||
// BeforeQuery 查询前钩子
|
||
func (h *SQLHook) BeforeQuery(ctx context.Context, link gdb.Link, sql string, args []interface{}) (context.Context, error) {
|
||
// 记录查询开始时间
|
||
ctx = context.WithValue(ctx, "sql_start_time", time.Now())
|
||
return ctx, nil
|
||
}
|
||
|
||
// AfterQuery 查询后钩子
|
||
func (h *SQLHook) AfterQuery(ctx context.Context, link gdb.Link, sql string, args []interface{}, result gdb.Result, err error) error {
|
||
// 计算执行时间
|
||
startTime, ok := ctx.Value("sql_start_time").(time.Time)
|
||
var duration time.Duration
|
||
if ok {
|
||
duration = time.Since(startTime)
|
||
}
|
||
|
||
// 获取影响行数
|
||
var rowsAffected int64
|
||
if result != nil {
|
||
rowsAffected = int64(result.Len())
|
||
}
|
||
|
||
if err != nil {
|
||
// 记录SQL执行错误
|
||
logger.LogDatabaseError(ctx, "Query", sql, err)
|
||
logger.LogError(ctx, "SQL查询失败 | SQL: %s | Args: %v | Duration: %v | Error: %v",
|
||
sql, args, duration, err)
|
||
} else {
|
||
// 记录SQL执行成功
|
||
logger.LogDatabaseQuery(ctx, sql, args, duration, rowsAffected)
|
||
}
|
||
|
||
return err
|
||
}
|
||
|
||
// BeforeExec 执行前钩子
|
||
func (h *SQLHook) BeforeExec(ctx context.Context, link gdb.Link, sql string, args []interface{}) (context.Context, error) {
|
||
// 记录执行开始时间
|
||
ctx = context.WithValue(ctx, "sql_start_time", time.Now())
|
||
return ctx, nil
|
||
}
|
||
|
||
// AfterExec 执行后钩子
|
||
func (h *SQLHook) AfterExec(ctx context.Context, link gdb.Link, sql string, args []interface{}, result driver.Result, err error) error {
|
||
// 计算执行时间
|
||
startTime, ok := ctx.Value("sql_start_time").(time.Time)
|
||
var duration time.Duration
|
||
if ok {
|
||
duration = time.Since(startTime)
|
||
}
|
||
|
||
// 获取影响行数
|
||
var rowsAffected int64
|
||
if result != nil {
|
||
if affected, e := result.RowsAffected(); e == nil {
|
||
rowsAffected = affected
|
||
}
|
||
}
|
||
|
||
if err != nil {
|
||
// 记录SQL执行错误
|
||
logger.LogDatabaseError(ctx, "Exec", sql, err)
|
||
logger.LogError(ctx, "SQL执行失败 | SQL: %s | Args: %v | Duration: %v | Error: %v",
|
||
sql, args, duration, err)
|
||
} else {
|
||
// 记录SQL执行成功
|
||
logger.LogDatabaseQuery(ctx, sql, args, duration, rowsAffected)
|
||
}
|
||
|
||
return err
|
||
}
|
||
|
||
// BeforePrepare 预处理前钩子
|
||
func (h *SQLHook) BeforePrepare(ctx context.Context, link gdb.Link, sql string) (context.Context, error) {
|
||
return ctx, nil
|
||
}
|
||
|
||
// AfterPrepare 预处理后钩子
|
||
func (h *SQLHook) AfterPrepare(ctx context.Context, link gdb.Link, sql string, stmt *gdb.Stmt, err error) error {
|
||
if err != nil {
|
||
logger.LogDatabaseError(ctx, "Prepare", sql, err)
|
||
logger.LogError(ctx, "SQL预处理失败 | SQL: %s | Error: %v", sql, err)
|
||
}
|
||
return err
|
||
}
|
||
|
||
// BeforeCommit 提交前钩子
|
||
func (h *SQLHook) BeforeCommit(ctx context.Context, link gdb.Link) (context.Context, error) {
|
||
logger.LogSQL(ctx, "事务提交开始")
|
||
return ctx, nil
|
||
}
|
||
|
||
// AfterCommit 提交后钩子
|
||
func (h *SQLHook) AfterCommit(ctx context.Context, link gdb.Link, err error) error {
|
||
if err != nil {
|
||
logger.LogError(ctx, "事务提交失败 | Error: %v", err)
|
||
} else {
|
||
logger.LogSQL(ctx, "事务提交成功")
|
||
}
|
||
return err
|
||
}
|
||
|
||
// BeforeRollback 回滚前钩子
|
||
func (h *SQLHook) BeforeRollback(ctx context.Context, link gdb.Link) (context.Context, error) {
|
||
logger.LogSQL(ctx, "事务回滚开始")
|
||
return ctx, nil
|
||
}
|
||
|
||
// AfterRollback 回滚后钩子
|
||
func (h *SQLHook) AfterRollback(ctx context.Context, link gdb.Link, err error) error {
|
||
if err != nil {
|
||
logger.LogError(ctx, "事务回滚失败 | Error: %v", err)
|
||
} else {
|
||
logger.LogSQL(ctx, "事务回滚成功")
|
||
}
|
||
return err
|
||
}
|
||
|
||
// InitDatabaseHook 初始化数据库钩子
|
||
func InitDatabaseHook() {
|
||
// 获取默认数据库实例
|
||
db := g.DB()
|
||
|
||
// 添加SQL执行钩子
|
||
db.AddHook(&SQLHook{})
|
||
|
||
logger.LogInfo(context.Background(), "数据库钩子初始化完成")
|
||
}
|
||
|
||
// LogDatabaseConnection 记录数据库连接日志
|
||
func LogDatabaseConnection(ctx context.Context, config gdb.ConfigNode, err error) {
|
||
if err != nil {
|
||
logger.LogError(ctx, "数据库连接失败 | Host: %s | Database: %s | Error: %v",
|
||
config.Host, config.Name, err)
|
||
} else {
|
||
logger.LogInfo(ctx, "数据库连接成功 | Host: %s | Database: %s",
|
||
config.Host, config.Name)
|
||
}
|
||
}
|
||
|
||
// LogDatabasePing 记录数据库ping日志
|
||
func LogDatabasePing(ctx context.Context, duration time.Duration, err error) {
|
||
if err != nil {
|
||
logger.LogError(ctx, "数据库ping失败 | Duration: %v | Error: %v", duration, err)
|
||
} else {
|
||
logger.LogInfo(ctx, "数据库ping成功 | Duration: %v", duration)
|
||
}
|
||
}
|
||
|
||
// LogTransactionStart 记录事务开始日志
|
||
func LogTransactionStart(ctx context.Context, txId string) {
|
||
logger.LogSQL(ctx, "事务开始 | TxID: %s", txId)
|
||
}
|
||
|
||
// LogTransactionEnd 记录事务结束日志
|
||
func LogTransactionEnd(ctx context.Context, txId string, success bool, duration time.Duration) {
|
||
if success {
|
||
logger.LogSQL(ctx, "事务结束(成功) | TxID: %s | Duration: %v", txId, duration)
|
||
} else {
|
||
logger.LogError(ctx, "事务结束(失败) | TxID: %s | Duration: %v", txId, duration)
|
||
}
|
||
} |