// LazyHandler writes all values to the wrapped handler after evaluating // any lazy functions in the record's context. It is already wrapped // around StreamHandler and SyslogHandler in this library, you'll only need // it if you write your own Handler. func LazyHandler(h Handler) Handler { return FuncHandler(func(r *Record) error { // go through the values (odd indices) and reassign // the values of any lazy fn to the result of its execution hadErr := false for i := 1; i < len(r.Ctx); i += 2 { lz, ok := r.Ctx[i].(Lazy) if ok { v, err := evaluateLazy(lz) if err != nil { hadErr = true r.Ctx[i] = err } else { if cs, ok := v.(stack.Trace); ok { v = cs.TrimBelow(stack.Call(r.CallPC[0])). TrimRuntime() } r.Ctx[i] = v } } } if hadErr { r.Ctx = append(r.Ctx, errorKey, "bad lazy") } return h.Log(r) }) }
// CallerFileHandler returns a Handler that adds the line number and file of // the calling function to the context with key "caller". func CallerFileHandler(h Handler) Handler { return FuncHandler(func(r *Record) error { call := stack.Call(r.CallPC[0]) r.Ctx = append(r.Ctx, "caller", fmt.Sprint(call)) return h.Log(r) }) }
// CallerStackHandler returns a Handler that adds a stack trace to the context // with key "stack". The stack trace is formated as a space separated list of // call sites inside matching []'s. The most recent call site is listed first. // Each call site is formatted according to format. See the documentation of // log15/stack.Call.Format for the list of supported formats. func CallerStackHandler(format string, h Handler) Handler { return FuncHandler(func(r *Record) error { s := stack.Callers(). TrimBelow(stack.Call(r.CallPC[0])). TrimRuntime() if len(s) > 0 { buf := &bytes.Buffer{} buf.WriteByte('[') for i, pc := range s { if i > 0 { buf.WriteByte(' ') } fmt.Fprintf(buf, format, pc) } buf.WriteByte(']') r.Ctx = append(r.Ctx, "stack", buf.String()) } return h.Log(r) }) }