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獲取。

本文首發於本人微信公衆號【兮一昂吧】,歡迎掃碼關注!

相關文章
相關標籤/搜索