go微服务框架Kratos笔记(二)引入zap日志库

zap日志库是一款高性能的开源日志库,提供了结构化日志记录和printf风格的日志记录

go get -u go.uber.org/zap

参考官方文档中描述,为了方便业务自适配不同的 log 接入使用,Logger 只包含了最简单的 Log 接口。当业务需要在 Kratos 框架内部使用自定义的 log 的时候,只需要简单实现 Log 方法即可。

实现log接口并配置zap日志库编码

package pkg

import (
    "fmt"
    "github.com/go-kratos/kratos/v2/log"
    "github.com/natefinch/lumberjack"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "os"
)

var _ log.Logger = (*ZapLogger)(nil)

type ZapLogger struct {
    log  *zap.Logger
    Sync func() error
}

// Logger 配置zap日志,将zap日志库引入
func Logger() log.Logger {
    //配置zap日志库的编码器
    encoder := zapcore.EncoderConfig{
        TimeKey:        "time",
        LevelKey:       "level",
        NameKey:        "logger",
        CallerKey:      "caller",
        MessageKey:     "msg",
        StacktraceKey:  "stack",
        EncodeTime:     zapcore.ISO8601TimeEncoder,
        LineEnding:     zapcore.DefaultLineEnding,
        EncodeLevel:    zapcore.CapitalLevelEncoder,
        EncodeDuration: zapcore.SecondsDurationEncoder,
        EncodeCaller:   zapcore.FullCallerEncoder,
    }
    return NewZapLogger(
        encoder,
        zap.NewAtomicLevelAt(zapcore.DebugLevel),
        zap.AddStacktrace(
            zap.NewAtomicLevelAt(zapcore.ErrorLevel)),
        zap.AddCaller(),
        zap.AddCallerSkip(2),
        zap.Development(),
    )
}

// 日志自动切割,采用 lumberjack 实现的
func getLogWriter() zapcore.WriteSyncer {
    lumberJackLogger := &lumberjack.Logger{
        Filename:   "../../zap.log", //指定日志存储位置
        MaxSize:    10, //日志的最大大小(M)
        MaxBackups: 5, //日志的最大保存数量
        MaxAge:     30, //日志文件存储最大天数
        Compress:   false, //是否执行压缩
    }
    return zapcore.AddSync(lumberJackLogger)
}

// NewZapLogger return a zap logger.

func NewZapLogger(encoder zapcore.EncoderConfig, level zap.AtomicLevel, opts ...zap.Option) *ZapLogger {
    //日志切割
    writeSyncer := getLogWriter()
    //设置日志级别
    level.SetLevel(zap.InfoLevel)
    var core zapcore.Core
    //开发模式下打印到标准输出
    // --根据配置文件判断输出到控制台还是日志文件--
    if conf.GetConfig().GetString("project.mode") == "dev" {
        core = zapcore.NewCore(
            zapcore.NewConsoleEncoder(encoder),                      // 编码器配置
            zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), // 打印到控制台
            level, // 日志级别
        )
    } else {
        core = zapcore.NewCore(
            zapcore.NewJSONEncoder(encoder), // 编码器配置
            zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(writeSyncer)), // 打印到控制台和文件
            level, // 日志级别
        )
    }
    zapLogger := zap.New(core, opts...)
    return &ZapLogger{log: zapLogger, Sync: zapLogger.Sync}
}

// Log 实现log接口
func (l *ZapLogger) Log(level log.Level, keyvals ...interface{}) error {
    if len(keyvals) == 0 || len(keyvals)%2 != 0 {
        l.log.Warn(fmt.Sprint("Keyvalues must appear in pairs: ", keyvals))
        return nil
    }

    var data []zap.Field
    for i := 0; i < len(keyvals); i += 2 {
        data = append(data, zap.Any(fmt.Sprint(keyvals[i]), keyvals[i+1]))
    }

    switch level {
    case log.LevelDebug:
        l.log.Debug("", data...)
    case log.LevelInfo:
        l.log.Info("", data...)
    case log.LevelWarn:
        l.log.Warn("", data...)
    case log.LevelError:
        l.log.Error("", data...)
    case log.LevelFatal:
        l.log.Fatal("", data...)
    }
    return nil
}

替换为zap日志库

在main函数中将元日志替换为zap日志

app, cleanup, err := initApp(bc.Server, bc.Data, zaoLog.Logger())

添加日志中间件

在 grpc.ServerOption和http.ServerOption 中引入 logging.Server(), 则会在每次收到 gRPC 请求的时候打印详细请求信息。

var opts = []grpc.ServerOption{
        grpc.Middleware(
            recovery.Recovery(),
            logging.Server(logger),//日志中间件
        ),
    }
//=======================================
var opts = []http.ServerOption{
        http.Middleware(
            recovery.Recovery(),
            logging.Server(logger),//日志中间件
        ),
    }

在 grpc.WithMiddleware和http.WithMiddleware 中引入 logging.Client(), 则会在每次发起 grpc 请求的时候打印详细请求信息。

logger := log.DefaultLogger
conn, err := transgrpc.DialInsecure(
    context.Background(),
    grpc.WithEndpoint("127.0.0.1:9000"),
     grpc.WithMiddleware(
        logging.Client(logger),
    ),
)
//=======================================
logger := log.DefaultLogger
conn, err := http.NewClient(
    context.Background(),
    http.WithMiddleware(
        logging.Client(logger),
    ),
    http.WithEndpoint("127.0.0.1:8000"),
)

如有错误请留言反馈

Original: https://www.cnblogs.com/zly-go/p/15500015.html
Author: 悠悠听风
Title: go微服务框架Kratos笔记(二)引入zap日志库

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516540/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • go tool – 快速生成CHANGELOG.md

    在git项目中,通过添加CHANGELOG.md可以展示项目的版本更新记录,方便用户查看项目的重大bug修复或不兼容版本信息。 安装: 打开项目目录运行 或者通过命令行指定项目目录…

    Go语言 2023年5月25日
    070
  • Golang笔记

    本文主要为go的学习过程笔记。 一、基本介绍 1、开发环境安装-windows安装 打开Golang官网,选择对应版本,进行安装。 2、环境变量配置 1)步骤 (1)首先在环境变量…

    Go语言 2023年5月25日
    058
  • Go语言之高级篇beego框架之日志收集系统

    一、日志收集系统架构设计 图1 图2 二、开发环境 1、安装jdk jdk-8u51-windows-x64.exe 安装目录:C:\Program Files\jdk8 2、安装…

    Go语言 2023年5月29日
    056
  • Go语言之网络编程

    一、网络编程基础 网络基础之TCP/IP协议族 网络编程之socket 二、TCP Socket编程 (一)流程 首先应该了解服务端和客户端的处理流程: 1、服务端处理流程 监听端…

    Go语言 2023年5月29日
    065
  • 写了一年golang,来聊聊进程、线程与协程

    本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 进程 在早期的单任务计算机中,用户一次只能提交一个作业,独享系统的全部资源…

    Go语言 2023年5月25日
    080
  • go-zero单体服务使用泛型简化注册Handler路由

    一、Golang环境安装及配置Go Module https://go-zero.dev/cn/docs/prepare/golang-install mac OS安装Go 下载并…

    Go语言 2023年5月25日
    078
  • Go语言之Goroutine与信道、异常处理

    一、Goroutine Go 协程可以看做成一个轻量级的线程,Go 协程相比于线程的优势: Goroutine 的成本更低大小只有 2 kb 左右,线程有几个兆。 Goroutin…

    Go语言 2023年5月25日
    065
  • golang低级编程:一.unsafe包

    go语言在设计上确保了一些安全的属性,限制了程序可能出错的途径。例如严格的类型转换规则。但也使得很多实现的细节无法通过go程序来访问,例如对于聚合类型(如结构体)的内存布局,或者一…

    Go语言 2023年5月25日
    051
  • go 错误处理设计思考

    前段时间准备对线上一个golang系统服务进行内部开源,对代码里面的错误处理进行了一波优化。 优化的几个原因: 错误处理信息随意,未分类未定义。看到错误日志不能第一时间定位 错误的…

    Go语言 2023年5月25日
    059
  • gofs使用教程-基于golang的开源跨平台文件同步工具

    gofs是基于golang开发的一款开箱即用的跨平台文件同步工具,支持在本地磁盘之间同步、从远程服务器同步变更到本地、将本地文件变更推送到远程服务器三种模式。开源地址如下:Gith…

    Go语言 2023年5月25日
    057
  • croncli 定时器命令(golang)

    定时器是执行任务时的常用功能,配置系统的定时任务太麻烦,所以就想用golang简单实现一个定时器命令。 定时器的参数包括: $ croncli -h 定时器命令 Usage: cr…

    Go语言 2023年5月25日
    059
  • 【golang】pprof性能调优工具的具体使用(带案例)

    前言 大晚上的,老是刷到有关pprof的文章,忍不住看了几篇文章…写个学习笔记记录下~ 正文: 1.pprof是什么? pprof是go内置的性能调优工具,可以借助一些…

    Go语言 2023年5月25日
    081
  • go语言并发编程

    引言 说到go语言最厉害的是什么就不得不提到并发,并发是什么?,与并发相关的并行又是什么?并发:同一时间段内执行多个任务并行:同一时刻执行多个任务 进程、线程与协程 进程: 进程是…

    Go语言 2023年5月25日
    074
  • 使用Go搭建并行排序处理管道笔记

    go;collapse:true;;gutter:true; package main</p> <p>import ( "bufio" …

    Go语言 2023年5月25日
    060
  • go-micro集成RabbitMQ实战和原理

    在go-micro中异步消息的收发是通过Broker这个组件来完成的,底层实现有RabbitMQ、Kafka、Redis等等很多种方式,这篇文章主要介绍go-micro使用Rabb…

    Go语言 2023年5月25日
    071
  • 十分钟学会Golang开发gRPC服务

    gRPC是Google发起的一个开源RPC框架,使用HTTP/2传输协议,使用Protocol Buffers编码协议,相比RESTful框架的程序性能提高不少,而且当前流行的编程…

    Go语言 2023年5月25日
    079
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球