func (l *Core) log(lvl Level, template string, fmtArgs, context []interface{}) bool {
	c := l.get()
	if !c.Enabled(zapcore.Level(lvl)) {
		return false
	}
	msg := template
	if msg == "" && len(fmtArgs) > 0 {
		msg = fmt.Sprint(fmtArgs...)
	} else if msg != "" && len(fmtArgs) > 0 {
		msg = fmt.Sprintf(template, fmtArgs...)
	}
	const callerSkipOffset = 2
	ent := zapcore.Entry{
		LoggerName: c.name,
		Time:       time.Now(),
		Level:      zapcore.Level(lvl),
		Message:    msg,
	}
	ce := c.Check(ent, nil)
	if ce == nil {
		return false
	}
	ce.ErrorOutput = c.errorOutput
	if c.addCaller {
		ce.Entry.Caller = zapcore.NewEntryCaller(runtime.Caller(l.callerSkip + callerSkipOffset))
		if !ce.Entry.Caller.Defined {
			_, _ = fmt.Fprintf(c.errorOutput, "%v Logger.check error: failed to get caller\n", time.Now().UTC())
			_ = ce.ErrorOutput.Sync()
		}
	}
	fields := append(l.context, l.sweetenFields(context)...)  
	for i := range c.hooks {
		if f := c.hooks[i](ce, fields); f != nil {
			fields = f
		}
	}
	for i := range l.hooks {
		if f := l.hooks[i](ce, fields); f != nil {
			fields = f
		}
	}
	ce.Write(fields...)
	return true
}
log must be called directly from one of the public methods to make the addcaller
resolution resolve the caller of the public method.
package flume
import (
	"fmt"
	"go.uber.org/multierr"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"runtime"
	"sync/atomic"
	"time"
)
var _ Logger = (*Core)(nil)
type atomicInnerCore struct {
	innerLoggerPtr atomic.Value
}
func (af *atomicInnerCore) get() *innerCore {
	return af.innerLoggerPtr.Load().(*innerCore)
}
func (af *atomicInnerCore) set(ic *innerCore) {
	af.innerLoggerPtr.Store(ic)
}
type innerCore struct {
	name string
	zapcore.Core
	addCaller   bool
	errorOutput zapcore.WriteSyncer
	hooks       []HookFunc
}
type Core struct {
	*atomicInnerCore
	context    []zap.Field
	callerSkip int
	hooks []HookFunc
}
func (l *Core) Log(lvl Level, template string, fmtArgs, context []interface{}) bool {
	return l.log(lvl, template, fmtArgs, context)
}