goc/pkg/log/terminal_logger.go
2021-04-05 09:06:53 +08:00

177 lines
3.3 KiB
Go

package log
import (
"fmt"
"io"
"os"
"sync"
goansi "github.com/k0kubun/go-ansi"
"github.com/mgutz/ansi"
"go.uber.org/zap/zapcore"
)
// goansi works nicer on Windows platform
var stdout = goansi.NewAnsiStdout()
var stderr = goansi.NewAnsiStderr()
type terminalLogger struct {
mutex sync.Mutex
level zapcore.Level
loadingText *loadingText
}
type levelFuncType int32
const (
fatalFn levelFuncType = iota
infoFn
errorFn
warnFn
debugFn
doneFn
)
type levelFuncInfo struct {
tag string
color string
level zapcore.Level
stream io.Writer
}
var levelFuncMap = map[levelFuncType]*levelFuncInfo{
doneFn: {
tag: "[done] √ ",
color: "green+b",
level: zapcore.InfoLevel,
stream: stdout,
},
debugFn: {
tag: "[debug] ",
color: "green+b",
level: zapcore.DebugLevel,
stream: stdout,
},
infoFn: {
tag: "[info] ",
color: "cyan+b",
level: zapcore.InfoLevel,
stream: stdout,
},
warnFn: {
tag: "[warn] ",
color: "magenta+b",
level: zapcore.WarnLevel,
stream: stdout,
},
errorFn: {
tag: "[error] ",
color: "yellow+b",
level: zapcore.ErrorLevel,
stream: stdout,
},
fatalFn: {
tag: "[fatal] ",
color: "red+b",
level: zapcore.FatalLevel,
stream: stdout,
},
}
func (t *terminalLogger) writeMessage(funcType levelFuncType, message string) {
funcInfo := levelFuncMap[funcType]
if t.level <= funcInfo.level {
// 如果当前有消息在加载,需先暂停
if t.loadingText != nil {
t.loadingText.stop()
}
funcInfo.stream.Write([]byte(ansi.Color(funcInfo.tag, funcInfo.color)))
funcInfo.stream.Write([]byte(message))
// 恢复加载
if t.loadingText != nil && funcType != fatalFn {
t.loadingText.start()
}
}
}
// StartWait prints a waiting message until StopWait is called
func (t *terminalLogger) StartWait(message string) {
t.mutex.Lock()
defer t.mutex.Unlock()
// 撤销之前的加载
if t.loadingText != nil {
t.loadingText.stop()
t.loadingText = nil
}
// 创建新的加载字符串
t.loadingText = &loadingText{
message: message,
stream: goansi.NewAnsiStdout(),
}
t.loadingText.start()
}
// StopWait stops waiting
func (t *terminalLogger) StopWait() {
t.mutex.Lock()
defer t.mutex.Unlock()
if t.loadingText != nil {
t.loadingText.stop()
t.loadingText = nil
}
}
func (t *terminalLogger) Sync() {
}
func (t *terminalLogger) Debugf(format string, args ...interface{}) {
t.mutex.Lock()
defer t.mutex.Unlock()
t.writeMessage(debugFn, fmt.Sprintf(format, args...)+"\n")
}
func (t *terminalLogger) Donef(format string, args ...interface{}) {
t.mutex.Lock()
defer t.mutex.Unlock()
t.writeMessage(doneFn, fmt.Sprintf(format, args...)+"\n")
}
func (t *terminalLogger) Infof(format string, args ...interface{}) {
t.mutex.Lock()
defer t.mutex.Unlock()
t.writeMessage(infoFn, fmt.Sprintf(format, args...)+"\n")
}
func (t *terminalLogger) Errorf(format string, args ...interface{}) {
t.mutex.Lock()
defer t.mutex.Unlock()
t.writeMessage(errorFn, fmt.Sprintf(format, args...)+"\n")
}
func (t *terminalLogger) Warnf(format string, args ...interface{}) {
t.mutex.Lock()
defer t.mutex.Unlock()
t.writeMessage(warnFn, fmt.Sprintf(format, args...)+"\n")
}
func (t *terminalLogger) Fatalf(format string, args ...interface{}) {
t.mutex.Lock()
defer t.mutex.Unlock()
t.writeMessage(fatalFn, fmt.Sprintf(format, args...)+"\n")
os.Exit(1)
}