go get go.uber.org/zap
package main
import (
"go.uber.org/zap"
"time"
)
func main() {
url := "http://www.google.com"
//print format log
loggerDev, _ := zap.NewDevelopment()
defer loggerDev.Sync()
loggerDev.Info("loggerDev failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
//sugar 可以不指定类型,代码友好但效率比较低
sugarDev := loggerDev.Sugar()
sugarDev.Warnw("sugarDev failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugarDev.Warnf("sugarDev Failed to fetch URL: %s \n", url)
//print json log
loggerPro, _ := zap.NewProduction()
defer loggerPro.Sync()
loggerPro.Info("loggerPro failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
sugarPro := loggerPro.Sugar()
sugarPro.Errorw("sugarPro failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugarPro.Errorf("sugarPro Failed to fetch URL: %s", url)
}
go run logger.go
2019-07-09T11:09:08.635+0800 INFO zapdemo/logger.go:14 loggerDev failed to fetch URL {"url": "http://www.google.com", "attempt": 3, "backoff": "1s"}
2019-07-09T11:09:08.635+0800 WARN zapdemo/logger.go:23 sugarDev failed to fetch URL {"url": "http://www.google.com", "attempt": 3, "backoff": "1s"}
main.main
/Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:23
runtime.main
/usr/local/Cellar/go/1.12.5/libexec/src/runtime/proc.go:200
2019-07-09T11:09:08.635+0800 WARN zapdemo/logger.go:29 sugarDev Failed to fetch URL: http://www.google.com
main.main
/Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:29
runtime.main
/usr/local/Cellar/go/1.12.5/libexec/src/runtime/proc.go:200
{"level":"info","ts":1562641748.6360571,"caller":"zapdemo/logger.go:34","msg":"loggerPro failed to fetch URL","url":"http://www.google.com","attempt":3,"backoff":1}
{"level":"error","ts":1562641748.636079,"caller":"zapdemo/logger.go:42","msg":"sugarPro failed to fetch URL","url":"http://www.google.com","attempt":3,"backoff":1,"stacktrace":"main.main\n\t/Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:42\nruntime.main\n\t/usr/local/Cellar/go/1.12.5/libexec/src/runtime/proc.go:200"}
{"level":"error","ts":1562641748.636101,"caller":"zapdemo/logger.go:48","msg":"sugarPro Failed to fetch URL: http://www.google.com","stacktrace":"main.main\n\t/Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:48\nruntime.main\n\t/usr/local/Cellar/go/1.12.5/libexec/src/runtime/proc.go:200"}
NewDevelopment 行格式化输出;NewProduction json格式输出
可以根据项目需要及个人偏好进行选择
package main
import (
"fmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"time"
)
func main() {
ConfigLogDemo()
}
func ConfigLogDemo() {
encoderConfig := zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "message",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写编码器
EncodeTime: zapcore.ISO8601TimeEncoder, // ISO8601 UTC 时间格式
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.FullCallerEncoder, // 全路径编码器
}
atom := zap.NewAtomicLevelAt(zap.DebugLevel)
config := zap.Config{
Level:atom, // 日志级别
Development:true, // 开发模式,堆栈跟踪
Encoding:"console", // 输出格式 console json
EncoderConfig:encoderConfig,// 编码器配置
InitialFields:map[string]interface{}{"serviceName": "spikeProxy"}, // 初始化字段,如:添加一个服务器
OutputPaths:[]string{"stdout", "./logs/sample.log"}, // 输出到指定文件 stdout(标准输出,正常颜色) stderr(错误输出,红色)
ErrorOutputPaths:[]string{"stderr"},
}
//构建日志
logger, err := config.Build()
if err != nil{
panic(fmt.Sprintf("log 初始化失败: %v", err))
}
logger.Info("log 初始化成功")
logger.Info("无法获取网址",
zap.String("url", "http://www.baidu.com"),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
logger.Error("log error")
}
运行程序可以看到已经写入文件
2019-07-09T15:33:51.009+0800 info /Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:89 log 初始化成功 {"serviceName": "spikeProxy"}
2019-07-09T15:33:51.009+0800 info /Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:91 无法获取网址 {"serviceName": "spikeProxy", "url": "http://www.baidu.com", "attempt": 3, "backoff": 1}
2019-07-09T15:33:51.009+0800 error /Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:97 log error {"serviceName": "spikeProxy"}
main.ConfigLogDemo
/Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:97
main.main
/Users/chenpeng/working/gopractice/src/projects/logdemo/zapdemo/logger.go:11
runtime.main
/usr/local/Cellar/go/1.12.5/libexec/src/runtime/proc.go:200
注意文件必须先创建好,不然会报找不到文件的错误
go get gopkg.in/natefinch/lumberjack.v2
lumberjack介绍
Lumberjack是一个Go包,用于将日志写入滚动文件。
zap 不支持文件归档,如果要支持文件按大小或者时间归档,需要使用lumberjack,lumberjack也是zap官方推荐的。
代码:
package main
import (
"fmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
"os"
"time"
)
func main() {
LumberjackLog()
}
func LumberjackLog() {
hook := lumberjack.Logger{
Filename: "./logs/lumberjacklog.log", // 日志文件路径
MaxSize: 1, // 每个日志文件保存的最大尺寸 单位:M
MaxBackups: 300, // 日志文件最多保存多少个备份
MaxAge: 7, // 文件最多保存多少天
Compress: false, // 是否压缩
LocalTime: true, // 是否用当地时间命名文件
}
encoderConfig := zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
CallerKey: "linenum",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写编码器
EncodeTime: zapcore.ISO8601TimeEncoder, // ISO8601 UTC 时间格式
EncodeDuration: zapcore.SecondsDurationEncoder, //
EncodeCaller: zapcore.FullCallerEncoder, // 全路径编码器
EncodeName: zapcore.FullNameEncoder,
}
// 设置日志级别
atomicLevel := zap.NewAtomicLevel()
atomicLevel.SetLevel(zap.InfoLevel)
core := zapcore.NewCore(
zapcore.NewConsoleEncoder(encoderConfig), // 编码
zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印
atomicLevel, // 日志
)
// 开启开发模式,调用跟踪
caller := zap.AddCaller()
// 开启堆栈跟踪
stacktrace := zap.AddStacktrace(stacktraceLevel)
// 开启文件及行号
development := zap.Development()
// 设置初始化字段
filed := zap.Fields(zap.String("serviceName", "serviceName"))
// 构建日志
logger := zap.New(core, caller, stacktrace, development, filed)
var count int
for {
logger.Info("log 初始化成功")
logger.Info("无法获取网址",
zap.String("url", "http://www.baidu.com"),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second))
count++
if count > 10000 {
break
}
}
}
运行可以看到已经生成文件了
这个生成文件的逻辑是根据设置的文件最大空间,当达到最大空间后会根据当前时间把日志生成文件,新的日志继续打印到原来的目录中去。