https://github.com/uber-go/zap
Zap是非常快的、结构化的,分日志级别的Go日志库。是现在的主流, 没有用反射
https://github.com/wangshibiaoFlytiger/apiproject/tree/master/log

1 安装

go get -u go.uber.org/zap

2 如何输出日志

  1. package main
  2. import "go.uber.org/zap"
  3. func main() {
  4. // 开发环境
  5. logger1, _ := zap.NewDevelopment()
  6. defer logger1.Sync()
  7. logger1.Info("failed to fetch URL",
  8. zap.String("url", "https://imooc.com"),
  9. zap.Int("attempt", 3)) // 2021-11-16T10:58:24.906+0800 INFO zap_test/main.go:9 failed to fetch URL {"url": "https://imooc.com", "attempt": 3}
  10. // 生产环境
  11. logger2, _ := zap.NewProduction()
  12. defer logger2.Sync()
  13. // 普通logger2
  14. logger2.Info("failed to fetch URL",
  15. zap.String("url", "https://imooc.com"),
  16. zap.Int("attempt", 3)) // {"level":"info","ts":1637031504.9066734,"caller":"zap_test/main.go:17","msg":"failed to fetch URL","url":"https://imooc.com","attempt":3}
  17. // 使用语法糖
  18. sugar := logger2.Sugar()
  19. sugar.Infow("failed to fetch URL",
  20. "url", "https://imooc.com",
  21. "attempt", 3) // {"level":"info","ts":1637031504.9067116,"caller":"zap_test/main.go:23","msg":"failed to fetch URL","url":"https://imooc.com","attempt":3}
  22. }

3 日志输出到文件

  1. package main
  2. import (
  3. "go.uber.org/zap"
  4. "time"
  5. )
  6. func NewLogger() (*zap.Logger, error) {
  7. cfg := zap.NewProductionConfig()
  8. cfg.OutputPaths = []string {
  9. "./info.log",
  10. }
  11. return cfg.Build()
  12. }
  13. func main() {
  14. logger, err := NewLogger()
  15. if err != nil {
  16. panic(err)
  17. }
  18. su := logger.Sugar()
  19. defer su.Sync()
  20. su.Info("failed to fetch URL",
  21. "url", "https://immoc.com",
  22. "attempt", 3,
  23. "backoff", time.Second,
  24. )
  25. }

4 封装

  1. package zlog
  2. // 简单封装一下对 zap 日志库的使用
  3. // 使用方式:
  4. // zlog.Debug("hello", zap.String("name", "Kevin"), zap.Any("arbitraryObj", dummyObject))
  5. // zlog.Info("hello", zap.String("name", "Kevin"), zap.Any("arbitraryObj", dummyObject))
  6. // zlog.Warn("hello", zap.String("name", "Kevin"), zap.Any("arbitraryObj", dummyObject))
  7. var logger *zap.Logger
  8. func init() {
  9. ......
  10. }
  11. func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) {
  12. ......
  13. }
  14. func Info(message string, fields ...zap.Field) {
  15. callerFields := getCallerInfoForLog()
  16. fields = append(fields, callerFields...)
  17. logger.Info(message, fields...)
  18. }
  19. func Debug(message string, fields ...zap.Field) {
  20. callerFields := getCallerInfoForLog()
  21. fields = append(fields, callerFields...)
  22. logger.Debug(message, fields...)
  23. }
  24. func Error(message string, fields ...zap.Field) {
  25. callerFields := getCallerInfoForLog()
  26. fields = append(fields, callerFields...)
  27. logger.Error(message, fields...)
  28. }
  29. func Warn(message string, fields ...zap.Field) {
  30. callerFields := getCallerInfoForLog()
  31. fields = append(fields, callerFields...)
  32. logger.Warn(message, fields...)
  33. }
  34. func getCallerInfoForLog() (callerFields []zap.Field) {
  35. pc, file, line, ok := runtime.Caller(2) // 回溯两层,拿到写日志的调用方的函数信息
  36. if !ok {
  37. return
  38. }
  39. funcName := runtime.FuncForPC(pc).Name()
  40. funcName = path.Base(funcName) //Base函数返回路径的最后一个元素,只保留函数名
  41. callerFields = append(callerFields, zap.String("func", funcName), zap.String("file", file), zap.Int("line", line))
  42. return
  43. }