fix(db): log SQL statements at debug level

Move routine GORM SQL output to debug and omit SQL text from slow-query and query-error logs to prevent sensitive parameters from being emitted at production log levels.
This commit is contained in:
ryan
2026-07-13 15:39:35 +08:00
parent 9dc3983e0f
commit 60bc03f519
4 changed files with 55 additions and 18 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ database:
max_open_conn: 128
conn_max_lifetime: 1800
conn_max_idle_time: 600
log_level: "info" # error | warn | info | debug | silent
log_level: "info" # error | warn | info | debug | silent;SQL 语句仅在 log.level=debug 时输出
ssl_mode: "disable"
time_zone: "UTC"
application_name: "openflare-server"
+1
View File
@@ -35,6 +35,7 @@ sidebar: false
### 修复
- GORM SQL 语句改为仅在全局 `debug` 日志级别输出;生产默认日志级别不再记录查询文本,慢查询与执行错误也不包含 SQL 参数,避免节点访问令牌等敏感信息写入应用日志。
- WAF 规则编辑器支持通过按钮或键盘删除普通节点和连线,节点属性栏改为选中节点后按需显示,并修复拖动节点时因 React Flow 初始化状态丢失导致的画面闪烁与 error 015。
- WAF 规则编辑器新增启用/停用控制,并移除已废弃的规则组侧站点绑定入口;站点规则顺序统一在反代路由详情中管理。
- 修复 Agent 心跳无法从活动 WAF 运行图发现 IP 组引用的问题,并对发布与同步的完整 IP 组快照增加 20 MiB 聚合容量保护。
+14 -17
View File
@@ -53,30 +53,25 @@ func (l *gormZapLogger) Trace(ctx context.Context, begin time.Time, fc func() (s
elapsed := time.Since(begin)
switch {
case err != nil && l.logLevel >= gormLogger.Error && (!errors.Is(err, gorm.ErrRecordNotFound) || !l.ignoreRecordNotFoundError):
sql, rows := fc()
if rows == -1 {
logger.ErrorF(ctx, "%s\n[%.3fms] [rows:%v] %s", err, float64(elapsed.Nanoseconds())/nanoToMilli, "-", sql)
} else {
logger.ErrorF(ctx, "%s\n[%.3fms] [rows:%v] %s", err, float64(elapsed.Nanoseconds())/nanoToMilli, rows, sql)
}
_, rows := fc()
logger.ErrorF(ctx, "database query failed: %s [%.3fms] [rows:%v]", err, float64(elapsed.Nanoseconds())/nanoToMilli, formatRows(rows))
case elapsed > l.slowThreshold && l.slowThreshold != 0 && l.logLevel >= gormLogger.Warn:
sql, rows := fc()
_, rows := fc()
slowLog := fmt.Sprintf("SLOW SQL >= %v", l.slowThreshold)
if rows == -1 {
logger.WarnF(ctx, "%s\n[%.3fms] [rows:%v] %s", slowLog, float64(elapsed.Nanoseconds())/nanoToMilli, "-", sql)
} else {
logger.WarnF(ctx, "%s\n[%.3fms] [rows:%v] %s", slowLog, float64(elapsed.Nanoseconds())/nanoToMilli, rows, sql)
}
logger.WarnF(ctx, "%s [%.3fms] [rows:%v]", slowLog, float64(elapsed.Nanoseconds())/nanoToMilli, formatRows(rows))
case l.logLevel == gormLogger.Info:
sql, rows := fc()
if rows == -1 {
logger.InfoF(ctx, "[%.3fms] [rows:%v] %s", float64(elapsed.Nanoseconds())/nanoToMilli, "-", sql)
} else {
logger.InfoF(ctx, "[%.3fms] [rows:%v] %s", float64(elapsed.Nanoseconds())/nanoToMilli, rows, sql)
}
logger.DebugF(ctx, "[%.3fms] [rows:%v] %s", float64(elapsed.Nanoseconds())/nanoToMilli, formatRows(rows), sql)
}
}
func formatRows(rows int64) interface{} {
if rows == -1 {
return "-"
}
return rows
}
func parseLogLevel(level string) gormLogger.LogLevel {
level = strings.ToLower(level)
switch level {
@@ -88,6 +83,8 @@ func parseLogLevel(level string) gormLogger.LogLevel {
return gormLogger.Warn
case "info":
return gormLogger.Info
case "debug":
return gormLogger.Info
default:
return gormLogger.Info
}
+39
View File
@@ -0,0 +1,39 @@
// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package db
import (
"testing"
gormLogger "gorm.io/gorm/logger"
)
func TestParseLogLevel(t *testing.T) {
t.Parallel()
tests := []struct {
name string
configuredLevel string
want gormLogger.LogLevel
}{
{
name: "debug enables SQL trace processing",
configuredLevel: "debug",
want: gormLogger.Info,
},
{
name: "development preserves configured level",
configuredLevel: "warn",
want: gormLogger.Warn,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := parseLogLevel(tt.configuredLevel); got != tt.want {
t.Fatalf("parseLogLevel() = %v, want %v", got, tt.want)
}
})
}
}