go - 在 LoggingHandlers 中自定义日志格式 在 GO 中的 Gorilla 处理程序中实现

标签 go logging https gorilla handlers

我想在LoggingHandler中的 gorilla 处理程序实现中自定义日志记录格式。基本上它默认提供通用日志格式。我想根据请求 header 进行自定义。假设我将tenantId值作为一个请求 header 传递。然后我想将其添加到os.StdOut中。

r := mux.NewRouter()
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("This is a catch-all route"))
})
loggedRouter := handlers.LoggingHandler(os.Stdout, r)

127.0.0.1 - sandun [10/Oct/2018:13:55:36 -0700] "GET /api/request HTTP/1.0" 200 2326

然后请求 header

TeanantId:50

预期输出

127.0.0.1 - sandun [10/Oct/2018:13:55:36 -0700] "GET /api/request HTTP/1.0" 200 2326 50

我想在日志输出的最后添加tenantid。

如何在不更改 gorilla handlers liabry 的情况下做到这一点.

更多详细信息:我可以通过更改 gorilla 处理程序库的内部代码来做到这一点。

// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
    tenantId, err := strconv.Atoi(req.Header.Get("tenantid"))
    if err != nil {
        tenantId = 0
    }
    username := "-"
    if url.User != nil {
        if name := url.User.Username(); name != "" {
            username = name
        }
    }

    host, _, err := net.SplitHostPort(req.RemoteAddr)

    if err != nil {
        host = req.RemoteAddr
    }

    uri := req.RequestURI

    // Requests using the CONNECT method over HTTP/2.0 must use
    // the authority field (aka r.Host) to identify the target.
    // Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
    if req.ProtoMajor == 2 && req.Method == "CONNECT" {
        uri = req.Host
    }
    if uri == "" {
        uri = url.RequestURI()
    }

    buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
    buf = append(buf, host...)
    buf = append(buf, " - "...)
    buf = append(buf, username...)
    buf = append(buf, " ["...)
    buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
    buf = append(buf, `] "`...)
    buf = append(buf, req.Method...)
    buf = append(buf, " "...)
    buf = appendQuoted(buf, uri)
    buf = append(buf, " "...)
    buf = append(buf, req.Proto...)
    buf = append(buf, `" `...)
    buf = append(buf, strconv.Itoa(status)...)
    buf = append(buf, " "...)
    buf = append(buf, strconv.Itoa(size)...)
    buf = append(buf, " "...)
    buf = append(buf, strconv.Itoa(tenantId)...)
    return buf
}

但我认为这不是一个好的解决方案。我期待这个社区提供好的解决方案。

感谢您的帮助。

最佳答案

Gorilla 处理程序库使用 Apache Common Log Format 。更改输出格式会使您的日志消息对于除您之外的所有人来说都绝对不清楚。

惯用的方法:创建您自己的中间件处理程序,该处理程序写入 teanantId header 的输出(或任何其他 io.Writer)值。

第二种(我认为是错误的)方式: fork 存储库,更改行为并使用它。

关于go - 在 LoggingHandlers 中自定义日志格式 在 GO 中的 Gorilla 处理程序中实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51095051/

相关文章:

Go:与另一个进程的双向通信?

pointers - for-range 循环中指针和值 slice 之间的区别

C++ 守护程序日志功能不写入文件(段错误?)

reactjs - ReactJS 有什么方法可以发送 HTTP 请求吗?

node.js - HTTPS AWS Elastic Beanstalk

python - 如何使用 burp 套件代理 HTTPS 流量?

angularjs - 在 Angular/Golang 项目中使用 JWT

go - 去获取不起作用

java - Log4j 从字符串读取配置

c# - 如何在 MongoDB C# Driver 2.0 中记录我的查询?