当我将日志包用于其他语言时,我总是强制执行某种类型的上下文Guid(UUID),它会在每次记录器调用时记录。具体来说,这确实有助于在记录1000个请求时跟踪哪组日志属于哪个Web请求或单个线程。
我正在尝试使用Go附带的std记录器执行此操作。
type Context struct {
Log *log.Logger
}
// NewContext constructs a new context.
func NewContext(r *http.Request) (*Context, error) {
id, err := newUUID()
if err != nil {
log.Printf("ERROR in newUUID() : %s", err)
}
c := &Context{
Log: log.New(os.Stderr, id+" ", log.LstdFlags)
}
return c, nil
}
func newUUID() (string, error) {
uuid := make([]byte, 16)
n, err := io.ReadFull(rand.Reader, uuid)
if n != len(uuid) || err != nil {
return "", err
}
// variant bits; see section 4.1.1
uuid[8] = uuid[8]&^0xc0 | 0x80
// version 4 (pseudo-random); see section 4.1.3
uuid[6] = uuid[6]&^0xf0 | 0x40
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
}
如您所见,我将log.Logger分配给结构上的值。
它通过我的defaultHandler()
以及其他处理程序使用,例如:
func defaultHandler(fn func(http.ResponseWriter, *http.Request, *Context) error) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// create the context
c, err := NewContext(r)
if err != nil {
log.Printf("ERROR in creating context w/NewContext(): %s", http.StatusInternalServerError, err.Error())
}
defer c.Unload()
c.Log.Printf("METRIC, START URL: %s", r.URL.Path)
}
}
请注意c.Log.Printf()
对记录器的调用。
其中输出的内容如下:
8c93fa699f5a46c1a986076b952f5c2c 2014/07/13 22:45:21 METRIC, START URL: /
我之所以这样做,是因为我不确定以下内容如何在频道和同步环境中发挥作用:
log.SetPrefix("...")
对log.SetPrefix()有更多经验的人可以解释它在通道和线程方面的工作原理,特别是在http请求中吗?
尽量避免在每个请求上创建新的记录器。更愿意使用" log"中的标准全局log
记录器。包,使用.SetPrefix(" ...")。
或者,或许可以概述另一种解决方案?
答案 0 :(得分:2)
您无法使用SetPrefix
方法。这将在全局记录器中设置.prefix
属性。 所有处理程序共享同一个记录器。
你现在这样做是一种方法。另一种方法是在您的上下文中添加日志方法:
type Context struct {
UUID string
}
func (c *Context) Info(fmt string, args ...interface{}) {
log.Printf(c.UUID+" "+fmt, args...)
}
完整的工作示例
package main
import (
"crypto/rand"
"fmt"
"io"
"log"
)
func newUUID() (string, error) {
uuid := make([]byte, 16)
n, err := io.ReadFull(rand.Reader, uuid)
if n != len(uuid) || err != nil {
return "", err
}
// variant bits; see section 4.1.1
uuid[8] = uuid[8]&^0xc0 | 0x80
// version 4 (pseudo-random); see section 4.1.3
uuid[6] = uuid[6]&^0xf0 | 0x40
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
}
type Context struct {
UUID string
}
func (c *Context) Info(fmt string, args ...interface{}) {
log.Printf(c.UUID+" "+fmt, args...)
}
func main() {
uuid, err := newUUID()
if err != nil {
log.Fatal(err)
}
c := &Context{UUID: uuid}
c.Info("Hello ")
}