// Console 是 writers.Console 的初始化函数
4145
func Console(cfg *config.Config) (io.Writer, error) {
	outputIndex, found := cfg.Attrs["output"]
	if !found {
		outputIndex = "stderr"
	}

	output, found := consoleOutputMap[outputIndex]
	if !found {
		return nil, fmt.Errorf("[%v]不是一个有效的控制台输出项", outputIndex)
	}

	fcIndex, found := cfg.Attrs["foreground"]
	if !found { // 默认用红色前景色
		fcIndex = "red"
	}
	fc, found := consoleColorMap[fcIndex]
	if !found {
		return nil, fmt.Errorf("无效的前景色[%v]", fcIndex)
	}

	bcIndex, found := cfg.Attrs["background"]
	if !found {
		bcIndex = "default"
	}
	bc, found := consoleColorMap[bcIndex]
	if !found {
		return nil, fmt.Errorf("无效的背景色[%v]", bcIndex)
	}

	return writers.NewConsole(output, fc, bc), nil
}
170807
func NewConsole() LoggerInterface {
	cw := &ConsoleWriter{
		Level: LevelDebug,
		lg:    log.New(os.Stdout, "", log.LstdFlags),
	}
	return cw
}
799619
func (w ConsoleWriter) Write(p []byte) (n int, err error) {
	if w.PartsOrder == nil {
		w.PartsOrder = consoleDefaultPartsOrder()
	}

	var buf = consoleBufPool.Get().(*bytes.Buffer)
	defer func() {
		buf.Reset()
		consoleBufPool.Put(buf)
	}()

	var evt map[string]interface{}
	p = decodeIfBinaryToBytes(p)
	d := json.NewDecoder(bytes.NewReader(p))
	d.UseNumber()
	err = d.Decode(&evt)
	if err != nil {
		return n, fmt.Errorf("cannot decode event: %s", err)
	}

	for _, p := range w.PartsOrder {
		w.writePart(buf, evt, p)
	}

	w.writeFields(evt, buf)

	err = buf.WriteByte('\n')
	if err != nil {
		return n, err
	}
	_, err = buf.WriteTo(w.Out)
	return len(p), err
}
766657
func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer) {
	var fields = make([]string, 0, len(evt))
	for field := range evt {
		switch field {
		case LevelFieldName, TimestampFieldName, MessageFieldName, CallerFieldName:
			continue
		}
		fields = append(fields, field)
	}
	sort.Strings(fields)

	if len(fields) > 0 {
		buf.WriteByte(' ')
	}

	// Move the "error" field to the front
	ei := sort.Search(len(fields), func(i int) bool { return fields[i] >= ErrorFieldName })
	if ei < len(fields) && fields[ei] == ErrorFieldName {
		fields[ei] = ""
		fields = append([]string{ErrorFieldName}, fields...)
		var xfields = make([]string, 0, len(fields))
		for _, field := range fields {
			if field == "" { // Skip empty fields
				continue
			}
			xfields = append(xfields, field)
		}
		fields = xfields
	}

	for i, field := range fields {
		var fn Formatter
		var fv Formatter

		if field == ErrorFieldName {
			if w.FormatErrFieldName == nil {
				fn = consoleDefaultFormatErrFieldName(w.NoColor)
			} else {
				fn = w.FormatErrFieldName
			}

			if w.FormatErrFieldValue == nil {
				fv = consoleDefaultFormatErrFieldValue(w.NoColor)
			} else {
				fv = w.FormatErrFieldValue
			}
		} else {
			if w.FormatFieldName == nil {
				fn = consoleDefaultFormatFieldName(w.NoColor)
			} else {
				fn = w.FormatFieldName
			}

			if w.FormatFieldValue == nil {
				fv = consoleDefaultFormatFieldValue
			} else {
				fv = w.FormatFieldValue
			}
		}

		buf.WriteString(fn(field))

		switch fValue := evt[field].(type) {
		case string:
			if needsQuote(fValue) {
				buf.WriteString(fv(strconv.Quote(fValue)))
			} else {
				buf.WriteString(fv(fValue))
			}
		case json.Number:
			buf.WriteString(fv(fValue))
		default:
			b, err := json.Marshal(fValue)
			if err != nil {
				fmt.Fprintf(buf, colorize("[error: %v]", colorRed, w.NoColor), err)
			} else {
				fmt.Fprint(buf, fv(b))
			}
		}

		if i < len(fields)-1 { // Skip space for last field
			buf.WriteByte(' ')
		}
	}
}
618174
func (writer *baseFileWriter) write(level LevelType, args ...interface{}) {
	writer.lock.RLock()
	defer writer.lock.RUnlock()
	var size = 0

	if writer.closed {
		return
	}

	size = writer.blog.write(level, args...)

	// logrotate
	if writer.sizeRotated || writer.lineRotated {
		writer.logSizeChan <- size
	}

	if nil != writer.hook && !(level < writer.hookLevel) {
		if writer.hookAsync {
			// 异步调用log hook
			go writer.hook.Fire(level, writer.blog.Tags(), args...)
		} else {
			writer.hook.Fire(level, writer.blog.Tags(), args...)
		}
	}
}
1139825
func NewConsoleWriter(options ...func(w *ConsoleWriter)) ConsoleWriter {
	w := ConsoleWriter{
		Out:        os.Stdout,
		TimeFormat: consoleDefaultTimeFormat,
		PartsOrder: consoleDefaultPartsOrder(),
	}

	for _, opt := range options {
		opt(&w)
	}

	return w
}
430924
func NewConsoleLogWriter() *ConsoleLogWriter {
	consoleWriter := &ConsoleLogWriter{
		format: "[%T %D] [%L] (%S) %M",
		w:      make(chan *LogRecord, LogBufferLength),
	}
	go consoleWriter.run(stdout)
	return consoleWriter
}
418322
func (c *Console) consoleOutput(call otto.FunctionCall) otto.Value {
	var output []string
	for _, argument := range call.ArgumentList {
		output = append(output, fmt.Sprintf("%v", argument))
	}
	fmt.Fprintln(c.printer, strings.Join(output, " "))
	return otto.Value{}
}
697626
func (dl *ConsoleLogger) Error(message interface{}, params ...interface{}) {
	dl.logger.Errorf(fmt.Sprintf("%s %s", caller(), fmt.Sprint(message)), params...)
}
58395
func (dbch debugBatch) WriteSync() {
	fmt.Printf("%v.batch.WriteSync()\n", dbch.label)
	dbch.bch.WriteSync()
}
1333982
func (t *ConsoleFormatter) Format(errin error) (errtext string, err error) {
	return t.FormatSkip(errin, 1)
}
714795
func OptionWriter(x ConsoleWriter) Option {
	return func(p *Prompt) error {
		registerConsoleWriter(x)
		p.renderer.out = x
		return nil
	}
}
1042544
func (l *ConsoleLogger) Close() {
	l.closed = true
	l.output(&Message{len(l.levels) - 1, "Closing log now", time.Now()})
	l.out.Close()
}
85201
func (c *ConsoleWriter) WriteMsg(msg string, level int) error {
	if level > c.Level {
		return nil
	}
	if goos := runtime.GOOS; goos == "windows" {
		c.lg.Println(msg)
		return nil
	}
	c.lg.Println(colors[level](msg))

	return nil
}
431942
func (writer *ConsoleWriter) Close() {
	writer.lock.Lock()
	defer writer.lock.Unlock()

	if writer.closed {
		return
	}

	writer.blog.flush()
	writer.blog = nil
	writer.closed = true
}
1320242
func Stderr() io.Writer {
	stderr := colorable.NewColorableStderr()
	if stderr == os.Stderr {
		return os.Stderr
	}

	return &WinColorTerminal{output: stderr}
}
1238479
func (t *ConsoleTarget) Open(io.Writer) error {
	t.Filter.Init()
	if t.Writer == nil {
		return errors.New("ConsoleTarget.Writer cannot be nil")
	}
	if runtime.GOOS == "windows" {
		t.ColorMode = false
	}
	return nil
}