From dccff366d28f4fed3cedbcc7f89e603116837548 Mon Sep 17 00:00:00 2001 From: windyboy Date: Sat, 15 Nov 2025 17:42:10 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Update=20logger=20configuration=20f?= =?UTF-8?q?or=20development=20environment,=20enhancing=20logging=20structu?= =?UTF-8?q?re=20with=20zap=20and=20lumberjack=20settings.=20Refactor=20log?= =?UTF-8?q?ging=20utility=20to=20improve=20configuration=20file=20handling?= =?UTF-8?q?=20and=20add=20error=20management.=20Modify=20integration=20tes?= =?UTF-8?q?ts=20to=20utilize=20the=20new=20logger=20setup=20and=20adjust?= =?UTF-8?q?=20test=20payloads=20for=20consistency.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- configs/logger.dev.json | 33 +++++++++++++++ pkg/utils/log.go | 40 +++++++++++++++++-- .../jetstream_to_timescale_test.go | 25 +++++++----- 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/configs/logger.dev.json b/configs/logger.dev.json index d21309a..304243f 100644 --- a/configs/logger.dev.json +++ b/configs/logger.dev.json @@ -1,3 +1,36 @@ +{ + "zapConfig": { + "level": "info", + "development": true, + "encoding": "json", + "encoderConfig": { + "messageKey": "msg", + "levelKey": "level", + "timeKey": "ts", + "nameKey": "logger", + "callerKey": "caller", + "stacktraceKey": "stacktrace", + "lineEnding": "", + "levelEncoder": "lowercase", + "timeEncoder": "iso8601", + "durationEncoder": "string", + "callerEncoder": "short" + }, + "outputPaths": [ + "stdout" + ], + "errorOutputPaths": [ + "stderr" + ] + }, + "lumberjackConfig": { + "filename": "./logs/caatsm-dev.log", + "maxSize": 50, + "maxBackups": 5, + "maxAge": 14, + "compress": false + } +} { "zapConfig": { "level": "debug", diff --git a/pkg/utils/log.go b/pkg/utils/log.go index 626c2ee..47519b1 100644 --- a/pkg/utils/log.go +++ b/pkg/utils/log.go @@ -2,8 +2,12 @@ package utils import ( "encoding/json" + "errors" "fmt" "os" + "path/filepath" + "runtime" + "strings" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -12,7 +16,7 @@ import ( const ( TestConfigFileName = "./configs/logger.test.json" - ProdConfigFileName = ".configs/logger.json" + ProdConfigFileName = "./configs/logger.json" DevelopmentConfigFileName = "./configs/logger.dev.json" EnvTest = "test" EnvProd = "prod" @@ -33,10 +37,20 @@ type LumberjackConfig struct { } var ( - sugar *zap.SugaredLogger - log *zap.Logger + sugar *zap.SugaredLogger + log *zap.Logger + rootDir = detectRootDir() ) +func detectRootDir() string { + _, file, _, ok := runtime.Caller(0) + if !ok { + return "." + } + // pkg/utils/log.go -> project root + return filepath.Clean(filepath.Join(filepath.Dir(file), "..", "..")) +} + func load() { if log == nil { env := getEnv() @@ -103,7 +117,7 @@ func getConfigFile(env string) string { } func loadConfig(configFile string) (LoggerConfig, error) { - file, err := os.Open(configFile) + file, err := openConfigFile(configFile) if err != nil { return LoggerConfig{}, fmt.Errorf("error opening file: %v", err) } @@ -123,6 +137,24 @@ func GetLogger() *zap.SugaredLogger { return sugar } +func openConfigFile(configFile string) (*os.File, error) { + candidates := []string{ + configFile, + filepath.Join(rootDir, strings.TrimPrefix(configFile, "./")), + } + for _, candidate := range candidates { + if candidate == "" { + continue + } + if f, err := os.Open(candidate); err == nil { + return f, nil + } else if !errors.Is(err, os.ErrNotExist) { + return nil, err + } + } + return nil, fmt.Errorf("error opening file: %v", configFile) +} + func parseLogLevel(level string) zapcore.Level { switch level { case "debug": diff --git a/test/integration/jetstream_to_timescale_test.go b/test/integration/jetstream_to_timescale_test.go index e3286dd..d2fc334 100644 --- a/test/integration/jetstream_to_timescale_test.go +++ b/test/integration/jetstream_to_timescale_test.go @@ -14,6 +14,7 @@ import ( "caatsm/internal/app" "caatsm/internal/domain" "caatsm/internal/infra/config" + loginfra "caatsm/internal/infra/log" natsinfra "caatsm/internal/infra/nats" postgresinfra "caatsm/internal/infra/postgres" @@ -21,7 +22,6 @@ import ( "github.com/nats-io/nats.go" tc "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" - "go.uber.org/zap" ) func TestJetStreamToTimescaleFlow(t *testing.T) { @@ -43,7 +43,11 @@ func TestJetStreamToTimescaleFlow(t *testing.T) { }() cfg := buildTestConfig(natsURL, pgURL) - logger := zap.NewNop() + logger, err := loginfra.ProvideLogger(cfg) + if err != nil { + t.Fatalf("failed to init logger: %v", err) + } + defer logger.Sync() pool, err := postgresinfra.ProvideDB(cfg) if err != nil { @@ -99,10 +103,10 @@ func TestJetStreamToTimescaleFlow(t *testing.T) { }() // Publish a message to the input subject. - payload := []byte(`ZCZC ARR1234 150631 + payload := []byte(`ZCZC TMQ2526 141605 FF ZBTJZPZX -150630 ZBACZQZX -(ARR-CCA1234-A1234-ZBTJ1500-ZGGG0135) +141604 ZBACZQZX +(ARR-JAE7433/A0132-RKSI-ZBTJ1604) NNNN`) msg := nats.NewMsg(cfg.EffectiveSubscriptionTopic()) @@ -125,9 +129,12 @@ NNNN`) var status string err := pool.QueryRow(ctx, ` SELECT status FROM aviation.telegrams WHERE message_id = $1 LIMIT 1 - `, "ARR1234").Scan(&status) - if err == nil && status == string(domain.MessageStatusParsed) { - return + `, "TMQ2526").Scan(&status) + if err == nil { + if status == string(domain.MessageStatusParsed) { + return + } + t.Logf("message persisted with status=%s, waiting for parsed", status) } time.Sleep(500 * time.Millisecond) @@ -237,7 +244,7 @@ func buildTestConfig(natsURL, pgURL string) *config.Config { MonitorInterval: time.Second, }, Log: config.LogConfig{ - Level: "error", + Level: "debug", Format: "json", }, Publisher: config.PublisherConfig{