From bc3247dc4f4a4fd52cb40fb9a68099d6318cff4a Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Tue, 5 May 2026 17:59:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=87=AA=E4=B8=BB=E5=8C=96?= =?UTF-8?q?=EF=BC=9A=E5=AE=9E=E7=8E=B0=20DB=20=E5=8C=85=E8=87=AA=E7=BB=B4?= =?UTF-8?q?=E6=8A=A4=E6=97=A5=E5=BF=97=E7=BB=93=E6=9E=84=EF=BC=8C=E5=88=A9?= =?UTF-8?q?=E7=94=A8=20log.Log=20=E8=87=AA=E5=8A=A8=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E6=9C=BA=E5=88=B6=20(by=20AI)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Base.go | 2 +- CHANGELOG.md | 7 +++++++ DB.go | 16 +++++++-------- DB_test.go | 4 ++-- Log.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Result.go | 7 +++---- go.mod | 12 +++++++----- go.sum | 12 ++++++++---- 8 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 Log.go diff --git a/Base.go b/Base.go index 158b01a..b0f21d0 100644 --- a/Base.go +++ b/Base.go @@ -97,7 +97,7 @@ func flatArgs(args []any) []any { argValue := reflect.ValueOf(arg) kind := argValue.Kind() if kind == reflect.Map || kind == reflect.Struct || (kind == reflect.Slice && argValue.Type().Elem().Kind() != reflect.Uint8) { - args[i] = cast.MustToJSON(arg) + args[i] = cast.As(cast.ToJSON(arg)) } } return args diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fd7466..5bf620f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # 变更记录 - @go/db +## [1.0.5] - 2026-05-05 +### 优化 +- **日志自主化**: + - 将数据库日志逻辑从 `log` 包迁移至 `db` 包,实现日志格式与业务逻辑的深度绑定。 + - 自定义 `DBLog` 结构,利用 `log.GetEntry[DBLog]()` 对象池加速,并支持完整的错误堆栈捕获。 + - 接入 `log.Log` 的自动填充能力,精简元数据维护逻辑。 + ## [1.0.4] - 2026-05-04 ### 优化 - **日志增强**:升级 `apigo.cc/go/log` 至 v1.0.1,并重构数据库日志逻辑,利用新版 `log.DB` API 直接支持错误字段和调用栈捕获,提升排障效率。 diff --git a/DB.go b/DB.go index 2e18679..2e848b1 100644 --- a/DB.go +++ b/DB.go @@ -237,15 +237,15 @@ type dbLogger struct { } func (dl *dbLogger) LogError(errStr string) { - dl.logger.DB(dl.config.Type, dl.config.Dsn(), "", nil, 0, errStr) + dl.LogDB("", nil, 0, errors.New(errStr)) } func (dl *dbLogger) LogQuery(query string, args []any, usedTime float32) { - dl.logger.DB(dl.config.Type, dl.config.Dsn(), query, args, usedTime) + dl.LogDB(query, args, usedTime, nil) } func (dl *dbLogger) LogQueryError(errStr string, query string, args []any, usedTime float32) { - dl.logger.DB(dl.config.Type, dl.config.Dsn(), query, args, usedTime, errStr) + dl.LogDB(query, args, usedTime, errors.New(errStr)) } var dbConfigs = make(map[string]*Config) @@ -378,7 +378,7 @@ func getDB(name string, logger *log.Logger, useCache bool) *DB { if n == 0 { once.Do(func() { dbConfigs1 := make(map[string]*Config) - if err := config.Load("db", &dbConfigs1); err == nil { + if err := config.Load(&dbConfigs1, "db"); err == nil { for k, v := range dbConfigs1 { if v.Host != "" { dbConfigsLock.Lock() @@ -390,7 +390,7 @@ func getDB(name string, logger *log.Logger, useCache bool) *DB { logger.Error(err.Error()) } dbConfigs2 := make(map[string]string) - if err := config.Load("db", &dbConfigs2); err == nil { + if err := config.Load(&dbConfigs2, "db"); err == nil { for k, v := range dbConfigs2 { if strings.Contains(v, "://") { v2 := new(Config) @@ -434,7 +434,7 @@ func getDB(name string, logger *log.Logger, useCache bool) *DB { } if conf.SSL != "" && len(dbSSLs) == 0 { - _ = config.Load("dbssl", &dbSSLs) + _ = config.Load(&dbSSLs, "dbssl") } if conf.SSL != "" && dbSSLs[conf.SSL] == nil { @@ -467,7 +467,7 @@ func getDB(name string, logger *log.Logger, useCache bool) *DB { conn, err := getPool(conf) if err != nil { - logger.DB(conf.Type, conf.Dsn(), "", nil, 0, err.Error()) + LogDB(logger, conf, "", nil, 0, err) return &DB{conn: nil, QuoteTag: "\"", Error: err} } @@ -483,7 +483,7 @@ func getDB(name string, logger *log.Logger, useCache bool) *DB { for _, host := range conf.ReadonlyHosts { conn, err := getPoolForHost(conf, host) if err != nil { - logger.DB(conf.Type, conf.Dsn(), "", nil, 0, err.Error()) + LogDB(logger, conf, "", nil, 0, err) } else { readonlyConnections = append(readonlyConnections, conn) } diff --git a/DB_test.go b/DB_test.go index f2a641f..71024e1 100644 --- a/DB_test.go +++ b/DB_test.go @@ -409,7 +409,7 @@ func TestTransaction(t *testing.T) { } n2 := countConnection() - fmt.Println("# connection count", n1, n2, cast.MustToJSON(dbInst.GetOriginDB().Stats()), ".") + fmt.Println("# connection count", n1, n2, cast.As(cast.ToJSON(dbInst.GetOriginDB().Stats())), ".") } func countConnection() int { @@ -480,5 +480,5 @@ func BenchmarkForPoolParallel(b *testing.B) { b.Log("OpenConnections", dbInst.GetOriginDB().Stats().OpenConnections) n2 := countConnection() - fmt.Println("# connection count", n1, n2, cast.MustToJSON(dbInst.GetOriginDB().Stats()), ".") + fmt.Println("# connection count", n1, n2, cast.As(cast.ToJSON(dbInst.GetOriginDB().Stats())), ".") } diff --git a/Log.go b/Log.go new file mode 100644 index 0000000..31208d3 --- /dev/null +++ b/Log.go @@ -0,0 +1,55 @@ +package db + +import ( + "apigo.cc/go/cast" + "apigo.cc/go/log" +) + +type DBLog struct { + log.BaseLog + DbType string + Dsn string + Query string + QueryArgs string + UsedTime float32 + Error string + CallStacks []string +} + +func (dl *dbLogger) LogDB(query string, args []any, usedTime float32, err error, extra ...any) { + LogDB(dl.logger, dl.config, query, args, usedTime, err, extra...) +} + +func LogDB(logger *log.Logger, conf *Config, query string, args []any, usedTime float32, err error, extra ...any) { + if logger == nil { + return + } + + logType := log.LogTypeDb + level := log.INFO + var e string + if err != nil { + logType = log.LogTypeDbError + level = log.ERROR + e = err.Error() + } + + if logger.CheckLevel(level) { + entry := log.GetEntry[DBLog]() + // 仅关注业务字段,LogType 手动赋值,基础字段由 logger.Log 自动填充 + entry.LogType = logType + entry.DbType = conf.Type + entry.Dsn = conf.Dsn() + entry.Query = query + entry.QueryArgs = cast.To[string](args) + entry.UsedTime = usedTime + if e != "" { + entry.Error = e + entry.CallStacks = logger.GetCallStacks() + } + if len(extra) > 0 { + cast.FillMap(&entry.Extra, extra) + } + logger.Log(entry) + } +} diff --git a/Result.go b/Result.go index 86b97da..11c8981 100644 --- a/Result.go +++ b/Result.go @@ -10,7 +10,6 @@ import ( "time" "apigo.cc/go/cast" - "apigo.cc/go/convert" "github.com/mitchellh/mapstructure" ) @@ -224,7 +223,7 @@ func (r *QueryResult) ToKV(target any) error { } for _, item := range list { newKey := reflect.ValueOf(reflect.New(t.Key()).Interface()).Elem() - convert.To(item[colTypes[0].Name()], newKey.Addr().Interface()) + cast.Convert(newKey.Addr().Interface(), item[colTypes[0].Name()]) newValue := v.MapIndex(newKey) isNew := false @@ -439,10 +438,10 @@ func (r *QueryResult) makeResults(results any, rows *sql.Rows) error { if s != "" { _ = json.Unmarshal([]byte(s), storedValue) } - convert.To(storedValue, convertedObject.Interface()) + cast.Convert(convertedObject.Interface(), storedValue) field.Set(convertedObject.Elem()) } else { - convert.To(val.Interface(), convertedObject.Interface()) + cast.Convert(convertedObject.Interface(), val.Interface()) } } } else if field.Type().AssignableTo(val.Type()) { diff --git a/go.mod b/go.mod index b2f5446..3ebc8ab 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module apigo.cc/go/db go 1.25.0 require ( - apigo.cc/go/cast v1.1.1 - apigo.cc/go/config v1.0.4 - apigo.cc/go/convert v1.0.4 + apigo.cc/go/cast v1.2.6 + apigo.cc/go/config v1.0.5 apigo.cc/go/crypto v1.0.4 apigo.cc/go/id v1.0.4 - apigo.cc/go/log v1.0.1 + apigo.cc/go/log v1.1.1 apigo.cc/go/rand v1.0.4 + apigo.cc/go/redis v1.0.3 apigo.cc/go/safe v1.0.4 apigo.cc/go/shell v1.0.4 github.com/go-sql-driver/mysql v1.10.0 @@ -19,10 +19,12 @@ require ( ) require ( + apigo.cc/go/convert v1.0.4 // indirect apigo.cc/go/encoding v1.0.4 // indirect - apigo.cc/go/file v1.0.4 // indirect + apigo.cc/go/file v1.0.5 // indirect filippo.io/edwards25519 v1.2.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/gomodule/redigo v1.9.3 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect diff --git a/go.sum b/go.sum index 4a5089d..81e65a8 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -apigo.cc/go/cast v1.1.1 h1:+5pluN8g1RK2J4byr2xkfOmEdKSmy1PByOqDOHtt/Ns= -apigo.cc/go/cast v1.1.1/go.mod h1:vh9ZqISCmTUiyinkNMI/s4f045fRlDK3xC+nPWQYBzI= +apigo.cc/go/cast v1.2.6 h1:xnWiaQAGsRCrnu1p8fIFQfg5HFSc7CxR+3ItiDIDMaY= +apigo.cc/go/cast v1.2.6/go.mod h1:lGlwImiOvHxG7buyMWhFzcdvQzmSaoKbmr7bcDfUpHk= apigo.cc/go/config v1.0.4 h1:WG9zrQkqfFPkrKIL7RNvvAbbkuUBt1Av11ZP/aIfldM= apigo.cc/go/config v1.0.4/go.mod h1:obryzJiK6j7lQex/58d5eWYOGx5O5IABguqNWxyyXJo= apigo.cc/go/convert v1.0.4 h1:5+qPjC3dlPB59GnWZRlmthxcaXQtKvN+iOuiLdJ1GvQ= @@ -12,10 +12,12 @@ apigo.cc/go/file v1.0.4 h1:qCKegV7OYh7r0qc3jZjGA/aKh0vIHgmr1OEbhfEmGX8= apigo.cc/go/file v1.0.4/go.mod h1:C9gNo7386iA21OiBmuWh6CznKWlVBDFkhE4f0H0Susg= apigo.cc/go/id v1.0.4 h1:w+JSdeVit52iefIUolrh1qLEZS9XqHNKr1UygFcgv+s= apigo.cc/go/id v1.0.4/go.mod h1:kg7QuceAKtGNzGWt0+pIIh8Qom1eMSWGb8+0Yhi/QVY= -apigo.cc/go/log v1.0.0 h1:lI1NGTSS+Jm12G8BD7ZJO4/hrkfuLTu5O8z36GD8GpU= -apigo.cc/go/log v1.0.0/go.mod h1:tvPgFpebY9Wf/DlqMHZ0ZjxDp9AaQTywOQKvtBaNqNo= +apigo.cc/go/log v1.0.2 h1:OY6T3SC28blDNkMpdRvDK2N4sGdriAB9DBItGl/qOos= +apigo.cc/go/log v1.0.2/go.mod h1:tvPgFpebY9Wf/DlqMHZ0ZjxDp9AaQTywOQKvtBaNqNo= apigo.cc/go/rand v1.0.4 h1:we070eWSL0dB8NEMaWjXj43+EekXQTm/h0kKpZ/frqw= apigo.cc/go/rand v1.0.4/go.mod h1:mZ/4Soa3bk+XvDaqPWJuUe1bfEi4eThBj1XmEAuYxsk= +apigo.cc/go/redis v1.0.2 h1:gWBrL/6eDxtouTFSZrPKQNdEg1AZr2aKTpCOhwim3dI= +apigo.cc/go/redis v1.0.2/go.mod h1:auQ3cyORgD67HF5dNvZ1lA8bqMH1xIbnuKBuZWclNy4= apigo.cc/go/safe v1.0.4 h1:07pRSdEHprF/2v6SsqAjICYFoeLcqjjvHGEdh6Dzrzg= apigo.cc/go/safe v1.0.4/go.mod h1:o568sHS5rTRSVPmhxWod0tGdc+8l1KjidsNY1/OVZr0= apigo.cc/go/shell v1.0.4 h1:EL9zjI39YBe1h+kRYQeAi/8zVGHe5W198DYYN7cENiY= @@ -30,6 +32,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/go-sql-driver/mysql v1.10.0 h1:Q+1LV8DkHJvSYAdR83XzuhDaTykuDx0l6fkXxoWCWfw= github.com/go-sql-driver/mysql v1.10.0/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk= +github.com/gomodule/redigo v1.9.3 h1:dNPSXeXv6HCq2jdyWfjgmhBdqnR6PRO3m/G05nvpPC8= +github.com/gomodule/redigo v1.9.3/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=