diff --git a/go.mod b/go.mod index 8a8f922..2f7a762 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( ) require ( + github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.1 golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 // indirect golang.org/x/exp v0.0.0-20220328175248-053ad81199eb diff --git a/go.sum b/go.sum index d11ef7a..177e065 100644 --- a/go.sum +++ b/go.sum @@ -42,9 +42,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -77,6 +80,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= diff --git a/logx/log.go b/logx/log.go new file mode 100644 index 0000000..dc7616f --- /dev/null +++ b/logx/log.go @@ -0,0 +1,115 @@ +package logx + +import ( + "fmt" + "strings" +) + +// Fields type, used to pass to `WithFields`. +type Fields map[string]any + +type Level uint32 + +// Convert the Level to a string. E.g. PanicLevel becomes "panic". +func (level Level) String() string { + if b, err := level.MarshalText(); err == nil { + return string(b) + } else { + return "unknown" + } +} + +// ParseLevel takes a string level and returns the Logrus log level constant. +func ParseLevel(lvl string) (Level, error) { + switch strings.ToLower(lvl) { + case "panic": + return PanicLevel, nil + case "fatal": + return FatalLevel, nil + case "error": + return ErrorLevel, nil + case "warn", "warning": + return WarnLevel, nil + case "info": + return InfoLevel, nil + case "debug": + return DebugLevel, nil + case "trace": + return TraceLevel, nil + } + + var l Level + return l, fmt.Errorf("not a valid logrus Level: %q", lvl) +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (level *Level) UnmarshalText(text []byte) error { + l, err := ParseLevel(string(text)) + if err != nil { + return err + } + + *level = l + + return nil +} + +func (level Level) MarshalText() ([]byte, error) { + switch level { + case TraceLevel: + return []byte("trace"), nil + case DebugLevel: + return []byte("debug"), nil + case InfoLevel: + return []byte("info"), nil + case WarnLevel: + return []byte("warning"), nil + case ErrorLevel: + return []byte("error"), nil + case FatalLevel: + return []byte("fatal"), nil + case PanicLevel: + return []byte("panic"), nil + } + + return nil, fmt.Errorf("not a valid logrus level %d", level) +} + +// These are the different logging levels. You can set the logging level to log +// on your instance of logger, obtained with `logrus.New()`. +const ( + // PanicLevel level, highest level of severity. Logs and then calls panic with the + // message passed to Debug, Info, ... + PanicLevel Level = iota + // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the + // logging level is set to Panic. + FatalLevel + // ErrorLevel level. Logs. Used for errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. + ErrorLevel + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel + // InfoLevel level. General operational entries about what's going on inside the + // application. + InfoLevel + // DebugLevel level. Usually only enabled when debugging. Very verbose logging. + DebugLevel + // TraceLevel level. Designates finer-grained informational events than the Debug. + TraceLevel +) + +type Logger interface { + SetLevel(level Level) + WithField(key string, value any) Logger + WithFields(fields Fields) Logger + Info(args ...any) + Infof(format string, args ...any) + Warn(args ...any) + Error(args ...any) + Warnf(format string, args ...any) + Errorf(format string, args ...any) + Fatalf(format string, args ...any) + Println(args ...any) + Print(args ...any) + Printf(format string, args ...any) +} diff --git a/logx/logrus.go b/logx/logrus.go new file mode 100644 index 0000000..55a0493 --- /dev/null +++ b/logx/logrus.go @@ -0,0 +1,69 @@ +package logx + +import "github.com/sirupsen/logrus" + +type logrusWrpper struct { + logger *logrus.Entry +} + +func CreateLogrus() Logger { + logger := logrus.New() + + return &logrusWrpper{ + logger: logrus.NewEntry(logger), + } +} + +func (l *logrusWrpper) SetLevel(level Level) { + l.logger.Logger.SetLevel(logrus.Level(level)) +} + +func (l *logrusWrpper) WithField(key string, value any) Logger { + return l.WithFields(Fields{key: value}) +} + +func (l *logrusWrpper) WithFields(fields Fields) Logger { + return &logrusWrpper{ + logger: l.logger.WithFields(logrus.Fields(fields)), + } +} + +func (l *logrusWrpper) Info(args ...any) { + l.logger.Info(args...) +} + +func (l *logrusWrpper) Infof(format string, args ...any) { + l.logger.Infof(format, args...) +} + +func (l *logrusWrpper) Warn(args ...any) { + l.logger.Warn(args...) +} + +func (l *logrusWrpper) Error(args ...any) { + l.Error(args...) +} + +func (l *logrusWrpper) Warnf(format string, args ...any) { + l.Warnf(format, args...) +} + +func (l *logrusWrpper) Errorf(format string, args ...any) { + l.Errorf(format, args...) +} + +func (l *logrusWrpper) Fatalf(format string, args ...any) { + l.Fatalf(format, args...) +} + +func (entry *logrusWrpper) Println(args ...interface{}) { + entry.logger.Infoln(args...) +} + +func (entry *logrusWrpper) Print(args ...interface{}) { + entry.Info(args...) +} + +func (entry *logrusWrpper) Printf(format string, args ...interface{}) { + entry.Infof(format, args...) +}