首頁>技術>

生命不止,繼續go go go~~~

之前我們簡要介紹了go語言中的log package 和 net/http package,那麼我們今天就乾點實事兒,將二者結合,實現我們自己的日誌記錄網路請求。

另外,我們還沒有跟你介紹time package,但是也可以看懂的。

首先,我預設你瞭解go語言的組織結構。

匯入需要的package

我們需要 log net/http time三個包

```package httploggerimport (	"log"	"net/http"	"time")```
實現一個結構體
```type loggedRoundTripper struct {	rt  http.RoundTripper	log HTTPLogger}```

其中http.RoudTripper:

RoundTripper is an interface representing the ability to execute a single HTTP transaction, obtaining the Response for a given Request.

實現一個介面HTTPLogger
```type HTTPLogger interface {	LogRequest(*http.Request)	LogResponse(*http.Request, *http.Response, error, time.Duration)}```

實現函式:

```type DefaultLogger struct {}func (dl DefaultLogger) LogRequest(*http.Request) {}func (dl DefaultLogger) LogResponse(req *http.Request, res *http.Response, err error, duration time.Duration) {	duration /= time.Millisecond	if err != nil {		log.Printf("HTTP Request method=%s host=%s path=%s status=error durationMs=%d error=%q", req.Method, req.Host, req.URL.Path, duration, err.Error())	} else {		log.Printf("HTTP Request method=%s host=%s path=%s status=%d durationMs=%d", req.Method, req.Host, req.URL.Path, res.StatusCode, duration)	}}```
完整程式碼
```package httploggerimport (	"log"	"net/http"	"time")type loggedRoundTripper struct {	rt  http.RoundTripper	log HTTPLogger}func (c *loggedRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {	c.log.LogRequest(request)	startTime := time.Now()	response, err := c.rt.RoundTrip(request)	duration := time.Since(startTime)	c.log.LogResponse(request, response, err, duration)	return response, err}// NewLoggedTransport takes an http.RoundTripper and returns a new one that logs requests and responsesfunc NewLoggedTransport(rt http.RoundTripper, log HTTPLogger) http.RoundTripper {	return &loggedRoundTripper{rt: rt, log: log}}// HTTPLogger defines the interface to log http request and responsestype HTTPLogger interface {	LogRequest(*http.Request)	LogResponse(*http.Request, *http.Response, error, time.Duration)}// DefaultLogger is an http logger that will use the standard logger in the log package to provide basic information about http responsestype DefaultLogger struct {}// LogRequest doens't do anything since we'll be logging replies onlyfunc (dl DefaultLogger) LogRequest(*http.Request) {}// LogResponse logs path, host, status code and duration in millisecondsfunc (dl DefaultLogger) LogResponse(req *http.Request, res *http.Response, err error, duration time.Duration) {	duration /= time.Millisecond	if err != nil {		log.Printf("HTTP Request method=%s host=%s path=%s status=error durationMs=%d error=%q", req.Method, req.Host, req.URL.Path, duration, err.Error())	} else {		log.Printf("HTTP Request method=%s host=%s path=%s status=%d durationMs=%d", req.Method, req.Host, req.URL.Path, res.StatusCode, duration)	}}// DefaultLoggedTransport wraps http.DefaultTransport to log using DefaultLoggervar DefaultLoggedTransport = NewLoggedTransport(http.DefaultTransport, DefaultLogger{})```
使用

實現介面:

```type httpLogger struct {	log *log.Logger}func newLogger() *httpLogger {	return &httpLogger{		log: log.New(os.Stderr, "log - ", log.LstdFlags),	}}func (l *httpLogger) LogRequest(req *http.Request) {	l.log.Printf(		"Request %s %s",		req.Method,		req.URL.String(),	)}func (l *httpLogger) LogResponse(req *http.Request, res *http.Response, err error, duration time.Duration) {	duration /= time.Millisecond	if err != nil {		l.log.Println(err)	} else {		l.log.Printf(			"Response method=%s status=%d durationMs=%d %s",			req.Method,			res.StatusCode,			duration,			req.URL.String(),		)	}}```

完整程式碼:

```package mainimport (	"log"	"net/http"	"os"	"time"	"httplogger/httplogger")func main() {	client := http.Client{		Transport: httplogger.NewLoggedTransport(http.DefaultTransport, newLogger()),	}	client.Get("https://www.baidu.com")}type httpLogger struct {	log *log.Logger}func newLogger() *httpLogger {	return &httpLogger{		log: log.New(os.Stderr, "log - ", log.LstdFlags),	}}func (l *httpLogger) LogRequest(req *http.Request) {	l.log.Printf(		"Request %s %s",		req.Method,		req.URL.String(),	)}func (l *httpLogger) LogResponse(req *http.Request, res *http.Response, err error, duration time.Duration) {	duration /= time.Millisecond	if err != nil {		l.log.Println(err)	} else {		l.log.Printf(			"Response method=%s status=%d durationMs=%d %s",			req.Method,			res.StatusCode,			duration,			req.URL.String(),		)	}}```

結果:

log - 2017/04/18 23:39:41 Request GET https://www.baidu.com

log - 2017/04/18 23:39:42 Response method=GET status=200 durationMs=614 https://www.baidu.com

16
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • nginx 1.19.6 主線版釋出