mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2024-11-22 05:06:04 +03:00
integrate zap logger
This commit is contained in:
parent
2455c11704
commit
96ac6a6940
@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log/slog"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -15,6 +14,7 @@ import (
|
|||||||
"github.com/gorilla/securecookie"
|
"github.com/gorilla/securecookie"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
"github.com/retailcrm/zabbix-metrics-collector"
|
"github.com/retailcrm/zabbix-metrics-collector"
|
||||||
|
"go.uber.org/zap"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
||||||
@ -141,13 +141,9 @@ func (e *Engine) Prepare() *Engine {
|
|||||||
e.Localizer.Preload(e.PreloadLanguages)
|
e.Localizer.Preload(e.PreloadLanguages)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !e.Config.IsDebug() {
|
|
||||||
logger.DefaultOpts.Level = slog.LevelInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
e.CreateDB(e.Config.GetDBConfig())
|
e.CreateDB(e.Config.GetDBConfig())
|
||||||
e.ResetUtils(e.Config.GetAWSConfig(), e.Config.IsDebug(), 0)
|
e.ResetUtils(e.Config.GetAWSConfig(), e.Config.IsDebug(), 0)
|
||||||
e.SetLogger(logger.NewDefaultText())
|
e.SetLogger(logger.NewDefault(e.Config.IsDebug()))
|
||||||
e.Sentry.Localizer = &e.Localizer
|
e.Sentry.Localizer = &e.Localizer
|
||||||
e.Utils.Logger = e.Logger()
|
e.Utils.Logger = e.Logger()
|
||||||
e.Sentry.Logger = e.Logger()
|
e.Sentry.Logger = e.Logger()
|
||||||
@ -180,14 +176,14 @@ func (e *Engine) HijackGinLogs() *Engine {
|
|||||||
if e.Logger() == nil {
|
if e.Logger() == nil {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
gin.DefaultWriter = logger.WriterAdapter(e.Logger(), slog.LevelDebug)
|
gin.DefaultWriter = logger.WriterAdapter(e.Logger(), zap.DebugLevel)
|
||||||
gin.DefaultErrorWriter = logger.WriterAdapter(e.Logger(), slog.LevelError)
|
gin.DefaultErrorWriter = logger.WriterAdapter(e.Logger(), zap.ErrorLevel)
|
||||||
gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
|
gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
|
||||||
e.Logger().Debug("route",
|
e.Logger().Debug("route",
|
||||||
slog.String(logger.HTTPMethodAttr, httpMethod),
|
zap.String(logger.HTTPMethodAttr, httpMethod),
|
||||||
slog.String("path", absolutePath),
|
zap.String("path", absolutePath),
|
||||||
slog.String(logger.HandlerAttr, handlerName),
|
zap.String(logger.HandlerAttr, handlerName),
|
||||||
slog.Int("handlerCount", nuHandlers))
|
zap.Int("handlerCount", nuHandlers))
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ func (e *EngineTest) Test_SetLogger() {
|
|||||||
defer func() {
|
defer func() {
|
||||||
e.engine.logger = origLogger
|
e.engine.logger = origLogger
|
||||||
}()
|
}()
|
||||||
e.engine.logger = logger.NewDefaultNil()
|
e.engine.logger = logger.NewNil()
|
||||||
e.engine.SetLogger(nil)
|
e.engine.SetLogger(nil)
|
||||||
assert.NotNil(e.T(), e.engine.logger)
|
assert.NotNil(e.T(), e.engine.logger)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package healthcheck
|
package healthcheck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -31,19 +30,19 @@ type CounterProcessor struct {
|
|||||||
func (c CounterProcessor) Process(id int, counter Counter) bool { // nolint:varnamelen
|
func (c CounterProcessor) Process(id int, counter Counter) bool { // nolint:varnamelen
|
||||||
if counter.IsFailed() {
|
if counter.IsFailed() {
|
||||||
if counter.IsFailureProcessed() {
|
if counter.IsFailureProcessed() {
|
||||||
c.debugLog("skipping counter because its failure is already processed", slog.Int(logger.CounterIDAttr, id))
|
c.debugLog("skipping counter because its failure is already processed", zap.Int(logger.CounterIDAttr, id))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
apiURL, apiKey, _, exists := c.ConnectionDataProvider(id)
|
apiURL, apiKey, _, exists := c.ConnectionDataProvider(id)
|
||||||
if !exists {
|
if !exists {
|
||||||
c.debugLog("cannot find connection data for counter", slog.Int(logger.CounterIDAttr, id))
|
c.debugLog("cannot find connection data for counter", zap.Int(logger.CounterIDAttr, id))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
err := c.Notifier(apiURL, apiKey, counter.Message())
|
err := c.Notifier(apiURL, apiKey, counter.Message())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.debugLog("cannot send notification for counter",
|
c.debugLog("cannot send notification for counter",
|
||||||
slog.Int(logger.CounterIDAttr, id), logger.Err(err), slog.String(logger.FailureMessageAttr, counter.Message()))
|
zap.Int(logger.CounterIDAttr, id), logger.Err(err), zap.String(logger.FailureMessageAttr, counter.Message()))
|
||||||
}
|
}
|
||||||
counter.FailureProcessed()
|
counter.FailureProcessed()
|
||||||
return true
|
return true
|
||||||
@ -56,7 +55,7 @@ func (c CounterProcessor) Process(id int, counter Counter) bool { // nolint:varn
|
|||||||
// The results may not be representative.
|
// The results may not be representative.
|
||||||
if (succeeded + failed) < c.MinRequests {
|
if (succeeded + failed) < c.MinRequests {
|
||||||
c.debugLog("skipping counter because it has too few requests",
|
c.debugLog("skipping counter because it has too few requests",
|
||||||
slog.Int(logger.CounterIDAttr, id), slog.Any("minRequests", c.MinRequests))
|
zap.Int(logger.CounterIDAttr, id), zap.Any("minRequests", c.MinRequests))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,13 +74,13 @@ func (c CounterProcessor) Process(id int, counter Counter) bool { // nolint:varn
|
|||||||
|
|
||||||
apiURL, apiKey, lang, exists := c.ConnectionDataProvider(id)
|
apiURL, apiKey, lang, exists := c.ConnectionDataProvider(id)
|
||||||
if !exists {
|
if !exists {
|
||||||
c.debugLog("cannot find connection data for counter", slog.Int(logger.CounterIDAttr, id))
|
c.debugLog("cannot find connection data for counter", zap.Int(logger.CounterIDAttr, id))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
err := c.Notifier(apiURL, apiKey, c.getErrorText(counter.Name(), c.Error, lang))
|
err := c.Notifier(apiURL, apiKey, c.getErrorText(counter.Name(), c.Error, lang))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.debugLog("cannot send notification for counter",
|
c.debugLog("cannot send notification for counter",
|
||||||
slog.Int(logger.CounterIDAttr, id), logger.Err(err), slog.String(logger.FailureMessageAttr, counter.Message()))
|
zap.Int(logger.CounterIDAttr, id), logger.Err(err), zap.String(logger.FailureMessageAttr, counter.Message()))
|
||||||
}
|
}
|
||||||
counter.CountersProcessed()
|
counter.CountersProcessed()
|
||||||
return true
|
return true
|
||||||
@ -99,6 +98,6 @@ func (c CounterProcessor) getErrorText(name, msg, lang string) string {
|
|||||||
|
|
||||||
func (c CounterProcessor) debugLog(msg string, args ...interface{}) {
|
func (c CounterProcessor) debugLog(msg string, args ...interface{}) {
|
||||||
if c.Debug {
|
if c.Debug {
|
||||||
c.Logger.Debug(msg, args...)
|
c.Logger.Debug(msg, logger.AnyZapFields(args)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ func (t *CounterProcessorTest) Test_FailureProcessed() {
|
|||||||
p.Process(1, c)
|
p.Process(1, c)
|
||||||
c.AssertExpectations(t.T())
|
c.AssertExpectations(t.T())
|
||||||
t.Assert().Contains(log.String(), "skipping counter because its failure is already processed")
|
t.Assert().Contains(log.String(), "skipping counter because its failure is already processed")
|
||||||
t.Assert().Contains(log.String(), "counterId=1")
|
t.Assert().Contains(log.String(), `"counterId": 1`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *CounterProcessorTest) Test_CounterFailed_CannotFindConnection() {
|
func (t *CounterProcessorTest) Test_CounterFailed_CannotFindConnection() {
|
||||||
@ -109,7 +109,7 @@ func (t *CounterProcessorTest) Test_CounterFailed_CannotFindConnection() {
|
|||||||
p.Process(1, c)
|
p.Process(1, c)
|
||||||
c.AssertExpectations(t.T())
|
c.AssertExpectations(t.T())
|
||||||
t.Assert().Contains(log.String(), "cannot find connection data for counter")
|
t.Assert().Contains(log.String(), "cannot find connection data for counter")
|
||||||
t.Assert().Contains(log.String(), "counterId=1")
|
t.Assert().Contains(log.String(), `"counterId": 1`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *CounterProcessorTest) Test_CounterFailed_ErrWhileNotifying() {
|
func (t *CounterProcessorTest) Test_CounterFailed_ErrWhileNotifying() {
|
||||||
@ -124,9 +124,9 @@ func (t *CounterProcessorTest) Test_CounterFailed_ErrWhileNotifying() {
|
|||||||
p.Process(1, c)
|
p.Process(1, c)
|
||||||
c.AssertExpectations(t.T())
|
c.AssertExpectations(t.T())
|
||||||
t.Assert().Contains(log.String(), "cannot send notification for counter")
|
t.Assert().Contains(log.String(), "cannot send notification for counter")
|
||||||
t.Assert().Contains(log.String(), "counterId=1")
|
t.Assert().Contains(log.String(), `"counterId": 1`)
|
||||||
t.Assert().Contains(log.String(), `error="http status code: 500"`)
|
t.Assert().Contains(log.String(), `"error": "http status code: 500"`)
|
||||||
t.Assert().Contains(log.String(), `failureMessage="error message"`)
|
t.Assert().Contains(log.String(), `"failureMessage": "error message"`)
|
||||||
t.Assert().Equal(t.apiURL, n.apiURL)
|
t.Assert().Equal(t.apiURL, n.apiURL)
|
||||||
t.Assert().Equal(t.apiKey, n.apiKey)
|
t.Assert().Equal(t.apiKey, n.apiKey)
|
||||||
t.Assert().Equal("error message", n.message)
|
t.Assert().Equal("error message", n.message)
|
||||||
@ -160,7 +160,7 @@ func (t *CounterProcessorTest) Test_TooFewRequests() {
|
|||||||
p.Process(1, c)
|
p.Process(1, c)
|
||||||
c.AssertExpectations(t.T())
|
c.AssertExpectations(t.T())
|
||||||
t.Assert().Contains(log.String(),
|
t.Assert().Contains(log.String(),
|
||||||
fmt.Sprintf(`msg="skipping counter because it has too few requests" counterId=%d minRequests=%d`, 1, DefaultMinRequests))
|
fmt.Sprintf(`skipping counter because it has too few requests {"counterId": %d, "minRequests": %d}`, 1, DefaultMinRequests))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *CounterProcessorTest) Test_ThresholdNotPassed() {
|
func (t *CounterProcessorTest) Test_ThresholdNotPassed() {
|
||||||
@ -206,7 +206,7 @@ func (t *CounterProcessorTest) Test_ThresholdPassed_NoConnectionFound() {
|
|||||||
p.Process(1, c)
|
p.Process(1, c)
|
||||||
c.AssertExpectations(t.T())
|
c.AssertExpectations(t.T())
|
||||||
t.Assert().Contains(log.String(), "cannot find connection data for counter")
|
t.Assert().Contains(log.String(), "cannot find connection data for counter")
|
||||||
t.Assert().Contains(log.String(), "counterId=1")
|
t.Assert().Contains(log.String(), `"counterId": 1`)
|
||||||
t.Assert().Empty(n.message)
|
t.Assert().Empty(n.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ func (t *CounterProcessorTest) Test_ThresholdPassed_NotifyingError() {
|
|||||||
|
|
||||||
p.Process(1, c)
|
p.Process(1, c)
|
||||||
c.AssertExpectations(t.T())
|
c.AssertExpectations(t.T())
|
||||||
t.Assert().Contains(log.String(), `msg="cannot send notification for counter" counterId=1 error="unknown error" failureMessage=""`)
|
t.Assert().Contains(log.String(), `cannot send notification for counter {"counterId": 1, "error": "unknown error", "failureMessage": ""}`)
|
||||||
t.Assert().Equal(`default error [{"Name":"MockedCounter"}]`, n.message)
|
t.Assert().Equal(`default error [{"Name":"MockedCounter"}]`, n.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,11 @@ package core
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobFunc is empty func which should be executed in a parallel goroutine.
|
// JobFunc is empty func which should be executed in a parallel goroutine.
|
||||||
@ -74,7 +74,7 @@ func (j *Job) getWrappedFunc(name string, log logger.Logger) func(callback JobAf
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log = log.With(logger.HandlerAttr, name)
|
log = log.With(logger.Handler(name))
|
||||||
err := j.Command(log)
|
err := j.Command(log)
|
||||||
if err != nil && j.ErrorHandler != nil {
|
if err != nil && j.ErrorHandler != nil {
|
||||||
j.ErrorHandler(name, err, log)
|
j.ErrorHandler(name, err, log)
|
||||||
@ -148,14 +148,14 @@ func (j *Job) runOnceSync(name string, log logger.Logger) {
|
|||||||
|
|
||||||
// NewJobManager is a JobManager constructor.
|
// NewJobManager is a JobManager constructor.
|
||||||
func NewJobManager() *JobManager {
|
func NewJobManager() *JobManager {
|
||||||
return &JobManager{jobs: &sync.Map{}, nilLogger: logger.NewDefaultNil()}
|
return &JobManager{jobs: &sync.Map{}, nilLogger: logger.NewNil()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultJobErrorHandler returns default error handler for a job.
|
// DefaultJobErrorHandler returns default error handler for a job.
|
||||||
func DefaultJobErrorHandler() JobErrorHandler {
|
func DefaultJobErrorHandler() JobErrorHandler {
|
||||||
return func(name string, err error, log logger.Logger) {
|
return func(name string, err error, log logger.Logger) {
|
||||||
if err != nil && name != "" {
|
if err != nil && name != "" {
|
||||||
log.Error("job failed with an error", slog.String("job", name), logger.Err(err))
|
log.Error("job failed with an error", zap.String("job", name), logger.Err(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ func DefaultJobErrorHandler() JobErrorHandler {
|
|||||||
func DefaultJobPanicHandler() JobPanicHandler {
|
func DefaultJobPanicHandler() JobPanicHandler {
|
||||||
return func(name string, recoverValue interface{}, log logger.Logger) {
|
return func(name string, recoverValue interface{}, log logger.Logger) {
|
||||||
if recoverValue != nil && name != "" {
|
if recoverValue != nil && name != "" {
|
||||||
log.Error("job panicked with the value", slog.String("job", name), slog.Any("value", recoverValue))
|
log.Error("job panicked with the value", zap.String("job", name), zap.Any("value", recoverValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -14,6 +12,8 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
||||||
)
|
)
|
||||||
@ -26,7 +26,7 @@ type JobTest struct {
|
|||||||
executeErr chan error
|
executeErr chan error
|
||||||
panicValue chan interface{}
|
panicValue chan interface{}
|
||||||
lastLog string
|
lastLog string
|
||||||
lastMsgLevel slog.Level
|
lastMsgLevel zapcore.Level
|
||||||
syncBool bool
|
syncBool bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,18 +37,58 @@ type JobManagerTest struct {
|
|||||||
syncRunnerFlag bool
|
syncRunnerFlag bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type callbackLoggerFunc func(ctx context.Context, level slog.Level, msg string, args ...any)
|
type callbackLoggerFunc func(level zapcore.Level, msg string, args ...zap.Field)
|
||||||
|
|
||||||
type callbackLogger struct {
|
type callbackLogger struct {
|
||||||
fn callbackLoggerFunc
|
fields []zap.Field
|
||||||
|
fn callbackLoggerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) Handler() slog.Handler {
|
func (n *callbackLogger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
|
||||||
return logger.NilHandler
|
return &zapcore.CheckedEntry{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) With(args ...any) logger.Logger {
|
func (n *callbackLogger) DPanic(msg string, fields ...zap.Field) {
|
||||||
return n
|
n.fn(zap.PanicLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) Panic(msg string, fields ...zap.Field) {
|
||||||
|
n.fn(zap.PanicLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) Fatal(msg string, fields ...zap.Field) {
|
||||||
|
n.fn(zap.FatalLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) Sync() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) clone() *callbackLogger {
|
||||||
|
return &callbackLogger{fn: n.fn, fields: n.fields}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) cloneWithFields(fields []zap.Field) *callbackLogger {
|
||||||
|
cl := &callbackLogger{fn: n.fn, fields: n.fields}
|
||||||
|
existing := cl.fields
|
||||||
|
if len(existing) == 0 {
|
||||||
|
cl.fields = fields
|
||||||
|
return cl
|
||||||
|
}
|
||||||
|
cl.fields = append(existing, fields...)
|
||||||
|
return cl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) Level() zapcore.Level {
|
||||||
|
return zapcore.DebugLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) With(args ...zap.Field) logger.Logger {
|
||||||
|
return n.cloneWithFields(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *callbackLogger) WithLazy(args ...zap.Field) logger.Logger {
|
||||||
|
return n.cloneWithFields(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) WithGroup(name string) logger.Logger {
|
func (n *callbackLogger) WithGroup(name string) logger.Logger {
|
||||||
@ -59,47 +99,24 @@ func (n *callbackLogger) ForAccount(handler, conn, acc any) logger.Logger {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) Enabled(ctx context.Context, level slog.Level) bool {
|
func (n *callbackLogger) Log(level zapcore.Level, msg string, args ...zap.Field) {
|
||||||
return true
|
n.fn(level, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) Log(ctx context.Context, level slog.Level, msg string, args ...any) {
|
func (n *callbackLogger) Debug(msg string, args ...zap.Field) {
|
||||||
n.fn(ctx, level, msg, args...)
|
n.Log(zap.DebugLevel, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr) {
|
func (n *callbackLogger) Info(msg string, args ...zap.Field) {
|
||||||
|
n.Log(zap.InfoLevel, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) Debug(msg string, args ...any) {
|
func (n *callbackLogger) Warn(msg string, args ...zap.Field) {
|
||||||
n.Log(nil, slog.LevelDebug, msg, args...)
|
n.Log(zap.WarnLevel, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *callbackLogger) DebugContext(ctx context.Context, msg string, args ...any) {
|
func (n *callbackLogger) Error(msg string, args ...zap.Field) {
|
||||||
n.Log(ctx, slog.LevelDebug, msg, args...)
|
n.Log(zap.ErrorLevel, msg, args...)
|
||||||
}
|
|
||||||
|
|
||||||
func (n *callbackLogger) Info(msg string, args ...any) {
|
|
||||||
n.Log(nil, slog.LevelInfo, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *callbackLogger) InfoContext(ctx context.Context, msg string, args ...any) {
|
|
||||||
n.Log(ctx, slog.LevelInfo, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *callbackLogger) Warn(msg string, args ...any) {
|
|
||||||
n.Log(nil, slog.LevelWarn, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *callbackLogger) WarnContext(ctx context.Context, msg string, args ...any) {
|
|
||||||
n.Log(ctx, slog.LevelWarn, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *callbackLogger) Error(msg string, args ...any) {
|
|
||||||
n.Log(nil, slog.LevelError, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *callbackLogger) ErrorContext(ctx context.Context, msg string, args ...any) {
|
|
||||||
n.Log(ctx, slog.LevelError, msg, args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJob(t *testing.T) {
|
func TestJob(t *testing.T) {
|
||||||
@ -117,9 +134,9 @@ func TestDefaultJobErrorHandler(t *testing.T) {
|
|||||||
|
|
||||||
fn := DefaultJobErrorHandler()
|
fn := DefaultJobErrorHandler()
|
||||||
require.NotNil(t, fn)
|
require.NotNil(t, fn)
|
||||||
fn("job", errors.New("test"), &callbackLogger{fn: func(_ context.Context, level slog.Level, s string, i ...interface{}) {
|
fn("job", errors.New("test"), &callbackLogger{fn: func(level zapcore.Level, s string, i ...zap.Field) {
|
||||||
require.Len(t, i, 2)
|
require.Len(t, i, 2)
|
||||||
assert.Equal(t, "error=test", fmt.Sprintf("%s", i[1]))
|
assert.Equal(t, "error=test", fmt.Sprintf("%s=%v", i[1].Key, i[1].Interface))
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,9 +147,9 @@ func TestDefaultJobPanicHandler(t *testing.T) {
|
|||||||
|
|
||||||
fn := DefaultJobPanicHandler()
|
fn := DefaultJobPanicHandler()
|
||||||
require.NotNil(t, fn)
|
require.NotNil(t, fn)
|
||||||
fn("job", errors.New("test"), &callbackLogger{fn: func(_ context.Context, level slog.Level, s string, i ...interface{}) {
|
fn("job", errors.New("test"), &callbackLogger{fn: func(level zapcore.Level, s string, i ...zap.Field) {
|
||||||
require.Len(t, i, 2)
|
require.Len(t, i, 2)
|
||||||
assert.Equal(t, "value=test", fmt.Sprintf("%s", i[1]))
|
assert.Equal(t, "value=test", fmt.Sprintf("%s=%s", i[1].Key, i[1].Interface))
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +166,7 @@ func (t *JobTest) testPanicHandler() JobPanicHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *JobTest) testLogger() logger.Logger {
|
func (t *JobTest) testLogger() logger.Logger {
|
||||||
return &callbackLogger{fn: func(_ context.Context, level slog.Level, format string, args ...interface{}) {
|
return &callbackLogger{fn: func(level zapcore.Level, format string, args ...zap.Field) {
|
||||||
if format == "" {
|
if format == "" {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
sb.Grow(3 * len(args)) // nolint:gomnd
|
sb.Grow(3 * len(args)) // nolint:gomnd
|
||||||
@ -161,7 +178,12 @@ func (t *JobTest) testLogger() logger.Logger {
|
|||||||
format = strings.TrimRight(sb.String(), " ")
|
format = strings.TrimRight(sb.String(), " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
t.lastLog = fmt.Sprintf(format, args...)
|
anyFields := []any{}
|
||||||
|
for _, item := range args {
|
||||||
|
anyFields = append(anyFields, item.Key+"="+fmt.Sprint(item.Interface))
|
||||||
|
}
|
||||||
|
|
||||||
|
t.lastLog = fmt.Sprintf(format, anyFields...)
|
||||||
t.lastMsgLevel = level
|
t.lastMsgLevel = level
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -406,7 +428,7 @@ func (t *JobManagerTest) WaitForJob() bool {
|
|||||||
|
|
||||||
func (t *JobManagerTest) Test_SetLogger() {
|
func (t *JobManagerTest) Test_SetLogger() {
|
||||||
t.manager.logger = nil
|
t.manager.logger = nil
|
||||||
t.manager.SetLogger(logger.NewDefaultText())
|
t.manager.SetLogger(logger.NewDefault(true))
|
||||||
assert.IsType(t.T(), &logger.Default{}, t.manager.logger)
|
assert.IsType(t.T(), &logger.Default{}, t.manager.logger)
|
||||||
|
|
||||||
t.manager.SetLogger(nil)
|
t.manager.SetLogger(nil)
|
||||||
|
@ -2,8 +2,9 @@ package logger
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -19,28 +20,32 @@ const (
|
|||||||
HTTPStatusNameAttr = "statusName"
|
HTTPStatusNameAttr = "statusName"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Err(err any) slog.Attr {
|
func Err(err any) zap.Field {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return slog.String(ErrorAttr, "<nil>")
|
return zap.String(ErrorAttr, "<nil>")
|
||||||
}
|
}
|
||||||
return slog.Any(ErrorAttr, err)
|
return zap.Any(ErrorAttr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HTTPStatusCode(code int) slog.Attr {
|
func Handler(name string) zap.Field {
|
||||||
return slog.Int(HTTPStatusAttr, code)
|
return zap.String(HandlerAttr, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HTTPStatusName(code int) slog.Attr {
|
func HTTPStatusCode(code int) zap.Field {
|
||||||
return slog.String(HTTPStatusNameAttr, http.StatusText(code))
|
return zap.Int(HTTPStatusAttr, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Body(val any) slog.Attr {
|
func HTTPStatusName(code int) zap.Field {
|
||||||
|
return zap.String(HTTPStatusNameAttr, http.StatusText(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Body(val any) zap.Field {
|
||||||
switch item := val.(type) {
|
switch item := val.(type) {
|
||||||
case string:
|
case string:
|
||||||
return slog.String(BodyAttr, item)
|
return zap.String(BodyAttr, item)
|
||||||
case []byte:
|
case []byte:
|
||||||
return slog.String(BodyAttr, string(item))
|
return zap.String(BodyAttr, string(item))
|
||||||
default:
|
default:
|
||||||
return slog.String(BodyAttr, fmt.Sprintf("%#v", val))
|
return zap.String(BodyAttr, fmt.Sprintf("%#v", val))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,87 +1,59 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"strconv"
|
||||||
"log/slog"
|
|
||||||
"os"
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Logger interface {
|
||||||
|
With(fields ...zap.Field) Logger
|
||||||
|
WithLazy(fields ...zap.Field) Logger
|
||||||
|
Level() zapcore.Level
|
||||||
|
Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry
|
||||||
|
Log(lvl zapcore.Level, msg string, fields ...zap.Field)
|
||||||
|
Debug(msg string, fields ...zap.Field)
|
||||||
|
Info(msg string, fields ...zap.Field)
|
||||||
|
Warn(msg string, fields ...zap.Field)
|
||||||
|
Error(msg string, fields ...zap.Field)
|
||||||
|
DPanic(msg string, fields ...zap.Field)
|
||||||
|
Panic(msg string, fields ...zap.Field)
|
||||||
|
Fatal(msg string, fields ...zap.Field)
|
||||||
|
ForAccount(handler, conn, acc any) Logger
|
||||||
|
Sync() error
|
||||||
|
}
|
||||||
|
|
||||||
type Default struct {
|
type Default struct {
|
||||||
Logger *slog.Logger
|
*zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefault(log *slog.Logger) Logger {
|
func NewDefault(debug bool) Logger {
|
||||||
return &Default{Logger: log}
|
return &Default{
|
||||||
|
Logger: NewZap(debug),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultText() Logger {
|
func (l *Default) With(fields ...zap.Field) Logger {
|
||||||
return NewDefault(slog.New(slog.NewTextHandler(os.Stdout, DefaultOpts)))
|
return l.With(fields...).(Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultJSON() Logger {
|
func (l *Default) WithLazy(fields ...zap.Field) Logger {
|
||||||
return NewDefault(slog.New(slog.NewJSONHandler(os.Stdout, DefaultOpts)))
|
return l.WithLazy(fields...).(Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultNil() Logger {
|
func (l *Default) ForAccount(handler, conn, acc any) Logger {
|
||||||
return NewDefault(slog.New(NilHandler))
|
return l.WithLazy(zap.Any(HandlerAttr, handler), zap.Any(ConnectionAttr, conn), zap.Any(AccountAttr, acc))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Default) Handler() slog.Handler {
|
func AnyZapFields(args []interface{}) []zap.Field {
|
||||||
return d.Logger.Handler()
|
fields := make([]zap.Field, len(args))
|
||||||
}
|
for i := 0; i < len(fields); i++ {
|
||||||
|
if val, ok := args[i].(zap.Field); ok {
|
||||||
func (d *Default) ForAccount(handler, conn, acc any) Logger {
|
fields[i] = val
|
||||||
return d.With(slog.Any(HandlerAttr, handler), slog.Any(ConnectionAttr, conn), slog.Any(AccountAttr, acc))
|
continue
|
||||||
}
|
}
|
||||||
|
fields[i] = zap.Any("arg"+strconv.Itoa(i), args[i])
|
||||||
func (d *Default) With(args ...any) Logger {
|
}
|
||||||
return &Default{Logger: d.Logger.With(args...)}
|
return fields
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) WithGroup(name string) Logger {
|
|
||||||
return &Default{Logger: d.Logger.WithGroup(name)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) Enabled(ctx context.Context, level slog.Level) bool {
|
|
||||||
return d.Logger.Enabled(ctx, level)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) Log(ctx context.Context, level slog.Level, msg string, args ...any) {
|
|
||||||
d.Logger.Log(ctx, level, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr) {
|
|
||||||
d.Logger.LogAttrs(ctx, level, msg, attrs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) Debug(msg string, args ...any) {
|
|
||||||
d.Logger.Debug(msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) DebugContext(ctx context.Context, msg string, args ...any) {
|
|
||||||
d.Logger.DebugContext(ctx, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) Info(msg string, args ...any) {
|
|
||||||
d.Logger.Info(msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) InfoContext(ctx context.Context, msg string, args ...any) {
|
|
||||||
d.Logger.InfoContext(ctx, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) Warn(msg string, args ...any) {
|
|
||||||
d.Logger.Warn(msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) WarnContext(ctx context.Context, msg string, args ...any) {
|
|
||||||
d.Logger.WarnContext(ctx, msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) Error(msg string, args ...any) {
|
|
||||||
d.Logger.Error(msg, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Default) ErrorContext(ctx context.Context, msg string, args ...any) {
|
|
||||||
d.Logger.ErrorContext(ctx, msg, args...)
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"log/slog"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GinMiddleware will construct Gin middleware which will log requests.
|
// GinMiddleware will construct Gin middleware which will log requests.
|
||||||
@ -23,14 +24,14 @@ func GinMiddleware(log Logger) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Info("request",
|
log.Info("request",
|
||||||
slog.String(HandlerAttr, "GIN"),
|
zap.String(HandlerAttr, "GIN"),
|
||||||
slog.String("startTime", start.Format(time.RFC3339)),
|
zap.String("startTime", start.Format(time.RFC3339)),
|
||||||
slog.String("endTime", end.Format(time.RFC3339)),
|
zap.String("endTime", end.Format(time.RFC3339)),
|
||||||
slog.Any("latency", end.Sub(start)/time.Millisecond),
|
zap.Any("latency", end.Sub(start)/time.Millisecond),
|
||||||
slog.String("remoteAddress", c.ClientIP()),
|
zap.String("remoteAddress", c.ClientIP()),
|
||||||
slog.String(HTTPMethodAttr, c.Request.Method),
|
zap.String(HTTPMethodAttr, c.Request.Method),
|
||||||
slog.String("path", path),
|
zap.String("path", path),
|
||||||
slog.Int("bodySize", c.Writer.Size()),
|
zap.Int("bodySize", c.Writer.Size()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
package logger
|
|
||||||
|
|
||||||
import "log/slog"
|
|
||||||
|
|
||||||
var DefaultOpts = &slog.HandlerOptions{
|
|
||||||
AddSource: false,
|
|
||||||
Level: slog.LevelDebug,
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package logger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoggerOld contains methods which should be present in logger implementation.
|
|
||||||
type LoggerOld interface {
|
|
||||||
Fatal(args ...any)
|
|
||||||
Fatalf(format string, args ...any)
|
|
||||||
Panic(args ...any)
|
|
||||||
Panicf(format string, args ...any)
|
|
||||||
Critical(args ...any)
|
|
||||||
Criticalf(format string, args ...any)
|
|
||||||
Error(args ...any)
|
|
||||||
Errorf(format string, args ...any)
|
|
||||||
Warning(args ...any)
|
|
||||||
Warningf(format string, args ...any)
|
|
||||||
Notice(args ...any)
|
|
||||||
Noticef(format string, args ...any)
|
|
||||||
Info(args ...any)
|
|
||||||
Infof(format string, args ...any)
|
|
||||||
Debug(args ...any)
|
|
||||||
Debugf(format string, args ...any)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Logger interface {
|
|
||||||
Handler() slog.Handler
|
|
||||||
With(args ...any) Logger
|
|
||||||
WithGroup(name string) Logger
|
|
||||||
ForAccount(handler, conn, acc any) Logger
|
|
||||||
Enabled(ctx context.Context, level slog.Level) bool
|
|
||||||
Log(ctx context.Context, level slog.Level, msg string, args ...any)
|
|
||||||
LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr)
|
|
||||||
Debug(msg string, args ...any)
|
|
||||||
DebugContext(ctx context.Context, msg string, args ...any)
|
|
||||||
Info(msg string, args ...any)
|
|
||||||
InfoContext(ctx context.Context, msg string, args ...any)
|
|
||||||
Warn(msg string, args ...any)
|
|
||||||
WarnContext(ctx context.Context, msg string, args ...any)
|
|
||||||
Error(msg string, args ...any)
|
|
||||||
ErrorContext(ctx context.Context, msg string, args ...any)
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package logger
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
|
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
52
core/logger/nil.go
Normal file
52
core/logger/nil.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Nil struct{}
|
||||||
|
|
||||||
|
func NewNil() Logger {
|
||||||
|
return &Nil{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Nil) With(fields ...zap.Field) Logger {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Nil) WithLazy(fields ...zap.Field) Logger {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Nil) Level() zapcore.Level {
|
||||||
|
return zapcore.DebugLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Nil) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
|
||||||
|
return &zapcore.CheckedEntry{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Nil) Log(lvl zapcore.Level, msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) Debug(msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) Info(msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) Warn(msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) Error(msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) DPanic(msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) Panic(msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) Fatal(msg string, fields ...zap.Field) {}
|
||||||
|
|
||||||
|
func (l *Nil) ForAccount(handler, conn, acc any) Logger {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Nil) Sync() error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,26 +0,0 @@
|
|||||||
package logger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
var NilHandler slog.Handler = &nilHandler{}
|
|
||||||
|
|
||||||
type nilHandler struct{}
|
|
||||||
|
|
||||||
func (n *nilHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *nilHandler) Handle(ctx context.Context, record slog.Record) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *nilHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *nilHandler) WithGroup(name string) slog.Handler {
|
|
||||||
return n
|
|
||||||
}
|
|
@ -1,21 +1,21 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
||||||
type writerAdapter struct {
|
type writerAdapter struct {
|
||||||
log Logger
|
log Logger
|
||||||
level slog.Level
|
level zapcore.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriterAdapter(log Logger, level slog.Level) io.Writer {
|
func WriterAdapter(log Logger, level zapcore.Level) io.Writer {
|
||||||
return &writerAdapter{log: log, level: level}
|
return &writerAdapter{log: log, level: level}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *writerAdapter) Write(p []byte) (n int, err error) {
|
func (w *writerAdapter) Write(p []byte) (n int, err error) {
|
||||||
w.log.Log(context.Background(), w.level, string(p))
|
w.log.Log(w.level, string(p))
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
52
core/logger/zap.go
Normal file
52
core/logger/zap.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewZap(debug bool) *zap.Logger {
|
||||||
|
level := zapcore.InfoLevel
|
||||||
|
if debug {
|
||||||
|
level = zapcore.DebugLevel
|
||||||
|
}
|
||||||
|
log, err := zap.Config{
|
||||||
|
Level: zap.NewAtomicLevelAt(level),
|
||||||
|
Development: debug,
|
||||||
|
Encoding: "console",
|
||||||
|
EncoderConfig: EncoderConfig(),
|
||||||
|
OutputPaths: []string{"stdout"},
|
||||||
|
ErrorOutputPaths: []string{"stderr"},
|
||||||
|
}.Build()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return log
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncoderConfig() zapcore.EncoderConfig {
|
||||||
|
return zapcore.EncoderConfig{
|
||||||
|
MessageKey: "message",
|
||||||
|
LevelKey: "level",
|
||||||
|
TimeKey: "timestamp",
|
||||||
|
NameKey: "logger",
|
||||||
|
CallerKey: "caller",
|
||||||
|
FunctionKey: zapcore.OmitKey,
|
||||||
|
StacktraceKey: "",
|
||||||
|
LineEnding: "\n",
|
||||||
|
EncodeLevel: func(level zapcore.Level, encoder zapcore.PrimitiveArrayEncoder) {
|
||||||
|
encoder.AppendString("level=" + level.String())
|
||||||
|
},
|
||||||
|
EncodeTime: func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
|
||||||
|
encoder.AppendString("time=" + t.Format(time.RFC3339))
|
||||||
|
},
|
||||||
|
EncodeDuration: zapcore.StringDurationEncoder,
|
||||||
|
EncodeCaller: func(caller zapcore.EntryCaller, encoder zapcore.PrimitiveArrayEncoder) {
|
||||||
|
encoder.AppendString("caller=" + caller.TrimmedPath())
|
||||||
|
},
|
||||||
|
EncodeName: zapcore.FullNameEncoder,
|
||||||
|
ConsoleSeparator: " ",
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log/slog"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
@ -13,6 +12,7 @@ import (
|
|||||||
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
"github.com/gomarkdown/markdown"
|
"github.com/gomarkdown/markdown"
|
||||||
|
"go.uber.org/zap"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
||||||
@ -91,14 +91,14 @@ func (s *ModuleFeaturesUploader) Upload() {
|
|||||||
|
|
||||||
content, err := os.ReadFile(s.featuresFilename)
|
content, err := os.ReadFile(s.featuresFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error("cannot read markdown file %s %s", slog.String("fileName", s.featuresFilename), logger.Err(err))
|
s.log.Error("cannot read markdown file %s %s", zap.String("fileName", s.featuresFilename), logger.Err(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, lang := range languages {
|
for _, lang := range languages {
|
||||||
translated, err := s.translate(content, lang)
|
translated, err := s.translate(content, lang)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error("cannot translate module features file", slog.String("lang", lang.String()), logger.Err(err))
|
s.log.Error("cannot translate module features file", zap.String("lang", lang.String()), logger.Err(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ func (s *ModuleFeaturesUploader) Upload() {
|
|||||||
resp, err := s.uploadFile(html, lang.String())
|
resp, err := s.uploadFile(html, lang.String())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error("cannot upload file", slog.String("lang", lang.String()), logger.Err(err))
|
s.log.Error("cannot upload file", zap.String("lang", lang.String()), logger.Err(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
@ -16,6 +15,7 @@ import (
|
|||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
sentrygin "github.com/getsentry/sentry-go/gin"
|
sentrygin "github.com/getsentry/sentry-go/gin"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/stacktrace"
|
"github.com/retailcrm/mg-transport-core/v2/core/stacktrace"
|
||||||
@ -260,8 +260,8 @@ func (s *Sentry) recoveryMiddleware() gin.HandlerFunc { // nolint
|
|||||||
}
|
}
|
||||||
headers[idx] = "header: " + headers[idx]
|
headers[idx] = "header: " + headers[idx]
|
||||||
}
|
}
|
||||||
headersToStr := slog.String("headers", strings.Join(headers, "\r\n"))
|
headersToStr := zap.String("headers", strings.Join(headers, "\r\n"))
|
||||||
formattedStack := slog.String("stacktrace", string(stack))
|
formattedStack := zap.String("stacktrace", string(stack))
|
||||||
switch {
|
switch {
|
||||||
case brokenPipe:
|
case brokenPipe:
|
||||||
l.Error("error", formattedErr, headersToStr)
|
l.Error("error", formattedErr, headersToStr)
|
||||||
|
@ -12,9 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -275,7 +273,7 @@ func (b *HTTPClientBuilder) buildMocks() error {
|
|||||||
func (b *HTTPClientBuilder) log(msg string, args ...interface{}) {
|
func (b *HTTPClientBuilder) log(msg string, args ...interface{}) {
|
||||||
if b.logging {
|
if b.logging {
|
||||||
if b.logger != nil {
|
if b.logger != nil {
|
||||||
b.logger.Info(msg, args...)
|
b.logger.Info(msg, logger.AnyZapFields(args)...)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(append([]any{msg}, args...))
|
fmt.Println(append([]any{msg}, args...))
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ func (t *HTTPClientBuilderTest) Test_WithLogger() {
|
|||||||
builder.WithLogger(nil)
|
builder.WithLogger(nil)
|
||||||
assert.Nil(t.T(), builder.logger)
|
assert.Nil(t.T(), builder.logger)
|
||||||
|
|
||||||
log := logger.NewDefaultText()
|
log := logger.NewDefault(true)
|
||||||
builder.WithLogger(log)
|
builder.WithLogger(log)
|
||||||
assert.NotNil(t.T(), builder.logger)
|
assert.NotNil(t.T(), builder.logger)
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package testutil
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"os"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReadBuffer is implemented by the BufferLogger.
|
// ReadBuffer is implemented by the BufferLogger.
|
||||||
@ -32,21 +34,32 @@ type BufferLogger struct {
|
|||||||
// NewBufferedLogger returns new BufferedLogger instance.
|
// NewBufferedLogger returns new BufferedLogger instance.
|
||||||
func NewBufferedLogger() BufferedLogger {
|
func NewBufferedLogger() BufferedLogger {
|
||||||
bl := &BufferLogger{}
|
bl := &BufferLogger{}
|
||||||
bl.Logger = slog.New(slog.NewTextHandler(&bl.buf, logger.DefaultOpts))
|
bl.Logger = zap.New(
|
||||||
|
zapcore.NewCore(
|
||||||
|
zapcore.NewConsoleEncoder(
|
||||||
|
logger.EncoderConfig()), zap.CombineWriteSyncers(os.Stdout, os.Stderr, &bl.buf), zapcore.DebugLevel))
|
||||||
return bl
|
return bl
|
||||||
}
|
}
|
||||||
|
|
||||||
// With doesn't do anything here and only added for backwards compatibility with the interface.
|
func (l *BufferLogger) With(fields ...zapcore.Field) logger.Logger {
|
||||||
func (l *BufferLogger) With(args ...any) logger.Logger {
|
|
||||||
return &BufferLogger{
|
return &BufferLogger{
|
||||||
Default: logger.Default{
|
Default: logger.Default{
|
||||||
Logger: l.Logger.With(args...),
|
Logger: l.Logger.With(fields...),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *BufferLogger) WithLazy(fields ...zapcore.Field) logger.Logger {
|
||||||
|
return &BufferLogger{
|
||||||
|
Default: logger.Default{
|
||||||
|
Logger: l.Logger.WithLazy(fields...),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *BufferLogger) ForAccount(handler, conn, acc any) logger.Logger {
|
func (l *BufferLogger) ForAccount(handler, conn, acc any) logger.Logger {
|
||||||
return l.With(slog.Any(logger.HandlerAttr, handler), slog.Any(logger.ConnectionAttr, conn), slog.Any(logger.AccountAttr, acc))
|
return l.WithLazy(
|
||||||
|
zap.Any(logger.HandlerAttr, handler), zap.Any(logger.ConnectionAttr, conn), zap.Any(logger.AccountAttr, acc))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read bytes from the logger buffer. io.Reader implementation.
|
// Read bytes from the logger buffer. io.Reader implementation.
|
||||||
|
@ -29,17 +29,17 @@ func (t *BufferLoggerTest) Test_Read() {
|
|||||||
|
|
||||||
data, err := io.ReadAll(t.logger)
|
data, err := io.ReadAll(t.logger)
|
||||||
t.Require().NoError(err)
|
t.Require().NoError(err)
|
||||||
t.Assert().Contains(string(data), "level=DEBUG msg=test")
|
t.Assert().Contains(string(data), "level=debug test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BufferLoggerTest) Test_Bytes() {
|
func (t *BufferLoggerTest) Test_Bytes() {
|
||||||
t.logger.Debug("test")
|
t.logger.Debug("test")
|
||||||
t.Assert().Contains(string(t.logger.Bytes()), "level=DEBUG msg=test")
|
t.Assert().Contains(string(t.logger.Bytes()), "level=debug test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BufferLoggerTest) Test_String() {
|
func (t *BufferLoggerTest) Test_String() {
|
||||||
t.logger.Debug("test")
|
t.logger.Debug("test")
|
||||||
t.Assert().Contains(t.logger.String(), "level=DEBUG msg=test")
|
t.Assert().Contains(t.logger.String(), "level=debug test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BufferLoggerTest) TestRace() {
|
func (t *BufferLoggerTest) TestRace() {
|
||||||
|
@ -148,3 +148,8 @@ func (b *LockableBuffer) ReadString(delim byte) (line string, err error) {
|
|||||||
b.rw.Lock()
|
b.rw.Lock()
|
||||||
return b.buf.ReadString(delim)
|
return b.buf.ReadString(delim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync is a no-op.
|
||||||
|
func (b *LockableBuffer) Sync() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
retailcrm "github.com/retailcrm/api-client-go/v2"
|
retailcrm "github.com/retailcrm/api-client-go/v2"
|
||||||
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
|
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
"github.com/retailcrm/mg-transport-core/v2/core/config"
|
||||||
|
|
||||||
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
"github.com/retailcrm/mg-transport-core/v2/core/logger"
|
||||||
@ -145,12 +144,12 @@ func (u *Utils) GetAPIClient(
|
|||||||
|
|
||||||
if res := u.checkScopes(cr.Scopes, scopes); len(res) != 0 {
|
if res := u.checkScopes(cr.Scopes, scopes); len(res) != 0 {
|
||||||
if len(credentials) == 0 || len(cr.Scopes) > 0 {
|
if len(credentials) == 0 || len(cr.Scopes) > 0 {
|
||||||
u.Logger.Error(url, status, res)
|
u.Logger.Error(url, logger.HTTPStatusCode(status), logger.Body(res))
|
||||||
return nil, http.StatusBadRequest, errorutil.NewInsufficientScopesErr(res)
|
return nil, http.StatusBadRequest, errorutil.NewInsufficientScopesErr(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
if res := u.checkScopes(cr.Credentials, credentials[0]); len(res) != 0 {
|
if res := u.checkScopes(cr.Credentials, credentials[0]); len(res) != 0 {
|
||||||
u.Logger.Error(url, status, res)
|
u.Logger.Error(url, logger.HTTPStatusCode(status), logger.Body(res))
|
||||||
return nil, http.StatusBadRequest, errorutil.NewInsufficientScopesErr(res)
|
return nil, http.StatusBadRequest, errorutil.NewInsufficientScopesErr(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func mgClient() *v1.MgClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UtilsTest) SetupSuite() {
|
func (u *UtilsTest) SetupSuite() {
|
||||||
logger := logger.NewDefaultText()
|
logger := logger.NewDefault(true)
|
||||||
awsConfig := config.AWS{
|
awsConfig := config.AWS{
|
||||||
AccessKeyID: "access key id (will be removed)",
|
AccessKeyID: "access key id (will be removed)",
|
||||||
SecretAccessKey: "secret access key",
|
SecretAccessKey: "secret access key",
|
||||||
|
2
go.mod
2
go.mod
@ -28,6 +28,7 @@ require (
|
|||||||
github.com/retailcrm/zabbix-metrics-collector v1.0.0
|
github.com/retailcrm/zabbix-metrics-collector v1.0.0
|
||||||
github.com/stretchr/testify v1.8.3
|
github.com/stretchr/testify v1.8.3
|
||||||
go.uber.org/atomic v1.10.0
|
go.uber.org/atomic v1.10.0
|
||||||
|
go.uber.org/zap v1.26.0
|
||||||
golang.org/x/text v0.14.0
|
golang.org/x/text v0.14.0
|
||||||
gopkg.in/gormigrate.v1 v1.6.0
|
gopkg.in/gormigrate.v1 v1.6.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
@ -77,6 +78,7 @@ require (
|
|||||||
github.com/stretchr/objx v0.5.0 // indirect
|
github.com/stretchr/objx v0.5.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/crypto v0.21.0 // indirect
|
golang.org/x/crypto v0.21.0 // indirect
|
||||||
golang.org/x/net v0.23.0 // indirect
|
golang.org/x/net v0.23.0 // indirect
|
||||||
|
11
go.sum
11
go.sum
@ -297,8 +297,9 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
|||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
|
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
|
||||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||||
@ -377,8 +378,6 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R
|
|||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/retailcrm/api-client-go/v2 v2.1.3 h1:AVcp9oeSOm6+3EWXCgdQs+XE3PTjzCKKB//MUAe0Zb0=
|
github.com/retailcrm/api-client-go/v2 v2.1.3 h1:AVcp9oeSOm6+3EWXCgdQs+XE3PTjzCKKB//MUAe0Zb0=
|
||||||
github.com/retailcrm/api-client-go/v2 v2.1.3/go.mod h1:1yTZl9+gd3+/k0kAJe7sYvC+mL4fqMwIwtnSgSWZlkQ=
|
github.com/retailcrm/api-client-go/v2 v2.1.3/go.mod h1:1yTZl9+gd3+/k0kAJe7sYvC+mL4fqMwIwtnSgSWZlkQ=
|
||||||
github.com/retailcrm/mg-transport-api-client-go v1.1.32 h1:IBPltSoD5q2PPZJbNC/prK5F9rEVPXVx/ZzDpi7HKhs=
|
|
||||||
github.com/retailcrm/mg-transport-api-client-go v1.1.32/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI=
|
|
||||||
github.com/retailcrm/mg-transport-api-client-go v1.3.4 h1:HIn4eorABNfudn7hr5Rd6XYC/ieDTqCkaq6wv0AFTBE=
|
github.com/retailcrm/mg-transport-api-client-go v1.3.4 h1:HIn4eorABNfudn7hr5Rd6XYC/ieDTqCkaq6wv0AFTBE=
|
||||||
github.com/retailcrm/mg-transport-api-client-go v1.3.4/go.mod h1:gDe/tj7t3Hr/uwIFSBVgGAmP85PoLajVl1A+skBo1Ro=
|
github.com/retailcrm/mg-transport-api-client-go v1.3.4/go.mod h1:gDe/tj7t3Hr/uwIFSBVgGAmP85PoLajVl1A+skBo1Ro=
|
||||||
github.com/retailcrm/zabbix-metrics-collector v1.0.0 h1:ju3rhpgVoiKII6oXEJEf2eoJy5bNcYAmOPRp1oPWDmA=
|
github.com/retailcrm/zabbix-metrics-collector v1.0.0 h1:ju3rhpgVoiKII6oXEJEf2eoJy5bNcYAmOPRp1oPWDmA=
|
||||||
@ -444,6 +443,12 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
|
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||||
|
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||||
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||||
|
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
Loading…
Reference in New Issue
Block a user