当我使用其他语言的日志包时,我总是强制使用某种类型的上下文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
}
如您所见,我分配了一个日志。
它通过我的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
Logger,带有。setprefix("…")。
或者,也许概述另一个解决方案?
不能使用SetPrefix
方法。这将在全局日志记录器中设置.prefix
属性。所有处理程序共享同一个记录器。
你现在做这件事的方法是一种方法。另一种方法是在上下文中添加一个log方法:
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 ")
}
http://play.golang.org/p/uEIKweC-kp