diff --git a/go.mod b/go.mod index d8430d1..3c8a666 100644 --- a/go.mod +++ b/go.mod @@ -16,4 +16,5 @@ require ( github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 github.com/russross/meddler v1.0.0 github.com/stretchr/testify v1.6.1 + go.uber.org/zap v1.13.0 ) diff --git a/go.sum b/go.sum index 3782f05..ff62838 100644 --- a/go.sum +++ b/go.sum @@ -539,11 +539,14 @@ go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..c86a709 --- /dev/null +++ b/log/log.go @@ -0,0 +1,121 @@ +package log + +import ( + "fmt" + "os" + "time" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +var log *zap.SugaredLogger + +// errorsFile is the file where the errors are being written +var errorsFile *os.File + +func init() { + // default level: debug + Init("debug", "") +} + +// Init the logger with defined level. errorsPath defines the file where to store the errors, if set to "" will not store errors. +func Init(levelStr, errorsPath string) { + var level zap.AtomicLevel + err := level.UnmarshalText([]byte(levelStr)) + if err != nil { + panic(fmt.Errorf("Error on setting log level: %s", err)) + } + cfg := zap.Config{ + Level: level, + Encoding: "console", + OutputPaths: []string{"stdout"}, + ErrorOutputPaths: []string{"stderr"}, + EncoderConfig: zapcore.EncoderConfig{ + MessageKey: "message", + + LevelKey: "level", + EncodeLevel: zapcore.CapitalColorLevelEncoder, + + TimeKey: "timestamp", + EncodeTime: func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.Local().Format(time.RFC3339)) + }, + EncodeDuration: zapcore.SecondsDurationEncoder, + + CallerKey: "caller", + EncodeCaller: zapcore.ShortCallerEncoder, + + StacktraceKey: "stacktrace", + LineEnding: zapcore.DefaultLineEnding, + }, + } + + logger, err := cfg.Build() + if err != nil { + panic(err) + } + //nolint:errcheck + defer logger.Sync() + log = logger.Sugar() + + if errorsPath != "" { + log.Infof("file where errors will be written: %s", errorsPath) + errorsFile, err = os.OpenFile(errorsPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + panic(err) + } + } + + log.Infof("log level: %s", level) +} + +func writeToErrorsFile(msg string) { + if errorsFile == nil { + return + } + //nolint:errcheck + errorsFile.WriteString(fmt.Sprintf("%s %s\n", time.Now().Format(time.RFC3339), msg)) +} + +// Debug calls log.Debug +func Debug(args ...interface{}) { + log.Debug(args...) +} + +// Info calls log.Info +func Info(args ...interface{}) { + log.Info(args...) +} + +// Warn calls log.Warn +func Warn(args ...interface{}) { + log.Warn(args...) +} + +// Error calls log.Error and stores the error message into the ErrorFile +func Error(args ...interface{}) { + log.Error(args...) + go writeToErrorsFile(fmt.Sprint(args...)) +} + +// Debugf calls log.Debugf +func Debugf(template string, args ...interface{}) { + log.Debugf(template, args...) +} + +// Infof calls log.Infof +func Infof(template string, args ...interface{}) { + log.Infof(template, args...) +} + +// Warnf calls log.Warnf +func Warnf(template string, args ...interface{}) { + log.Warnf(template, args...) +} + +// Errorf calls log.Errorf and stores the error message into the ErrorFile +func Errorf(template string, args ...interface{}) { + log.Errorf(template, args...) + go writeToErrorsFile(fmt.Sprintf(template, args...)) +} diff --git a/log/log_test.go b/log/log_test.go new file mode 100644 index 0000000..f228d7d --- /dev/null +++ b/log/log_test.go @@ -0,0 +1,14 @@ +package log + +import ( + "testing" +) + +func TestLog(t *testing.T) { + Info("Test log.Infow", "value", 10) + Infof("Test log.Infof %d", 10) + Debugf("Test log.Debugf %d", 10) + Error("Test log.Error", "value", 10) + Errorf("Test log.Errorf %d", 10) + Warnf("Test log.Warnf %d", 10) +}