go-kit 微服务 添加日志(并为每个请求添加UUID)

  • 通过日志我们可以了解到我们关心的数据在软件内的执行情况,同时出问题时可以分析与定位系统故障
  • 用户的每个请求都添加请求ID(我使用的UUID),我们可以更好的了解到每个请求的执行过程,更利于分析与定位问题

简介

  • 在上篇文章中go-kit 微服务 基础使用(HTTP)我们实现了使用go-kit 构建一个简单的加法的http服务
  • 这篇文章中我们将实现使用go-kit中间件机制为其增加日志功能

开始

下载依赖

Server层修改

在Server层文件夹中创建middleware.go文件

  • 定义服务中间件
type NewMiddlewareServer func(Service) Service
  • 创建logMiddlewareServer结构体
type logMiddlewareServer struct {
	logger *zap.Logger
	next   Service
}
  • 创建NewLogMiddlewareServer把日志记录对象嵌入中间件(其实就是对Service添加了一层装饰)
func NewLogMiddlewareServer(log *zap.Logger) NewMiddlewareServer {
	return func(service Service) Service {
		return logMiddlewareServer{
			logger: log,
			next:   service,
		}
	}
}
  • 让logMiddlewareServer实现Service中的全部方法
func (l logMiddlewareServer) TestAdd(ctx context.Context, in Add) (out AddAck) {
	defer func() {
		l.logger.Debug(fmt.Sprint(ctx.Value(ContextReqUUid)), zap.Any("调用 v2_service logMiddlewareServer", "TestAdd"), zap.Any("req", in), zap.Any("res", out))
	}()
	out = l.next.TestAdd(ctx, in)
	return out
}

修改Service中的代码

  • baseServer结构体添加日志对象
type baseServer struct {
	logger *zap.Logger
}
  • 修改Service的初始化方法,加入日志中间件
func NewService(log *zap.Logger) Service {
	var server Service
	server = &baseServer{log}
	server = NewLogMiddlewareServer(log)(server)
	return server
}

Endpoint层修改

  • 添加日志中间件
func LoggingMiddleware(logger *zap.Logger) endpoint.Middleware {
	return func(next endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, request interface{}) (response interface{}, err error) {
			defer func(begin time.Time) {
				logger.Debug(fmt.Sprint(ctx.Value(v2_service.ContextReqUUid)), zap.Any("调用 v2_endpoint LoggingMiddleware", "处理完请求"), zap.Any("耗时毫秒", time.Since(begin).Milliseconds()))
			}(time.Now())
			return next(ctx, request)
		}
	}
}
  • 在NewEndPointServer方法中为每个Endpoint添加日志中间件
func NewEndPointServer(svc v2_service.Service, log *zap.Logger) EndPointServer {
	var addEndPoint endpoint.Endpoint
	{
		addEndPoint = MakeAddEndPoint(svc)
		addEndPoint = LoggingMiddleware(log)(addEndPoint)
	}
	return EndPointServer{AddEndPoint: addEndPoint}
}

Transport层修改

  • 为每个请求添加UUID
httptransport.ServerBefore(func(ctx context.Context, request *http.Request) context.Context {
			UUID := uuid.NewV5(uuid.Must(uuid.NewV4()), "req_uuid").String()
			log.Debug("给请求添加uuid", zap.Any("UUID", UUID))
			ctx = context.WithValue(ctx, v2_service.ContextReqUUid, UUID)
			return ctx
		}

激动人心的时刻来了,修改main方法

utils.NewLoggerServer()
server := v2_service.NewService(utils.GetLogger())
endpoints := v2_endpoint.NewEndPointServer(server, utils.GetLogger())
httpHandler := v2_transport.NewHttpHandler(endpoints, utils.GetLogger())
utils.GetLogger().Info("server run 0.0.0.0:8888")
_ = http.ListenAndServe("0.0.0.0:8888", httpHandler)

访问 http://127.0.0.1:8888/sum?a=1&b=1

2020-01-02 10:21:43     INFO    logtool/log.go:89       [NewLogger] success
2020-01-02 10:21:43     INFO    v2/main.go:16   server run 0.0.0.0:8888
2020-01-02 10:22:00     DEBUG   v2_transport/transport.go:27    给请求添加uuid  {"UUID": "18f7e742-62ef-57ab-b96a-bfa87c654b50"}
2020-01-02 10:22:00     DEBUG   v2_transport/transport.go:52    18f7e742-62ef-57ab-b96a-bfa87c654b50    {" 开始解析请求数据","b":1}}
2020-01-02 10:22:00     DEBUG   v2_service/service.go:28        18f7e742-62ef-57ab-b96a-bfa87c654b50    {"调用 v2_service Seice": "TestAdd 处理请求"}
2020-01-02 10:22:00     DEBUG   v2_service/service.go:30        18f7e742-62ef-57ab-b96a-bfa87c654b50    {"调用 v2_service Seice": "TestAdd 处理请求", "处理返回值": {"res":2}}
2020-01-02 10:22:00     DEBUG   v2_service/middleware.go:29     18f7e742-62ef-57ab-b96a-bfa87c654b50    {"调用 v2_service loiddlewareServer": "TestAdd", "req": {"a":1,"b":1}, "res": {"res":2}}
2020-01-02 10:22:00     DEBUG   v2_endpoint/middleware.go:16    18f7e742-62ef-57ab-b96a-bfa87c654b50    {"调用 v2_endpoint LgingMiddleware": "处理完请求", "耗时毫秒": 2}
2020-01-02 10:22:00     DEBUG   v2_transport/transport.go:57    18f7e742-62ef-57ab-b96a-bfa87c654b50    {"请求结束封装返回值:2}}
  • 有疑问请联系我

结语

git-kit的中间件采用的装饰者模式,所以新增的日志功能基本对各层逻辑基本没有侵入,方便中间件的插拔处理

完整代码地址

联系 QQ: 3355168235