refactor(logging): 迁移日志记录到 Zerolog 并优化错误处理
- 将日志记录库从 Logrus 替换为 Zerolog,提升性能和灵活性 - 更新各个模块的日志记录方式,确保一致性 - 优化错误处理逻辑,确保在发生错误时能够正确记录并传递错误信息 - 移除不再使用的错误处理字段,简化代码结构 - 更新相关文档以反映新的日志记录和错误处理机制
This commit is contained in:
@@ -4,73 +4,114 @@ import (
|
||||
"bytes"
|
||||
"code.hoteas.com/golang/hotime/cache"
|
||||
. "code.hoteas.com/golang/hotime/common"
|
||||
"code.hoteas.com/golang/hotime/log"
|
||||
"database/sql"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
_ "gitee.com/chunanyong/dm"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// DBError 最后一次 SQL 操作的结构化快照
|
||||
// 嵌入框架 Error 类型,与 Obj 等保持一致的错误 API(HasError/GetError/Unwrap)
|
||||
type DBError struct {
|
||||
Error
|
||||
Query string
|
||||
Data []interface{}
|
||||
}
|
||||
|
||||
// HoTimeDB 数据库操作核心结构体
|
||||
type HoTimeDB struct {
|
||||
*sql.DB
|
||||
ContextBase
|
||||
DBName string
|
||||
*cache.HoTimeCache
|
||||
Log *logrus.Logger
|
||||
Type string // 数据库类型: mysql, sqlite3, postgres
|
||||
Prefix string
|
||||
LastQuery string
|
||||
LastData []interface{}
|
||||
ConnectFunc func(err ...*Error) (*sql.DB, *sql.DB)
|
||||
LastErr *Error
|
||||
limit Slice
|
||||
*sql.Tx //事务对象
|
||||
SlaveDB *sql.DB // 从数据库
|
||||
Mode int // mode为0生产模式,1为测试模式,2为开发模式
|
||||
mu sync.RWMutex
|
||||
limitMu sync.Mutex
|
||||
Dialect Dialect // 数据库方言适配器
|
||||
testTx *sql.Tx // 测试事务:设置后所有操作都在此事务内,测试结束回滚
|
||||
testMu *sync.Mutex // 保护 testTx 单连接不被并发访问
|
||||
testLogBuf *bytes.Buffer // 测试模式:SQL 日志写入此 buffer 而非直接打印,失败时才输出
|
||||
testLogBufMu sync.Mutex // 保护 testLogBuf 并发写入
|
||||
txFailed *bool // 事务内是否有SQL出错,出错则事务必须回滚(指针确保按值传递 HoTimeDB 时状态共享)
|
||||
Log *log.Logger
|
||||
Type string // 数据库类型: mysql, sqlite3, postgres
|
||||
Prefix string
|
||||
ConnectFunc func() (*sql.DB, *sql.DB)
|
||||
lastError atomic.Pointer[DBError] // 无锁读写,始终记录最后一次 SQL 操作
|
||||
limit Slice
|
||||
*sql.Tx //事务对象
|
||||
SlaveDB *sql.DB // 从数据库
|
||||
limitMu sync.Mutex
|
||||
Dialect Dialect // 数据库方言适配器
|
||||
testTx *sql.Tx // 测试事务:设置后所有操作都在此事务内,测试结束回滚
|
||||
testMu *sync.Mutex // 保护 testTx 单连接不被并发访问
|
||||
testLogBuf *bytes.Buffer // 测试模式:SQL 日志写入此 buffer 而非直接打印,失败时才输出
|
||||
testLogBufMu sync.Mutex // 保护 testLogBuf 并发写入
|
||||
txFailed *bool // 事务内是否有SQL出错,出错则事务必须回滚(指针确保按值传递 HoTimeDB 时状态共享)
|
||||
}
|
||||
|
||||
// GetLast 返回最后一次 SQL 操作的完整快照(Query + Data + Error)
|
||||
func (that *HoTimeDB) GetLast() *DBError {
|
||||
return that.lastError.Load()
|
||||
}
|
||||
|
||||
// GetLastError 返回最后一次 SQL 的错误(nil = 成功)
|
||||
func (that *HoTimeDB) GetLastError() error {
|
||||
if e := that.lastError.Load(); e != nil {
|
||||
return e.GetError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetLastQuery 返回最后一次执行的 SQL 语句
|
||||
func (that *HoTimeDB) GetLastQuery() string {
|
||||
if e := that.lastError.Load(); e != nil {
|
||||
return e.Query
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetLastData 返回最后一次 SQL 的参数
|
||||
func (that *HoTimeDB) GetLastData() []interface{} {
|
||||
if e := that.lastError.Load(); e != nil {
|
||||
return e.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetConnect 设置数据库配置连接
|
||||
func (that *HoTimeDB) SetConnect(connect func(err ...*Error) (master, slave *sql.DB), err ...*Error) {
|
||||
func (that *HoTimeDB) SetConnect(connect func() (master, slave *sql.DB)) {
|
||||
that.ConnectFunc = connect
|
||||
_ = that.InitDb(err...)
|
||||
that.InitDb()
|
||||
}
|
||||
|
||||
// InitDb 初始化数据库连接
|
||||
func (that *HoTimeDB) InitDb(err ...*Error) *Error {
|
||||
if len(err) != 0 {
|
||||
that.LastErr = err[0]
|
||||
}
|
||||
that.DB, that.SlaveDB = that.ConnectFunc(that.LastErr)
|
||||
func (that *HoTimeDB) InitDb() {
|
||||
that.DB, that.SlaveDB = that.ConnectFunc()
|
||||
if that.DB == nil {
|
||||
return that.LastErr
|
||||
return
|
||||
}
|
||||
e := that.DB.Ping()
|
||||
|
||||
that.LastErr.SetError(e)
|
||||
if e != nil {
|
||||
dbErr := &DBError{}
|
||||
dbErr.SetError(e)
|
||||
that.lastError.Store(dbErr)
|
||||
if that.Log != nil {
|
||||
that.Log.Error().Err(e).Msg("数据库连接失败")
|
||||
}
|
||||
}
|
||||
|
||||
if that.SlaveDB != nil {
|
||||
e := that.SlaveDB.Ping()
|
||||
that.LastErr.SetError(e)
|
||||
if e != nil {
|
||||
dbErr := &DBError{}
|
||||
dbErr.SetError(e)
|
||||
that.lastError.Store(dbErr)
|
||||
if that.Log != nil {
|
||||
that.Log.Error().Err(e).Msg("从数据库连接失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据数据库类型初始化方言适配器
|
||||
if that.Dialect == nil {
|
||||
that.initDialect()
|
||||
}
|
||||
|
||||
return that.LastErr
|
||||
}
|
||||
|
||||
// initDialect 根据数据库类型初始化方言
|
||||
|
||||
Reference in New Issue
Block a user