package logger import ( "io" "os" "strings" "sync" "github.com/caarlos0/env/v11" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) type Logger struct { LogLevel string `env:"LEVEL" envDefault:"INFO"` TraceIDLabel string `env:"TRACE_ID_LABEL" envDefault:"trace_id"` DateTimeFormat string `env:"DATE_TIME_FORMAT" envDefault:"2006-01-02 15:04:05.000"` } var ( once sync.Once singleton *zap.Logger cfg Logger ) const RequestID = "RequestID" func init() { cfg = Logger{} if err := env.Parse(&cfg); err != nil { Panic("Problemas ao inicializar a aplicação", zap.Error(err)) } // once ensures the singleton is initialized only once once.Do(func() { levelType := getLevelLogType(cfg.LogLevel) encoderConfig := getEconderConfig() atom := zap.NewAtomicLevelAt(levelType) core := zapcore.NewCore( zapcore.NewJSONEncoder(encoderConfig), zapcore.AddSync(os.Stdout), atom, ) singleton = zap.New(core, zap.AddCallerSkip(1), zap.AddCaller()) }) } func SetAppName(appName string) { singleton = singleton.With(zap.String("app", appName)) } func ChangeWriteSyncer(recurso io.Writer) { singleton = singleton.WithOptions( zap.WrapCore( func(zapcore.Core) zapcore.Core { return zapcore.NewCore(zapcore.NewJSONEncoder(getEconderConfig()), zapcore.AddSync(recurso), zap.NewAtomicLevelAt(zap.DebugLevel)) })) } func ChangeLogLevel(level string) { levelType := getLevelLogType(level) singleton = singleton.WithOptions( zap.WrapCore( func(zapcore.Core) zapcore.Core { return zapcore.NewCore(zapcore.NewJSONEncoder(getEconderConfig()), zapcore.AddSync(os.Stdout), zap.NewAtomicLevelAt(levelType)) })) } func getLevelLogType(entrada string) zapcore.Level { entrada = strings.TrimSpace(entrada) switch strings.ToUpper(entrada) { case "INFO": return zap.InfoLevel case "DEBUG": return zap.DebugLevel case "ERROR": return zap.ErrorLevel case "WARN": return zap.WarnLevel case "PANIC": return zap.PanicLevel case "DPANIC": return zap.DPanicLevel case "FATAL": return zap.FatalLevel default: return zap.InfoLevel } } func getEconderConfig() zapcore.EncoderConfig { return zapcore.EncoderConfig{ MessageKey: "msg", TimeKey: "time", LevelKey: "level", NameKey: "logger", CallerKey: "caller", StacktraceKey: "stacktrace", FunctionKey: "func", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.CapitalLevelEncoder, // EncodeTime: zapcore.ISO8601TimeEncoder, EncodeTime: zapcore.TimeEncoderOfLayout(cfg.DateTimeFormat), // EncodeDuration: zapcore.SecondsDurationEncoder, EncodeDuration: zapcore.StringDurationEncoder, EncodeCaller: zapcore.ShortCallerEncoder, // EncodeCaller: zapcore.FullCallerEncoder, } } // Debug logs a debug message with the given fields func Debug(message string, fields ...zap.Field) { singleton.Debug(message, fields...) } // Info logs a debug message with the given fields func Info(message string, fields ...zap.Field) { singleton.Info(message, fields...) } func Printf(format string, args ...interface{}) { singleton.Sugar().Infof(format, args...) } // Warn logs a debug message with the given fields func Warn(message string, fields ...zap.Field) { singleton.Warn(message, fields...) } // Error logs a debug message with the given fields func Error(message string, fields ...zap.Field) { singleton.Error(message, fields...) } // Fatal logs a message than calls os.Exit(1) func Fatal(message string, fields ...zap.Field) { singleton.Fatal(message, fields...) } func Panic(message string, fields ...zap.Field) { singleton.Panic(message, fields...) } func DPanic(message string, fields ...zap.Field) { singleton.DPanic(message, fields...) } func GetInstance() *zap.Logger { return singleton } func TraceID(traceID string) zap.Field { return zap.String(cfg.TraceIDLabel, traceID) }