diff --git a/core/engine.go b/core/engine.go index 2de7c2f..c8c051f 100644 --- a/core/engine.go +++ b/core/engine.go @@ -19,7 +19,7 @@ type Engine struct { Utils ginEngine *gin.Engine httpClient *http.Client - Logger *logging.Logger + Logger LoggerInterface csrf *CSRF jobManager *JobManager Sessions sessions.Store diff --git a/core/http_client_builder.go b/core/http_client_builder.go index 41d1731..5dc6963 100644 --- a/core/http_client_builder.go +++ b/core/http_client_builder.go @@ -8,7 +8,6 @@ import ( "net/http" "time" - "github.com/op/go-logging" "github.com/pkg/errors" ) @@ -46,7 +45,7 @@ type HTTPClientBuilder struct { httpClient *http.Client httpTransport *http.Transport dialer *net.Dialer - logger *logging.Logger + logger LoggerInterface built bool logging bool timeout time.Duration @@ -70,7 +69,7 @@ func NewHTTPClientBuilder() *HTTPClientBuilder { } // WithLogger sets provided logger into HTTPClientBuilder -func (b *HTTPClientBuilder) WithLogger(logger *logging.Logger) *HTTPClientBuilder { +func (b *HTTPClientBuilder) WithLogger(logger LoggerInterface) *HTTPClientBuilder { if logger != nil { b.logger = logger } diff --git a/core/job_manager.go b/core/job_manager.go index 76bd8d1..a24540c 100644 --- a/core/job_manager.go +++ b/core/job_manager.go @@ -52,7 +52,7 @@ type Job struct { type JobManager struct { jobs *sync.Map enableLogging bool - logger *logging.Logger + logger LoggerInterface } // getWrappedFunc wraps job into function @@ -143,7 +143,7 @@ func DefaultJobPanicHandler() JobPanicHandler { } // SetLogger sets logger into JobManager -func (j *JobManager) SetLogger(logger *logging.Logger) *JobManager { +func (j *JobManager) SetLogger(logger LoggerInterface) *JobManager { if logger != nil { j.logger = logger } diff --git a/core/job_manager_test.go b/core/job_manager_test.go index fc994dc..5ca079a 100644 --- a/core/job_manager_test.go +++ b/core/job_manager_test.go @@ -324,10 +324,10 @@ func (t *JobManagerTest) ranFlag() bool { func (t *JobManagerTest) Test_SetLogger() { t.manager.logger = nil t.manager.SetLogger(NewLogger("test", logging.ERROR, DefaultLogFormatter())) - assert.IsType(t.T(), &logging.Logger{}, t.manager.logger) + assert.IsType(t.T(), &Logger{}, t.manager.logger) t.manager.SetLogger(nil) - assert.IsType(t.T(), &logging.Logger{}, t.manager.logger) + assert.IsType(t.T(), &Logger{}, t.manager.logger) } func (t *JobManagerTest) Test_SetLogging() { diff --git a/core/localizer.go b/core/localizer.go index 321f492..e06d891 100644 --- a/core/localizer.go +++ b/core/localizer.go @@ -39,6 +39,23 @@ func NewLocalizer(locale language.Tag, bundle *i18n.Bundle, matcher language.Mat return localizer } +// NewLocalizerFS returns localizer instance with specified parameters. *packr.Box should be used instead of directory. +// Usage: +// NewLocalizerFS(language.English, DefaultLocalizerBundle(), DefaultLocalizerMatcher(), translationsBox) +// TODO This code should be covered with tests. +func NewLocalizerFS(locale language.Tag, bundle *i18n.Bundle, matcher language.Matcher, translationsBox *packr.Box) *Localizer { + localizer := &Localizer{ + i18n: nil, + LocaleBundle: bundle, + LocaleMatcher: matcher, + TranslationsBox: translationsBox, + } + localizer.SetLanguage(locale) + localizer.LoadTranslations() + + return localizer +} + // DefaultLocalizerBundle returns new localizer bundle with English as default language func DefaultLocalizerBundle() *i18n.Bundle { return i18n.NewBundle(language.English) diff --git a/core/logger.go b/core/logger.go index 7c16627..0e9ea1c 100644 --- a/core/logger.go +++ b/core/logger.go @@ -2,14 +2,49 @@ package core import ( "os" + "sync" "github.com/op/go-logging" ) -// NewLogger will create new logger with specified formatter. +// LoggerInterface contains methods which should be present in logger implementation +type LoggerInterface interface { + Fatal(args ...interface{}) + Fatalf(format string, args ...interface{}) + Panic(args ...interface{}) + Panicf(format string, args ...interface{}) + Critical(args ...interface{}) + Criticalf(format string, args ...interface{}) + Error(args ...interface{}) + Errorf(format string, args ...interface{}) + Warning(args ...interface{}) + Warningf(format string, args ...interface{}) + Notice(args ...interface{}) + Noticef(format string, args ...interface{}) + Info(args ...interface{}) + Infof(format string, args ...interface{}) + Debug(args ...interface{}) + Debugf(format string, args ...interface{}) +} + +// Logger component. Uses github.com/op/go-logging under the hood. +type Logger struct { + logger *logging.Logger + mutex *sync.RWMutex +} + +// NewLogger will create new goroutine-safe logger with specified formatter. // Usage: // logger := NewLogger("telegram", logging.ERROR, DefaultLogFormatter()) -func NewLogger(transportCode string, logLevel logging.Level, logFormat logging.Formatter) *logging.Logger { +func NewLogger(transportCode string, logLevel logging.Level, logFormat logging.Formatter) *Logger { + return &Logger{ + logger: newInheritedLogger(transportCode, logLevel, logFormat), + mutex: &sync.RWMutex{}, + } +} + +// newInheritedLogger is a constructor for underlying logger in Logger struct. +func newInheritedLogger(transportCode string, logLevel logging.Level, logFormat logging.Formatter) *logging.Logger { logger := logging.MustGetLogger(transportCode) logBackend := logging.NewLogBackend(os.Stdout, "", 0) formatBackend := logging.NewBackendFormatter(logBackend, logFormat) @@ -26,3 +61,114 @@ func DefaultLogFormatter() logging.Formatter { `%{time:2006-01-02 15:04:05.000} %{level:.4s} => %{message}`, ) } + +// Fatal is equivalent to l.Critical(fmt.Sprint()) followed by a call to os.Exit(1). +func (l *Logger) Fatal(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Fatal(args...) +} + +// Fatalf is equivalent to l.Critical followed by a call to os.Exit(1). +func (l *Logger) Fatalf(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Fatalf(format, args...) +} + +// Panic is equivalent to l.Critical(fmt.Sprint()) followed by a call to panic(). +func (l *Logger) Panic(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Panic(args...) +} + +// Panicf is equivalent to l.Critical followed by a call to panic(). +func (l *Logger) Panicf(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Panicf(format, args...) +} + +// Critical logs a message using CRITICAL as log level. +func (l *Logger) Critical(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Critical(args...) +} + +// Criticalf logs a message using CRITICAL as log level. +func (l *Logger) Criticalf(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Criticalf(format, args...) +} + +// Error logs a message using ERROR as log level. +func (l *Logger) Error(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Error(args...) +} + +// Errorf logs a message using ERROR as log level. +func (l *Logger) Errorf(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Errorf(format, args...) +} + +// Warning logs a message using WARNING as log level. +func (l *Logger) Warning(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Warning(args...) +} + +func (l *Logger) Warningf(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Warningf(format, args...) +} + +// Warningf logs a message using WARNING as log level. +func (l *Logger) Notice(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Notice(args...) +} + +// Noticef logs a message using NOTICE as log level. +func (l *Logger) Noticef(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Noticef(format, args...) +} + +// Info logs a message using INFO as log level. +func (l *Logger) Info(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Info(args...) +} + +// Infof logs a message using INFO as log level. +func (l *Logger) Infof(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Infof(format, args...) +} + +// Debug logs a message using DEBUG as log level. +func (l *Logger) Debug(args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Debug(args...) +} + +// Debugf logs a message using DEBUG as log level. +func (l *Logger) Debugf(format string, args ...interface{}) { + l.mutex.Lock() + defer l.mutex.Unlock() + l.logger.Debugf(format, args...) +} diff --git a/core/sentry.go b/core/sentry.go index 377062a..637251a 100644 --- a/core/sentry.go +++ b/core/sentry.go @@ -13,7 +13,6 @@ import ( "github.com/getsentry/raven-go" "github.com/gin-gonic/gin" - "github.com/op/go-logging" ) // ErrorHandlerFunc will handle errors @@ -39,7 +38,7 @@ type Sentry struct { Stacktrace bool DefaultError string Localizer *Localizer - Logger *logging.Logger + Logger LoggerInterface Client *raven.Client } @@ -57,7 +56,7 @@ type SentryTaggedScalar struct { } // NewSentry constructor -func NewSentry(sentryDSN string, defaultError string, taggedTypes SentryTaggedTypes, logger *logging.Logger, localizer *Localizer) *Sentry { +func NewSentry(sentryDSN string, defaultError string, taggedTypes SentryTaggedTypes, logger LoggerInterface, localizer *Localizer) *Sentry { sentry := &Sentry{ DefaultError: defaultError, TaggedTypes: taggedTypes, diff --git a/core/utils.go b/core/utils.go index c0161e6..a963f1e 100644 --- a/core/utils.go +++ b/core/utils.go @@ -17,7 +17,6 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3/s3manager" - "github.com/op/go-logging" v5 "github.com/retailcrm/api-client-go/v5" v1 "github.com/retailcrm/mg-transport-api-client-go/v1" ) @@ -27,12 +26,12 @@ type Utils struct { IsDebug bool TokenCounter uint32 ConfigAWS ConfigAWS - Logger *logging.Logger + Logger LoggerInterface slashRegex *regexp.Regexp } // NewUtils will create new Utils instance -func NewUtils(awsConfig ConfigAWS, logger *logging.Logger, debug bool) *Utils { +func NewUtils(awsConfig ConfigAWS, logger LoggerInterface, debug bool) *Utils { return &Utils{ IsDebug: debug, ConfigAWS: awsConfig,