func DiscardHandler() Handler {
	return FuncHandler(int(LvlCrit), func(r *Record) error {
		return nil
	})
}
DiscardHandler reports success for all writes but does nothing.
It is useful for dynamically disabling logging at runtime via
a Logger's SetHandler method.
package log15
import (
	"fmt"
	"io"
	"net"
	"os"
	"reflect"
	"sync"
	"github.com/go-stack/stack"
)
type Handler interface {
	Log(r *Record) error
	MaxLevel() int
	SetMaxLevel(int)
}
func FuncHandler(maxLevel int, fn func(r *Record) error) Handler {
	return &handlebase{fn, maxLevel}
}
type handlebase struct {
	funcHandler func(r *Record) error
	maxLevel    int
}
func (h *handlebase) Log(r *Record) error {
	return h.funcHandler(r)
}
func (h *handlebase) MaxLevel() int {
	return h.maxLevel
}
func (h *handlebase) SetMaxLevel(maxLevel int) {
	h.maxLevel = maxLevel
}
func StreamHandler(wr io.Writer, fmtr Format) Handler {
	h := FuncHandler(int(LvlDebug), func(r *Record) error {
		_, err := wr.Write(fmtr.Format(r))
		return err
	})
	return LazyHandler(SyncHandler(h))
}
func SyncHandler(h Handler) Handler {
	var mu sync.Mutex
	return FuncHandler(h.MaxLevel(), func(r *Record) error {
		mu.Lock()
		err := h.Log(r)
		mu.Unlock()
		return err
	})
}
func FileHandler(path string, fmtr Format) (Handler, error) {
	f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		return nil, err
	}
	return closingHandler{f, StreamHandler(f, fmtr)}, nil
}
func NetHandler(network, addr string, fmtr Format) (Handler, error) {
	conn, err := net.Dial(network, addr)
	if err != nil {
		return nil, err
	}
	return closingHandler{conn, StreamHandler(conn, fmtr)}, nil
}
type closingHandler struct {
	io.WriteCloser
	Handler
}
func (h *closingHandler) Close() error {
	return h.WriteCloser.Close()
}
func CallerFileHandler(h Handler) Handler {
	return FuncHandler(h.MaxLevel(), func(r *Record) error {
		r.Ctx = append(r.Ctx, "caller", fmt.Sprint(r.Call))
		return h.Log(r)
	})
}
func CallerFuncHandler(h Handler) Handler {
	return FuncHandler(h.MaxLevel(), func(r *Record) error {
		r.Ctx = append(r.Ctx, "fn", fmt.Sprintf("%+n", r.Call))
		return h.Log(r)
	})
}
func CallerStackHandler(format string, h Handler) Handler {
	return FuncHandler(h.MaxLevel(), func(r *Record) error {
		s := stack.Trace().TrimBelow(r.Call).TrimRuntime()
		if len(s) > 0 {
			r.Ctx = append(r.Ctx, "stack", fmt.Sprintf(format, s))
		}
		return h.Log(r)
	})
}
func FilterHandler(fn func(r *Record) bool, h Handler) Handler {
	return FuncHandler(h.MaxLevel(), func(r *Record) error {
		if fn(r) {
			return h.Log(r)
		}
		return nil
	})
}
func MatchFilterHandler(key string, value interface{}, h Handler) Handler {
	return FilterHandler(func(r *Record) (pass bool) {
		switch key {
		case r.KeyNames.Lvl:
			return r.Lvl == value
		case r.KeyNames.Time:
			return r.Time == value
		case r.KeyNames.Msg:
			return r.Msg == value
		}
		for i := 0; i < len(r.Ctx); i += 2 {
			if r.Ctx[i] == key {
				return r.Ctx[i+1] == value
			}
		}
		return false
	}, h)
}
func LvlFilterHandler(maxLvl Lvl, h Handler) Handler {
	h.SetMaxLevel(int(maxLvl))
	return FilterHandler(func(r *Record) (pass bool) {
		return r.Lvl <= maxLvl
	}, h)
}
func maxLevelHanldes(hs []Handler) int {
	maxLevel := 0
	for _, handle := range hs {
		if handle.MaxLevel() > maxLevel {
			maxLevel = handle.MaxLevel()
		}
	}
	return maxLevel
}
func MultiHandler(hs ...Handler) Handler {
	return FuncHandler(maxLevelHanldes(hs), func(r *Record) error {
		for _, h := range hs {
			h.Log(r)
		}
		return nil
	})
}
func FailoverHandler(hs ...Handler) Handler {
	return FuncHandler(maxLevelHanldes(hs), func(r *Record) error {
		var err error
		for i, h := range hs {
			err = h.Log(r)
			if err == nil {
				return nil
			}
			r.Ctx = append(r.Ctx, fmt.Sprintf("failover_err_%d", i), err)
		}
		return err
	})
}
func ChannelHandler(recs chan<- *Record, maxLevel int) Handler {
	return FuncHandler(maxLevel, func(r *Record) error {
		recs <- r
		return nil
	})
}
func BufferedHandler(bufSize int, h Handler) Handler {
	recs := make(chan *Record, bufSize)
	go func() {
		for m := range recs {
			_ = h.Log(m)
		}
	}()
	return ChannelHandler(recs, h.MaxLevel())
}
func LazyHandler(h Handler) Handler {
	return FuncHandler(h.MaxLevel(), func(r *Record) error {
		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.CallStack); ok {
						v = cs.TrimBelow(r.Call).TrimRuntime()
					}
					r.Ctx[i] = v
				}
			}
		}
		if hadErr {
			r.Ctx = append(r.Ctx, errorKey, "bad lazy")
		}
		return h.Log(r)
	})
}
func evaluateLazy(lz Lazy) (interface{}, error) {
	t := reflect.TypeOf(lz.Fn)
	if t.Kind() != reflect.Func {
		return nil, fmt.Errorf("INVALID_LAZY, not func: %+v", lz.Fn)
	}
	if t.NumIn() > 0 {
		return nil, fmt.Errorf("INVALID_LAZY, func takes args: %+v", lz.Fn)
	}
	if t.NumOut() == 0 {
		return nil, fmt.Errorf("INVALID_LAZY, no func return val: %+v", lz.Fn)
	}
	value := reflect.ValueOf(lz.Fn)
	results := value.Call([]reflect.Value{})
	if len(results) == 1 {
		return results[0].Interface(), nil
	}
	values := make([]interface{}, len(results))
	for i, v := range results {
		values[i] = v.Interface()
	}
	return values, nil
}