Logger.SetPrefix()是否作为上下文固定在通道/线程之间?



当我使用其他语言的日志包时,我总是强制使用某种类型的上下文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

最新更新