go-kit微服务:日志功能

目前,几乎全部的软件系统都具有日志功能,经过日志咱们能够在软件运行异常时定位软件遇到的问题,还原应用程序异常时的运行状态。git

虽然系统上线前通过了严格的测试工做,可是生产环境业务的复杂性、不可预测性使得软件工程师没法确保系统上线后不会发生故障。为了可以在系统发生异常时对系统故障进行分析与定位,引入日志系统成为全部软件系统研发的必然选择。github

go-kit日志

在上篇文章《go-kit微服务-HTTP REST》中实现了算术运算的HTTP服务,这篇文章将基于Gokit中间件机制为其增长日志记录功能。bash

本质上讲,go-kit中间件采用了装饰者模式,传入Endpoint对象,封装部分业务逻辑,而后返回Endpoint对象。微信

Step-1:建立Middleware

打开service.go文件,加入以下代码:markdown

// ServiceMiddleware define service middleware
type ServiceMiddleware func(Service) Service
复制代码

Step-2:建立日志中间件

新建文件loggings.go,新建类型loggingMiddleware,该类型中嵌入了Service,还包含一个logger属性,代码以下所示:微服务

// loggingMiddleware Make a new type
// that contains Service interface and logger instance
type loggingMiddleware struct {
	Service
	logger log.Logger
}
复制代码

下来建立一个方法LoggingMiddleware把日志记录对象嵌入中间件。该方法接受日志对象,返回ServiceMiddleware,而ServiceMiddleware能够传入Service对象,这样就能够对Service增长一层装饰。代码以下:oop

// LoggingMiddleware make logging middleware
func LoggingMiddleware(logger log.Logger) ServiceMiddleware {
	return func(next Service) Service {
		return loggingMiddleware{next, logger}
	}
}
复制代码

接下来就可让新的类型loggingMiddleware实现Service的接口方法了。实现方法时能够在其中使用日志对象记录调用方法、调用时间、传入参数、输出结果、调用耗时等信息。下面以Add方法为例进行实现,其余方法与之相似:post

func (mw loggingMiddleware) Add(a, b int) (ret int) {

	defer func(beign time.Time) {
		mw.logger.Log(
			"function", "Add",
			"a", a,
			"b", b,
			"result", ret,
			"took", time.Since(beign),
		)
	}(time.Now())

	ret = mw.Service.Add(a, b)
	return ret
}
复制代码

Step-3:修改main方法

打开main.go,调用LoggingMiddleware建立日志中间件实现对svc的包装,代码以下所示(带有注释的一行即为新增代码):测试

func main() {

	ctx := context.Background()
	errChan := make(chan error)

	var logger log.Logger
	{
		logger = log.NewLogfmtLogger(os.Stderr)
		logger = log.With(logger, "ts", log.DefaultTimestampUTC)
		logger = log.With(logger, "caller", log.DefaultCaller)
	}

	var svc Service
	svc = ArithmeticService{}

	// add logging middleware
	svc = LoggingMiddleware(logger)(svc)

	endpoint := MakeArithmeticEndpoint(svc)

	r := MakeHttpHandler(ctx, endpoint, logger)

	go func() {
		fmt.Println("Http Server start at port:9000")
		handler := r
		errChan <- http.ListenAndServe(":9000", handler)
	}()

	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
		errChan <- fmt.Errorf("%s", <-c)
	}()

	fmt.Println(<-errChan)
}
复制代码

Step-4:编译&运行

在控制台编译并运行应用程序,而后经过Postman请求接口进行测试,便可看到输出的日志信息:spa

ts=2019-02-18T05:43:57.902971Z caller=logging.go:25 function=Add a=10 b=1 result=11 took=0s
ts=2019-02-18T05:44:10.116234Z caller=logging.go:25 function=Add a=10 b=1 result=11 took=0s
ts=2019-02-18T05:44:11.2682718Z caller=logging.go:25 function=Add a=10 b=1 result=11 took=0s
复制代码

总结

本文借助go-kit的中间件机制为微服务增长了日志功能。因为Gokit中间件采用装饰者模式,新增的日志功能对Endpoint、Service、Transport三个层次均无代码入侵,实现即插即用的效果,这一机制在开发中将很是有利于团队之间的配合。固然,本文采用的日志记录仅仅是经过控制台输出,还没法真正应用于生产环境,从此有时间继续研究其余方式。

本文代码可经过github获取。

本文首发于本人微信公众号【兮一昂吧】,欢迎扫码关注!

相关文章
相关标签/搜索