package logging
import (
"context"
"sync"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type contextKey = string
const loggerKey = contextKey("logger")
var (
defaultLogger *zap.SugaredLogger
defaultLoggerOnce sync.Once
)
var conf = &Config{
Encoding: "console",
Level: zapcore.InfoLevel,
Development: true,
}
type Config struct {
Encoding string
Level zapcore.Level
Development bool
}
// SetConfig sets given logging configs for DefaultLogger's logger.
// Must set configs before calling DefaultLogger()
func SetConfig(c *Config) {
conf = &Config{
Encoding: c.Encoding,
Level: c.Level,
Development: c.Development,
}
}
func SetLevel(l zapcore.Level) {
conf.Level = l
}
// NewLogger creates a new logger with the given log level
func NewLogger(conf *Config) *zap.SugaredLogger {
ec := zap.NewProductionEncoderConfig()
ec.EncodeTime = zapcore.ISO8601TimeEncoder
cfg := zap.Config{
Encoding: conf.Encoding,
EncoderConfig: ec,
Level: zap.NewAtomicLevelAt(conf.Level),
Development: conf.Development,
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stderr"},
}
logger, err := cfg.Build()
if err != nil {
logger = zap.NewNop()
}
return logger.Sugar()
}
// DefaultLogger returns the default logger for the package.
func DefaultLogger() *zap.SugaredLogger {
defaultLoggerOnce.Do(func() {
defaultLogger = NewLogger(conf)
})
return defaultLogger
}
// WithLogger creates a new context with the provided logger attached.
func WithLogger(ctx context.Context, logger *zap.SugaredLogger) context.Context {
if gCtx, ok := ctx.(*gin.Context); ok {
ctx = gCtx.Request.Context()
}
return context.WithValue(ctx, loggerKey, logger)
}
// FromContext returns the logger stored in the context. If no such logger
// exists, a default logger is returned.
func FromContext(ctx context.Context) *zap.SugaredLogger {
if ctx == nil {
return DefaultLogger()
}
if gCtx, ok := ctx.(*gin.Context); ok && gCtx != nil {
ctx = gCtx.Request.Context()
}
if logger, ok := ctx.Value(loggerKey).(*zap.SugaredLogger); ok {
return logger
}
return DefaultLogger()
}