go手写Redis(3)之自定义日志打印

自定义日志打印

logger会根据定义好的 Settings 对象来指定文件的存储路径文件名称、文件后缀以及文件的时间等进行操作

logger.go

// Settings stores config for logger
type Settings struct {
	Path       string `yaml:"path"`        //文件路径
	Name       string `yaml:"name"`        //文件名称
	Ext        string `yaml:"ext"`         //文件后缀
	TimeFormat string `yaml:"time-format"` //时间格式方式,默认输入 2006-01-02 15:04:05 会显示当前时间
}

var (
	logFile            *os.File                                              //日志文件
	defaultPrefix      = ""                                                  //默认的前缀
	defaultCallerDepth = 2                                                   //追溯到调用函数的上一层的栈帧数,0:当前函数调用的行数,1:上一层函数的调用函数,2:上两层函数的调用位置
	logger             *log.Logger                                           //日志打印器
	mu                 sync.Mutex                                            //锁
	logPrefix          = ""                                                  //日志的前缀
	levelFlags         = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"} //日志等级标识
)

//定义日志等级int类型
type logLevel int

// 日志等级,根据默认值后续自增
const (
	DEBUG logLevel = iota
	INFO
	WARNING
	ERROR
	FATAL
)

//初始化日志标识
const flags = log.LstdFlags

//初始化一个 logger 日志器,设置默认前缀,日志标识
func init() {
	logger = log.New(os.Stdout, defaultPrefix, flags)
}

// Setup 根据设置对象进行初始化
func Setup(settings *Settings) {
	var err error
	dir := settings.Path
	//拼接文件名称  名称-时间.Ext
	fileName := fmt.Sprintf("%s-%s.%s",
		settings.Name,
		time.Now().Format(settings.TimeFormat),
		settings.Ext)

	//判断路径是否可以打开,并且打开文件对象
	logFile, err = mustOpen(fileName, dir)
	if err != nil {
		log.Fatalf("logging.Setup err: %s", err)
	}
	//获取到文件的写入器
	mw := io.MultiWriter(os.Stdout, logFile)
	//创建logger
	logger = log.New(mw, defaultPrefix, flags)
}

//setPrefix 根据日志等级设置打印日志的前缀
func setPrefix(level logLevel) {
	//获取到当前程序调用执行函数的行号信息,如果想要获取到打印日志的函数日志位置就需要设置为2
	_, file, line, ok := runtime.Caller(defaultCallerDepth)
	if ok {
		logPrefix = fmt.Sprintf("[%s][%s:%d] ", levelFlags[level], filepath.Base(file), line)
	} else {
		logPrefix = fmt.Sprintf("[%s] ", levelFlags[level])
	}
	//设置logger的前缀
	logger.SetPrefix(logPrefix)
}

// Debug 打印debug日志
func Debug(v ...interface{}) {
	mu.Lock()
	defer mu.Unlock()
	setPrefix(DEBUG)
	logger.Println(v...)
}

// Info 打印info日志
func Info(v ...interface{}) {
	mu.Lock()
	defer mu.Unlock()
	setPrefix(INFO)
	logger.Println(v...)
}

// Warn 打印warn日志
func Warn(v ...interface{}) {
	mu.Lock()
	defer mu.Unlock()
	setPrefix(WARNING)
	logger.Println(v...)
}

// Error 打印Error日志
func Error(v ...interface{}) {
	mu.Lock()
	defer mu.Unlock()
	setPrefix(ERROR)
	logger.Println(v...)
}

// Errorf 打印Error格式化
func Errorf(format string, v ...interface{}) {
	mu.Lock()
	defer mu.Unlock()
	setPrefix(ERROR)
	logger.Println(fmt.Sprintf(format, v...))
}

// Fatal prints error log then stop the program
func Fatal(v ...interface{}) {
	mu.Lock()
	defer mu.Unlock()
	setPrefix(FATAL)
	logger.Fatalln(v...)
}

files.go

当前文件主要是用于操作对应的日志文件是否存储,并且创建等操作

// checkNotExist 检查文件是否存在
func checkNotExist(src string) bool {
	_, err := os.Stat(src)
	return os.IsNotExist(err)
}

// checkPermission 检查文件的权限
func checkPermission(src string) bool {
	_, err := os.Stat(src)
	return os.IsPermission(err)
}

// isNotExistMkDir 如果文件不存在就创建文件
func isNotExistMkDir(src string) error {
	if checkNotExist(src) {
		return mkDir(src)
	}
	return nil

}

// mkDir 创建文件
func mkDir(src string) error {
	return os.MkdirAll(src, os.ModePerm)
}

// mustOpen 打开文件
func mustOpen(fileName, dir string) (*os.File, error) {
	//检查文件权限
	if checkPermission(dir) {
		return nil, fmt.Errorf("permission denied dir: %s", dir)
	}
	//如果文件不存在并且也创建失败了
	if err := isNotExistMkDir(dir); err != nil {
		return nil, fmt.Errorf("error during make dir %s, err: %s", dir, err)
	}
	//通过路径开启文件
	f, err := os.OpenFile(dir+string(os.PathSeparator)+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		return nil, fmt.Errorf("fail to open file, err: %s", err)
	}
	return f, nil
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值