|
- package log
-
- import (
- "encoding/hex"
- "math/rand"
- "net/http"
- "time"
-
- "github.com/inconshreveable/log15"
- )
-
- const (
- gaeRequestIDHeader = "X-AppEngine-Request-Log-Id"
- )
-
- var random = rand.New(rand.NewSource(time.Now().UnixNano()))
-
- type httpContextHandler struct {
- log log15.Logger
- next http.Handler
- onAppEngine bool
- }
-
- // NewHTTPContextHandler adds a context logger based on the given logger to
- // each request. After a request passes through this handler,
- // Error(req.Context(), "foo") will log to that logger and add useful context
- // to each log entry.
- func NewHTTPContextHandler(h http.Handler, l log15.Logger, onAppEngine bool) http.Handler {
- if l == nil {
- l = log15.Root()
- }
-
- return &httpContextHandler{
- log: l,
- next: h,
- onAppEngine: onAppEngine,
- }
- }
-
- func (h *httpContextHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
-
- // We will accept an App Engine Request Header. If there isn't one, we will
- // fallback to 16 random bytes (hex encoded).
- reqID := r.Header.Get(gaeRequestIDHeader)
- if !h.onAppEngine || reqID == "" {
- buf := make([]byte, 16)
- random.Read(buf)
- reqID = hex.EncodeToString(buf)
- }
-
- requestLogger := h.log.New(log15.Ctx{
- "request_id": reqID,
- })
-
- r = r.WithContext(NewContext(ctx, requestLogger))
-
- h.next.ServeHTTP(w, r)
- }
|