go使用logrus和zap两大包实现日志分割等处理
1、日志文件
1.1、logrus
go get获取logrus包
go get -u github.com/sirupsen/logrus
1.1.1、日志级别
使用函数logrus.SetLevel(logrus.TraceLevel) 可以设置级别,这样就能显示最小级别的Trace和Debug日志。
- TraceLevel:追踪级别,用于输出非常详细的日志信息,通常用于调试和排查问题。
- DebugLevel:调试级别,用于输出辅助调试信息,帮助开发人员理解程序流程和内部状态。
- InfoLevel:信息级别,是默认的日志级别,用于输出程序运行中的一般信息,提供对程序执行情况的概要记录。
- WarnLevel:警告级别,用于输出可能的问题或潜在的错误情况,但不会阻止程序正常运行。
- ErrorLevel:错误级别,用于输出程序中的错误情况,帮助定位和解决错误。
- FatalLevel:致命级别,用于输出严重的错误情况,这些错误可能会导致程序中止或无法继续执行。
- PanicLevel:恐慌级别,用于输出导致程序崩溃的严重错误,此类错误将引发panic。
1.1.2、设置自定义字段
(1)**logrus.SetReportCaller(true) ** 添加了func和file两个字段
(2)
logrus.WithField("name", "dahua").Info("你好") 添加单个字段信息
logrus.WithFields(logrus.Fields{ 添加多个字段信息
"name": "niaho",
** "age": "19",**
** "height": "180",**
** }).Info("hello")**
1.1.3、重定向输出
file, _:= os.OpenFile("logs.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)//创建文件
logrus.SetOutput(io.MultiWriter(os.Stdout, file))//重定向,多路复用到终端和文件
1.1.4、钩子函数
type FileHook struct {
FireLevels []logrus.Level
Writer io.Writer
}
/*
钩子函数的接口
type Hook interface {
Levels() []Level
Fire(*Entry) error
}
*/
func (hook *FileHook) Fire(entry *logrus.Entry) error {
msg, err := entry.String()
if err != nil {
return err
}
_, err = hook.Writer.Write([]byte(msg))
if err != nil {
return err
}
return nil
}
func (hook *FileHook) Levels() []logrus.Level {
return hook.FireLevels
}
func main() {
//创建新的日志器logger,返回 *logrus.Logger
logger := logrus.New()
// 创建文件输出器
infoFile, _ := os.OpenFile("info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
warnFile, _ := os.OpenFile("warn.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
// 创建钩子并设置对应的文件和触发级别
infoHook := &FileHook{
FireLevels: []logrus.Level{logrus.InfoLevel},
Writer: infoFile,
}
warnHook := &FileHook{
FireLevels: []logrus.Level{logrus.WarnLevel},
Writer: warnFile,
}
// 添加钩子到日志器
logger.AddHook(infoHook)
logger.AddHook(warnHook)
// 输出不同级别的日志消息
logger.Info("info")
logger.Warn("warn")
1.1.5、日志分割
package main
import (
"io"
"os"
"path/filepath"
"time"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/sirupsen/logrus"
)
func main() {
// 创建日志文件夹
// os.MkdirAll() : 根据指定的路径 logFolder 创建一个新的文件夹
// os.ModePerm : 指定创建的文件夹具有完全的权限(读、写和执行权限)
logFolder := "./logs"
err := os.MkdirAll(logFolder, os.ModePerm)
if err != nil {
return
}
// 创建一个日志分割的写入器
logRotationInterval := 10 * time.Second //日志分割的时间间隔
logPath := filepath.Join(logFolder, "logfile") //将日志文件名和日志文件夹路径拼接在一起
options := []rotatelogs.Option{
rotatelogs.WithRotationTime(logRotationInterval), //指定日志文件分割的时间间隔
rotatelogs.WithClock(rotatelogs.Local), //指定日志文件分割时使用本地时钟。这样可以确保日志文件的命名和创建时间与本地时区一致,避免跨时区的问题。
}
// rotatelogs.New() 函数接受两个参数,即日志文件名模式和选项。它根据提供的模式和选项创建一个日志分割的写入器对象。
// logPath+".%Y%m%d%H%M%S" 是用于指定日志文件名称的模式。其中,%Y%m%d%H%M%S 是时间模式,表示年、月、日、小时、分钟和秒。
// options... 表示传递了之前定义的选项数组 options 到 rotatelogs.New 函数中。
logWriter, err := rotatelogs.New(logPath+".%Y%m%d%H%M%S", options...)
if err != nil {
return
}
logger := logrus.New()
logger.SetLevel(logrus.DebugLevel)
logger.SetFormatter(&logrus.TextFormatter{})
logger.SetOutput(io.MultiWriter(os.Stdout, logWriter))
logger.Info("one")
time.Sleep(10 * time.Second)
logger.Info("two")
time.Sleep(10 * time.Second)
logger.Info("three")
time.Sleep(10 * time.Second)
logger.Info("four")
}
1.2、zap
go语言的zap包
go get "go.uber.org/zap"
package main
import (
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func createLogger() *zap.Logger {
// 创建配置对象
cfg := zap.Config{
Encoding: "json", // 编码方式为JSON格式
Level: zap.NewAtomicLevelAt(zap.InfoLevel), // 全局日志级别为InfoLevel
OutputPaths: []string{"stdout", "logs.txt"}, // 输出到标准输出和名为"logs.txt"的文件
ErrorOutputPaths: []string{"stderr"}, // 错误输出到标准错误输出
EncoderConfig: zapcore.EncoderConfig{
TimeKey: "time", // 时间戳的键名
LevelKey: "level", // 日志级别的键名
NameKey: "logger", // 记录器名称的键名
CallerKey: "caller", // 调用者信息的键名
MessageKey: "msg", // 消息的键名
StacktraceKey: "stacktrace", // 堆栈跟踪信息的键名
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05")) //go的时间格式化模板
}, // 使用自定义时间编码器
EncodeLevel: zapcore.CapitalLevelEncoder, // 级别编码器设置为大写形式
EncodeCaller: zapcore.ShortCallerEncoder, // 调用者信息编码器设置为短格式
},
}
return zap.Must(cfg.Build()) // 创建Logger对象,如果发生错误则会panic
}
func main() {
logger := createLogger()
defer logger.Sync() // 确保所有日志都被刷新到存储设备
logger.Info("one") // 记录一条Info级别的日志
msgLogger := logger.With(
zap.String("name", "xizhenhua"), // 添加name字段
zap.Int("age", 16), // 添加age字段
)
msgLogger.Warn("two") // 在子记录器上记录一条Warn级别的日志
}
###