diff --git a/config.example.yaml b/config.example.yaml index e3f9014c..046bba34 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -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: "wavelet-server" diff --git a/internal/db/postgres_logger.go b/internal/db/postgres_logger.go index eb7964d9..0bfd0f7a 100644 --- a/internal/db/postgres_logger.go +++ b/internal/db/postgres_logger.go @@ -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 } diff --git a/internal/db/postgres_logger_test.go b/internal/db/postgres_logger_test.go new file mode 100644 index 00000000..20539a5b --- /dev/null +++ b/internal/db/postgres_logger_test.go @@ -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) + } + }) + } +}