func (o *log) Log(level Level, args ...interface{}) {
	o.log(level, fmt.Sprint(args...))
}
Log uses the given parameters to record a log of the specified level.
If the given log level is PanicLevel, the given panic function will be
called automatically after logging is completed.
If the given log level is FatalLevel, the given exit function will be
called automatically after logging is completed.
If the given log level is invalid, the log will be discarded.
package logger
import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"sync"
	"time"
	"github.com/edoger/zkits-logger/internal"
)
type Log interface {
	Name() string
	WithField(string, interface{}) Log
	WithError(error) Log
	WithFields(map[string]interface{}) Log
	WithContext(context.Context) Log
	WithCaller(...int) Log
	Log(Level, ...interface{})
	Logln(Level, ...interface{})
	Logf(Level, string, ...interface{})
	Trace(...interface{})
	Traceln(...interface{})
	Tracef(string, ...interface{})
	Print(...interface{})
	Println(...interface{})
	Printf(string, ...interface{})
	Debug(...interface{})
	Debugln(...interface{})
	Debugf(string, ...interface{})
	Info(...interface{})
	Infoln(...interface{})
	Infof(string, ...interface{})
	Echo(...interface{})
	Echoln(...interface{})
	Echof(string, ...interface{})
	Warn(...interface{})
	Warnln(...interface{})
	Warnf(string, ...interface{})
	Warning(...interface{})
	Warningln(...interface{})
	Warningf(string, ...interface{})
	Error(...interface{})
	Errorln(...interface{})
	Errorf(string, ...interface{})
	Fatal(...interface{})
	Fatalln(...interface{})
	Fatalf(string, ...interface{})
	Panic(...interface{})
	Panicln(...interface{})
	Panicf(string, ...interface{})
}
type core struct {
	name        string
	level       Level
	formatter   Formatter
	writer      io.Writer
	levelWriter map[Level]io.Writer
	pool        sync.Pool
	hooks       HookBag
	timeFormat  string
	nowFunc     func() time.Time
	exitFunc    func(int)
	panicFunc   func(string)
	caller      *internal.CallerReporter
	levelCaller map[Level]*internal.CallerReporter
	interceptor func(Summary, io.Writer) (int, error)
}
func newCore(name string) *core {
	return &core{
		name:        name,
		level:       TraceLevel,
		formatter:   DefaultJSONFormatter(),
		writer:      os.Stdout,
		levelWriter: make(map[Level]io.Writer),
		pool:        sync.Pool{New: func() interface{} { return new(logEntity) }},
		hooks:       NewHookBag(),
		timeFormat:  internal.DefaultTimeFormat,
		nowFunc:     internal.DefaultNowFunc,
		exitFunc:    internal.DefaultExitFunc,
		panicFunc:   internal.DefaultPanicFunc,
		levelCaller: make(map[Level]*internal.CallerReporter),
	}
}
func (c *core) getEntity(l *log, level Level, message, caller string) *logEntity {
	o := c.pool.Get().(*logEntity)
	o.name = c.name
	o.time = c.nowFunc()
	o.timeFormat = c.timeFormat
	o.level = level
	o.message = message
	o.ctx = l.ctx
	o.caller = caller
	o.fields = l.fields
	return o
}
func (c *core) putEntity(o *logEntity) {
	if o.buffer.Cap() > 1024 {
		o.buffer = bytes.Buffer{}
	} else {
		o.buffer.Reset()
	}
	o.name = ""
	o.timeFormat = ""
	o.message = ""
	o.fields = nil
	o.ctx = nil
	o.caller = ""
	c.pool.Put(o)
}
type log struct {
	core   *core
	ctx    context.Context
	fields internal.Fields
	caller *internal.CallerReporter
}
func (o *log) Name() string {
	return o.core.name
}
func (o *log) WithField(key string, value interface{}) Log {
	if len(o.fields) == 0 {
		return &log{core: o.core, fields: internal.Fields{key: value}, ctx: o.ctx, caller: o.caller}
	}
	r := &log{core: o.core, fields: o.fields.Clone(1), ctx: o.ctx, caller: o.caller}
	r.fields[key] = value
	return r
}
func (o *log) WithError(err error) Log {
	return o.WithField("error", err)
}
func (o *log) WithFields(fields map[string]interface{}) Log {
	if len(o.fields) == 0 {
		return &log{core: o.core, fields: internal.MakeFields(fields), ctx: o.ctx, caller: o.caller}
	}
	return &log{core: o.core, fields: o.fields.With(fields), ctx: o.ctx, caller: o.caller}
}
func (o *log) WithContext(ctx context.Context) Log {
	return &log{core: o.core, fields: o.fields, ctx: ctx, caller: o.caller}
}
func (o *log) WithCaller(skip ...int) Log {
	var n int
	if len(skip) > 0 && skip[0] > 0 {
		n = skip[0]
	}
	if o.caller != nil && o.caller.Equal(n) {
		return o
	}
	return &log{core: o.core, fields: o.fields, ctx: o.ctx, caller: internal.NewCallerReporter(n)}
}
func (o *log) record(level Level, message string) {
	entity := o.core.getEntity(o, level, message, o.getCaller(level))
	defer o.core.putEntity(entity)
	if err := o.core.formatter.Format(entity, &entity.buffer); err != nil {
		internal.EchoError("(%s) Failed to format log: %s", o.core.name, err)
	} else {
		err = o.core.hooks.Fire(entity)
		if err != nil {
			internal.EchoError("(%s) Failed to fire log hook: %s", o.core.name, err)
		}
		err = o.write(entity)
		if err != nil {
			internal.EchoError("(%s) Failed to write log: %s", o.core.name, err)
		}
	}
	if level < ErrorLevel {
		switch level {
		case FatalLevel:
			o.core.exitFunc(1)
		case PanicLevel:
			o.core.panicFunc(message)
		}
	}
}
func (o *log) write(entity *logEntity) (err error) {
	var w io.Writer
	if writer, found := o.core.levelWriter[entity.level]; found && writer != nil {
		w = writer
	} else {
		w = o.core.writer
	}
	if o.core.interceptor == nil {
		if entity.Size() > 0 {
			_, err = w.Write(entity.Bytes())
		}
	} else {
		_, err = o.core.interceptor(entity, w)
	}
	return
}
func (o *log) getCaller(level Level) string {
	if o.caller != nil {
		return o.caller.GetCaller()
	}
	if caller, found := o.core.levelCaller[level]; found {
		return caller.GetCaller()
	}
	if o.core.caller != nil {
		return o.core.caller.GetCaller()
	}
	return ""
}