diff --git a/go.mod b/go.mod index bb5ca229..9f35f27c 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-gonic/gin v1.6.3 github.com/go-playground/validator/v10 v10.2.0 + github.com/sirupsen/logrus v1.7.0 github.com/smartystreets/goconvey v1.6.4 // indirect github.com/stretchr/testify v1.4.0 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 diff --git a/go.sum b/go.sum index c53760e7..26e55275 100644 --- a/go.sum +++ b/go.sum @@ -34,11 +34,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 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.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -53,6 +56,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/pkg/log/formatter.go b/pkg/log/formatter.go new file mode 100644 index 00000000..22e26d94 --- /dev/null +++ b/pkg/log/formatter.go @@ -0,0 +1,55 @@ +package log + +import ( + "bytes" + "fmt" + "strings" + "time" + + "github.com/sirupsen/logrus" + + "github.com/mayswind/lab/pkg/utils" +) + +type LogFormatter struct { + Prefix string + DisableLevel bool +} + +func (f *LogFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var b *bytes.Buffer + + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + b.WriteString(utils.FormatToLongDateTime(time.Now())) + b.WriteString(" ") + + if f.Prefix != "" { + b.WriteString(f.Prefix) + b.WriteString(" ") + } + + if !f.DisableLevel { + b.WriteString("[") + b.WriteString(strings.ToUpper(entry.Level.String())) + b.WriteString("] ") + } + + b.WriteString(entry.Message) + + if requestId, exists := entry.Data[LOG_FIELD_REQUEST_ID]; exists { + b.WriteString(fmt.Sprintf(", r=%s", requestId)) + } + + b.WriteString("\n") + + if extra, exists := entry.Data[LOG_FIELD_EXTRA]; exists { + b.WriteString(extra.(string)) + } + + return b.Bytes(), nil +} diff --git a/pkg/log/logger.go b/pkg/log/logger.go new file mode 100644 index 00000000..c43a999e --- /dev/null +++ b/pkg/log/logger.go @@ -0,0 +1,172 @@ +package log + +import ( + "fmt" + "io" + "os" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/mayswind/lab/pkg/core" + "github.com/mayswind/lab/pkg/settings" +) + +const LOG_FIELD_REQUEST_ID = "REQUEST_ID" +const LOG_FIELD_EXTRA = "EXTRA" + +var bootLogger = logrus.New() +var defaultLogger = logrus.New() +var requestLogger = logrus.New() +var sqlQueryLogger = logrus.New() + +func init() { + bootLogger.SetFormatter(&LogFormatter{}) + bootLogger.SetOutput(os.Stdout) + bootLogger.SetLevel(logrus.InfoLevel) + + defaultLogger.SetFormatter(&LogFormatter{}) + defaultLogger.SetOutput(os.Stdout) + defaultLogger.SetLevel(logrus.InfoLevel) + + requestLogger.SetFormatter(&LogFormatter{Prefix: "[REQUEST]", DisableLevel: true}) + requestLogger.SetOutput(os.Stdout) + requestLogger.SetLevel(logrus.InfoLevel) + + sqlQueryLogger.SetFormatter(&LogFormatter{Prefix: "[SQLQUERY]", DisableLevel: true}) + sqlQueryLogger.SetOutput(os.Stdout) + sqlQueryLogger.SetLevel(logrus.InfoLevel) +} + +func SetLoggerConfiguration(config *settings.Config) error { + var bootWriters []io.Writer + var writers []io.Writer + + bootWriters = append(bootWriters, os.Stdout) + + if config.EnableConsoleLog { + writers = append(writers, os.Stdout) + } + + if config.EnableFileLog { + logFile, err := os.OpenFile(config.FileLogPath, os.O_CREATE|os.O_WRONLY, 0666) + + if err != nil { + return err + } + + bootWriters = append(bootWriters, logFile) + writers = append(writers, logFile) + } + + bootMultipleWriter := io.MultiWriter(bootWriters...) + multipleWriter := io.MultiWriter(writers...) + + bootLogger.SetOutput(bootMultipleWriter) + defaultLogger.SetOutput(multipleWriter) + requestLogger.SetOutput(multipleWriter) + sqlQueryLogger.SetOutput(multipleWriter) + + if config.LogLevel == settings.LOGLEVEL_DEBUG { + bootLogger.SetLevel(logrus.DebugLevel) + defaultLogger.SetLevel(logrus.DebugLevel) + } else if config.LogLevel == settings.LOGLEVEL_INFO { + bootLogger.SetLevel(logrus.InfoLevel) + defaultLogger.SetLevel(logrus.InfoLevel) + } else if config.LogLevel == settings.LOGLEVEL_WARN { + bootLogger.SetLevel(logrus.WarnLevel) + defaultLogger.SetLevel(logrus.WarnLevel) + } else if config.LogLevel == settings.LOGLEVEL_ERROR { + bootLogger.SetLevel(logrus.ErrorLevel) + defaultLogger.SetLevel(logrus.ErrorLevel) + } + + if !config.EnableRequestLog { + requestLogger = nil + } + + if !config.EnableQueryLog { + sqlQueryLogger = nil + } + + return nil +} + +func Debugf(format string, args ...interface{}) { + defaultLogger.Debugf(getFinalLog(format, args...)) +} + +func DebugfWithRequestId(c *core.Context, format string, args ...interface{}) { + defaultLogger.WithField(LOG_FIELD_REQUEST_ID, c.GetRequestId()).Debugf(getFinalLog(format, args...)) +} + +func Infof(format string, args ...interface{}) { + defaultLogger.Infof(getFinalLog(format, args...)) +} + +func InfofWithRequestId(c *core.Context, format string, args ...interface{}) { + defaultLogger.WithField(LOG_FIELD_REQUEST_ID, c.GetRequestId()).Infof(getFinalLog(format, args...)) +} + +func Warnf(format string, args ...interface{}) { + defaultLogger.Warnf(getFinalLog(format, args...)) +} + +func WarnfWithRequestId(c *core.Context, format string, args ...interface{}) { + defaultLogger.WithField(LOG_FIELD_REQUEST_ID, c.GetRequestId()).Warnf(getFinalLog(format, args...)) +} + +func Errorf(format string, args ...interface{}) { + defaultLogger.Errorf(getFinalLog(format, args...)) +} + +func ErrorfWithRequestId(c *core.Context, format string, args ...interface{}) { + defaultLogger.WithField(LOG_FIELD_REQUEST_ID, c.GetRequestId()).Errorf(getFinalLog(format, args...)) +} + +func ErrorfWithRequestIdAndExtra(c *core.Context, extraString string, format string, args ...interface{}) { + defaultLogger.WithField(LOG_FIELD_REQUEST_ID, c.GetRequestId()).WithField(LOG_FIELD_EXTRA, extraString).Errorf(getFinalLog(format, args...)) +} + +func BootInfof(format string, args ...interface{}) { + if bootLogger != nil { + bootLogger.Infof(getFinalLog(format, args...)) + } +} + +func BootWarnf(format string, args ...interface{}) { + if bootLogger != nil { + bootLogger.Warnf(getFinalLog(format, args...)) + } +} + +func BootErrorf(format string, args ...interface{}) { + if bootLogger != nil { + bootLogger.Errorf(getFinalLog(format, args...)) + } +} + +func Requestf(c *core.Context, format string, args ...interface{}) { + if requestLogger != nil { + requestLogger.WithField(LOG_FIELD_REQUEST_ID, c.GetRequestId()).Infof(getFinalLog(format, args...)) + } +} + +func SqlQuery(args ...interface{}) { + if sqlQueryLogger != nil { + sqlQueryLogger.Info(args...) + } +} + +func SqlQueryf(format string, args ...interface{}) { + if sqlQueryLogger != nil { + sqlQueryLogger.Infof(getFinalLog(format, args...)) + } +} + +func getFinalLog(format string, args ...interface{}) string { + result := fmt.Sprintf(format, args...) + result = strings.Replace(result, "\n", " ", -1) + + return result +}