From d38b6ab06441680f36cc43c8199b66cb0ed58249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Thu, 8 Sep 2022 14:33:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(log):=E5=AE=8C=E5=85=A8=E4=BD=BF=E7=94=A8Z?= =?UTF-8?q?erolog=E6=8E=A5=E7=AE=A1=E9=A1=B9=E7=9B=AE=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- global/db.go | 3 ++ logger/logger.go | 14 +++++++ logger/xormlogger.go | 97 ++++++++++++++++++++++++++++++++++++++++++++ main.go | 34 ++++++++-------- router/router.go | 9 ++-- 5 files changed, 136 insertions(+), 21 deletions(-) create mode 100644 logger/xormlogger.go diff --git a/global/db.go b/global/db.go index 0d8c1a4..e184457 100644 --- a/global/db.go +++ b/global/db.go @@ -6,6 +6,7 @@ import ( "time" "electricity_bill_calc/config" + "electricity_bill_calc/logger" // _ "github.com/lib/pq" _ "github.com/jackc/pgx/v5/stdlib" @@ -40,6 +41,8 @@ func SetupDatabaseConnection() error { if err != nil { return err } + xLogger := logger.NewXormZeroLogger(logger.GetLogger()) + DBConn.SetLogger(log.NewLoggerAdapter(xLogger)) DBConn.Ping() DBConn.SetMaxIdleConns(config.DatabaseSettings.MaxIdleConns) diff --git a/logger/logger.go b/logger/logger.go index 7f2b6bf..e0baead 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -4,6 +4,7 @@ import ( "io" "os" + jsoniter "github.com/json-iterator/go" "github.com/rs/zerolog" "github.com/samber/lo" ) @@ -20,6 +21,10 @@ func init() { logger.Info().Msg("Logger initialized.") } +func GetLogger() *zerolog.Logger { + return logger +} + func Panic() *zerolog.Event { return logger.Panic() } @@ -59,3 +64,12 @@ func Printf(format string, v ...interface{}) { func With() zerolog.Context { return logger.With() } + +func FormatAny(v interface{}) string { + b, err := jsoniter.MarshalToString(v) + if err != nil { + logger.Error().Str("process", "log").Err(err).Stack().Msg("Value marshal failed.") + return "" + } + return b +} diff --git a/logger/xormlogger.go b/logger/xormlogger.go new file mode 100644 index 0000000..30f5221 --- /dev/null +++ b/logger/xormlogger.go @@ -0,0 +1,97 @@ +package logger + +import ( + "fmt" + + "github.com/rs/zerolog" + "github.com/samber/lo" + "xorm.io/xorm/log" +) + +type XormZeroLogger struct { + logger *zerolog.Logger + off bool + show bool +} + +func NewXormZeroLogger(oLogger *zerolog.Logger) *XormZeroLogger { + return &XormZeroLogger{ + logger: lo.ToPtr(oLogger.With().Str("process", "Xorm").Logger()), + off: false, + show: true, + } +} + +func (l XormZeroLogger) BeforeSQL(_ log.LogContext) {} + +func (l XormZeroLogger) AfterSQL(c log.LogContext) { + if c.Err == nil { + l.logger.Info().Str("SQL", c.SQL).Str("args", FormatAny(c.Args)).Dur("execution", c.ExecuteTime).Send() + return + } + l.logger.Error().Err(c.Err).Stack().Str("SQL", c.SQL).Str("args", FormatAny(c.Args)).Dur("execution", c.ExecuteTime).Msg(c.Err.Error()) +} + +func (l XormZeroLogger) Debug(v ...interface{}) { + l.logger.Debug().Str("args", FormatAny(v)).Msg(fmt.Sprint(v...)) +} + +func (l XormZeroLogger) Debugf(format string, v ...interface{}) { + l.logger.Debug().Str("args", FormatAny(v)).Msg(fmt.Sprintf(format, v...)) +} + +func (l XormZeroLogger) Info(v ...interface{}) { + l.logger.Info().Str("args", FormatAny(v)).Msg(fmt.Sprint(v...)) +} + +func (l XormZeroLogger) Infof(format string, v ...interface{}) { + l.logger.Info().Str("args", FormatAny(v)).Msg(fmt.Sprintf(format, v...)) +} + +func (l XormZeroLogger) Warn(v ...interface{}) { + l.logger.Warn().Str("args", FormatAny(v)).Msg(fmt.Sprint(v...)) +} + +func (l XormZeroLogger) Warnf(format string, v ...interface{}) { + l.logger.Warn().Str("args", FormatAny(v)).Msg(fmt.Sprintf(format, v...)) +} + +func (l XormZeroLogger) Error(v ...interface{}) { + l.logger.Error().Str("args", FormatAny(v)).Msg(fmt.Sprint(v...)) +} + +func (l XormZeroLogger) Errorf(format string, v ...interface{}) { + l.logger.Error().Str("args", FormatAny(v)).Msg(fmt.Sprintf(format, v...)) +} + +func (l XormZeroLogger) SetLevel(lvl log.LogLevel) { + l.logger.Warn().Msg("Change log level is not supported.") +} + +func (l *XormZeroLogger) ShowSQL(b ...bool) { + l.show = b[0] +} + +func (l XormZeroLogger) IsShowSQL() bool { + return l.show +} + +func (l XormZeroLogger) Level() log.LogLevel { + if l.off { + return log.LOG_OFF + } + + for _, lvl := range []zerolog.Level{zerolog.DebugLevel, zerolog.InfoLevel, zerolog.WarnLevel, zerolog.ErrorLevel, zerolog.FatalLevel, zerolog.PanicLevel} { + switch lvl { + case zerolog.DebugLevel: + return log.LOG_DEBUG + case zerolog.InfoLevel: + return log.LOG_INFO + case zerolog.WarnLevel: + return log.LOG_WARNING + case zerolog.ErrorLevel: + return log.LOG_ERR + } + } + return log.LOG_UNKNOWN +} diff --git a/main.go b/main.go index 5f10237..b1319da 100644 --- a/main.go +++ b/main.go @@ -4,13 +4,13 @@ import ( "electricity_bill_calc/cache" "electricity_bill_calc/config" "electricity_bill_calc/global" + "electricity_bill_calc/logger" "electricity_bill_calc/model" "electricity_bill_calc/router" "electricity_bill_calc/service" "encoding/csv" "fmt" "io" - "log" "os" "strconv" "time" @@ -24,15 +24,15 @@ import ( func init() { err := config.SetupSetting() if err != nil { - log.Fatalf("Configuration load failed: %v", err) + logger.Fatal().Err(err).Stack().Msg("Configuration load failed.") } - log.Println("Configuration loaded!") + logger.Info().Msg("Configuration loaded!") err = global.SetupDatabaseConnection() if err != nil { - log.Fatalf("Main Database connect failed: %v", err) + logger.Fatal().Err(err).Stack().Msg("Main Database connect failed.") } - log.Println("Main Database connected!") + logger.Info().Msg("Main Database connected!") err = global.DBConn.Sync( &model.Region{}, @@ -47,27 +47,27 @@ func init() { &model.WillDilutedFee{}, &model.EndUserDetail{}) if err != nil { - log.Fatalf("Database structure synchronize failed: %v", err) + logger.Fatal().Err(err).Stack().Msg("Database structure synchronize failed.") } - log.Println("Database structure synchronized.") + logger.Info().Msg("Database structure synchronized.") err = global.SetupRedisConnection() if err != nil { - log.Fatalf("Main Cache Database connect failed: %v", err) + logger.Fatal().Err(err).Stack().Msg("Main Cache Database connect failed.") } - log.Println("Main Cache Database connected!") + logger.Info().Msg("Main Cache Database connected!") err = initializeRegions() if err != nil { - log.Fatalf("Regions initialize failed: %v", err) + logger.Fatal().Err(err).Stack().Msg("Regions initialize failed.") } - log.Println("Regions synchronized.") + logger.Info().Msg("Regions synchronized.") err = intializeSingularity() if err != nil { - log.Fatalf("Singularity account intialize failed: %v", err) + logger.Fatal().Err(err).Stack().Msg("Singularity account intialize failed.") } - log.Println("Singularity account intialized.") + logger.Info().Msg("Singularity account intialized.") timeZoneShanghai, _ := time.LoadLocation("Asia/Shanghai") jsontime.AddTimeFormatAlias("simple_datetime", "2006-01-02 15:04:05") @@ -76,7 +76,7 @@ func init() { } func initializeRegions() error { - log.Println("Synchronize regions...") + logger.Info().Msg("Synchronize regions...") regionCsvFile, err := os.Open("regions.csv") if err != nil { return fmt.Errorf("region initialize file is not found: %w", err) @@ -145,7 +145,7 @@ func intializeSingularity() error { if err != nil { return fmt.Errorf("singularity account failed to create: %w", err) } - log.Printf("Singularity account created, use %s as verify code to reset password.", verifyCode) + logger.Info().Str("account", "singularity").Str("verifyCode", verifyCode).Msg(fmt.Sprintf("Singularity account created, use %s as verify code to reset password.", verifyCode)) return nil } @@ -160,10 +160,10 @@ func DBConnectionKeepLive() { func RedisOrphanCleanup() { for range time.Tick(2 * time.Minute) { - log.Printf("[Cache] [Cleanup] Proceeding cleanup orphan keys.") + logger.Info().Str("process", "Cache").Str("function", "Cleanup").Msg("Proceeding cleanup orphan keys.") err := cache.ClearOrphanRelationItems() if err != nil { - log.Printf("[Cache] [Cleanup] Orphan keys clear failed: %v", err) + logger.Error().Err(err).Stack().Str("process", "Cache").Str("function", "Cleanup").Msg("Orphan keys clear failed.") continue } } diff --git a/router/router.go b/router/router.go index 765a45f..ee07362 100644 --- a/router/router.go +++ b/router/router.go @@ -2,16 +2,16 @@ package router import ( "electricity_bill_calc/controller" + "electricity_bill_calc/logger" "electricity_bill_calc/response" "electricity_bill_calc/security" - "log" - "runtime/debug" "github.com/gin-gonic/gin" ) func Router() *gin.Engine { router := gin.Default() + router.Use(logger.Logger()) router.Use(Recover) router.Use(security.SessionRecovery) @@ -40,8 +40,9 @@ func Recover(c *gin.Context) { defer func() { if r := recover(); r != nil { //打印错误堆栈信息 - log.Printf("panic: %v\n", r) - debug.PrintStack() + if err, ok := r.(error); ok { + logger.Error().Err(err).Stack().Msg(err.Error()) + } // response.NewResult(c).Error(500, "服务器内部错误") } }()