Go实战--实现一个自己的网络请求日志httplogger(The way to go)
来源:互联网 发布:usb网络接口转换器 编辑:程序博客网 时间:2024/04/30 22:00
生命不止,继续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
2 0
- Go实战--实现一个自己的网络请求日志httplogger(The way to go)
- Go实战--实现一个简单的tcp服务端和客户端(The way to go)
- Go实战--实现一个简单聊天室chatroom(The way to go)
- Go实战--实现一个单向链表(The way to go)
- Go实战--实现一个并发时钟服务器(The way to go)
- Go实战--实现简单的restful api(The way to go)
- Go实战--go中编码转换(The way to go)
- Go实战--go中使用libphonenumber(The way to go)
- Go实战--go中使用cookie(The way to go)
- Go实战--go中使用rpc(The way to go)
- Go实战--go中一些有用的代码片段(The way to go)
- Go实战--go中函数(function)和方法(method)的使用(The way to go)
- Go实战--go中函数递归(recursion)的使用(The way to go)
- Go实战--golang新手入门常见错误(The way to go)
- Go实战--golang生成uuid(The way to go)
- The way to go !
- Go实战--net/http中JSON的使用(The way to go)
- Go实战--压缩zip和解压缩unzip的应用(The way to go)
- sdnu第一场选拔赛--Miller_Rabin算法判断是否为素数
- 【HTML】HTML语言的使用方式和详细说明___完整教程(总结)
- ansible入门
- 状态压缩动态规划
- C#要火了么
- Go实战--实现一个自己的网络请求日志httplogger(The way to go)
- matlab 绘制直方图的函数实现
- 设计模式之13--享元模式
- 作业4
- Python 学习之 GIL
- Linux--网络编程-常见服务器模型
- hdu1874 畅通工程续(Dijkstra/Floyd/Bellman-Ford/SPFA)
- 免费激活win10六个月
- Codeforces801A Vicious Keyboard