func Info(info ...interface{}) {
	if !logger.infoLogOff && logger.Level <= zapcore.InfoLevel {
		logger.sugaredLogger.Info(info...)
	}
}
Info print the info message.
package logger
import (
	"os"
	"path/filepath"
	"strconv"
	"github.com/GoAdminGroup/go-admin/context"
	"github.com/GoAdminGroup/go-admin/modules/utils"
	"github.com/mgutz/ansi"
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)
var (
	defaultEncoderCfg = EncoderCfg{
		TimeKey:       "ts",
		LevelKey:      "level",
		NameKey:       "logger",
		CallerKey:     "caller",
		MessageKey:    "msg",
		StacktraceKey: "stacktrace",
		Level:         "capitalColor",
		Time:          "ISO8601",
		Duration:      "seconds",
		Caller:        "short",
		Encoding:      "console",
	}
	defaultRotateCfg = RotateCfg{
		MaxSize:    10,
		MaxBackups: 5,
		MaxAge:     30,
		Compress:   false,
	}
	logger = &Logger{
		rotate:  defaultRotateCfg,
		encoder: defaultEncoderCfg,
		Level:   zapcore.InfoLevel,
	}
	infoLevelEnabler = zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl == zapcore.InfoLevel
	})
	errorLevelEnabler = zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.ErrorLevel
	})
	accessLevelEnabler = zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl == zapcore.WarnLevel
	})
)
func init() {
	logger.Init()
}
type Logger struct {
	logger        *zap.Logger
	sugaredLogger *zap.SugaredLogger
	infoLogOff   bool
	errorLogOff  bool
	accessLogOff bool
	accessAssetsLogOff bool
	debug bool
	sqlLogOpen bool
	infoLogPath   string
	errorLogPath  string
	accessLogPath string
	rotate  RotateCfg
	encoder EncoderCfg
	Level zapcore.Level
}
type EncoderCfg struct {
	TimeKey       string
	LevelKey      string
	NameKey       string
	CallerKey     string
	MessageKey    string
	StacktraceKey string
	Level         string
	Time          string
	Duration      string
	Caller        string
	Encoding      string
}
type RotateCfg struct {
	MaxSize    int
	MaxBackups int
	MaxAge     int
	Compress   bool
}
func (l *Logger) Init() {
	zapLogger := zap.New(zapcore.NewTee(
		zapcore.NewCore(l.getEncoder(l.encoder.LevelKey), l.getLogWriter(l.infoLogPath), infoLevelEnabler),
		zapcore.NewCore(l.getEncoder(l.encoder.LevelKey), l.getLogWriter(l.errorLogPath), errorLevelEnabler),
		zapcore.NewCore(l.getEncoder(""), l.getLogWriter(l.accessLogPath), accessLevelEnabler),
	), zap.AddCaller(), zap.AddCallerSkip(1), zap.AddStacktrace(errorLevelEnabler))
	l.sugaredLogger = zapLogger.Sugar()
	l.logger = zapLogger
}
func (l *Logger) getEncoder(levelKey string) zapcore.Encoder {
	var (
		timeEncoder     = new(zapcore.TimeEncoder)
		durationEncoder = new(zapcore.DurationEncoder)
		callerEncoder   = new(zapcore.CallerEncoder)
		nameEncoder     = new(zapcore.NameEncoder)
		levelEncoder    = new(zapcore.LevelEncoder)
	)
	_ = timeEncoder.UnmarshalText([]byte(l.encoder.Time))
	_ = durationEncoder.UnmarshalText([]byte(l.encoder.Duration))
	_ = callerEncoder.UnmarshalText([]byte(l.encoder.Caller))
	_ = nameEncoder.UnmarshalText([]byte("full"))
	_ = levelEncoder.UnmarshalText([]byte(l.encoder.Level))
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        l.encoder.TimeKey,
		LevelKey:       levelKey,
		NameKey:        l.encoder.NameKey,
		CallerKey:      l.encoder.CallerKey,
		MessageKey:     l.encoder.MessageKey,
		StacktraceKey:  l.encoder.StacktraceKey,
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    *levelEncoder,
		EncodeTime:     *timeEncoder,
		EncodeDuration: *durationEncoder,
		EncodeCaller:   *callerEncoder,
		EncodeName:     *nameEncoder,
	}
	return filterZapEncoder(l.encoder.Encoding, encoderConfig)
}
func (l *Logger) getLogWriter(path string) zapcore.WriteSyncer {
	if path != "" {
		lumberJackLogger := &lumberjack.Logger{
			Filename:   path,
			MaxSize:    l.rotate.MaxSize,
			MaxBackups: l.rotate.MaxBackups,
			MaxAge:     l.rotate.MaxAge,
			Compress:   l.rotate.Compress,
		}
		if l.debug {
			return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(lumberJackLogger))
		}
		return zapcore.AddSync(lumberJackLogger)
	}
	return zapcore.AddSync(os.Stdout)
}
func (l *Logger) SetRotate(cfg RotateCfg) {
	if cfg.MaxSize != 0 && cfg.MaxAge != 0 && cfg.MaxBackups != 0 {
		l.rotate = cfg
	}
}
func (l *Logger) SetEncoder(cfg EncoderCfg) {
	cfg.TimeKey = utils.SetDefault(cfg.TimeKey, "", defaultEncoderCfg.TimeKey)
	cfg.LevelKey = utils.SetDefault(cfg.LevelKey, "", defaultEncoderCfg.LevelKey)
	cfg.NameKey = utils.SetDefault(cfg.NameKey, "", defaultEncoderCfg.NameKey)
	cfg.CallerKey = utils.SetDefault(cfg.CallerKey, "", defaultEncoderCfg.CallerKey)
	cfg.MessageKey = utils.SetDefault(cfg.MessageKey, "", defaultEncoderCfg.MessageKey)
	cfg.StacktraceKey = utils.SetDefault(cfg.StacktraceKey, "", defaultEncoderCfg.StacktraceKey)
	cfg.Level = utils.SetDefault(cfg.Level, "", defaultEncoderCfg.Level)
	cfg.Time = utils.SetDefault(cfg.Time, "", defaultEncoderCfg.Time)
	cfg.Duration = utils.SetDefault(cfg.Duration, "", defaultEncoderCfg.Duration)
	cfg.Caller = utils.SetDefault(cfg.Caller, "", defaultEncoderCfg.Caller)
	cfg.Encoding = utils.SetDefault(cfg.Encoding, "", defaultEncoderCfg.Encoding)
	l.encoder = cfg
}
type Config struct {
	InfoLogOff   bool
	ErrorLogOff  bool
	AccessLogOff bool
	SqlLogOpen bool
	InfoLogPath   string
	ErrorLogPath  string
	AccessLogPath string
	AccessAssetsLogOff bool
	Rotate RotateCfg
	Encode EncoderCfg
	Level int8
	Debug bool
}
func InitWithConfig(cfg Config) {
	logger.infoLogPath = cfg.InfoLogPath
	logger.infoLogOff = cfg.InfoLogOff
	logger.errorLogPath = cfg.ErrorLogPath
	logger.errorLogOff = cfg.ErrorLogOff
	logger.accessLogPath = cfg.AccessLogPath
	logger.accessLogOff = cfg.AccessLogOff
	logger.sqlLogOpen = cfg.SqlLogOpen
	logger.accessAssetsLogOff = cfg.AccessAssetsLogOff
	logger.debug = cfg.Debug
	logger.SetRotate(cfg.Rotate)
	logger.SetEncoder(cfg.Encode)
	logger.Level = filterZapAtomicLevelByViper(cfg.Level)
	logger.Init()
}
func SetRotate(cfg RotateCfg) {
	logger.rotate = cfg
	logger.Init()
}
func OpenSQLLog() {
	logger.sqlLogOpen = true
}
func Debug(info ...interface{}) {
	if !logger.infoLogOff {
		if logger.Level <= zapcore.DebugLevel {
			logger.sugaredLogger.Info(info...)
		}
	}
}
func Debugf(template string, args ...interface{}) {
	if !logger.infoLogOff && logger.Level <= zapcore.DebugLevel {
		logger.sugaredLogger.Infof(template, args...)
	}
}