go-common/app/tool/bgr/log/log.go
2019-04-22 18:49:16 +08:00

161 lines
3.3 KiB
Go

package log
import (
"fmt"
"io"
"os"
"strings"
"sync"
"go-common/app/tool/bgr/log/color"
"golang.org/x/crypto/ssh/terminal"
)
// FDWriter interface extends io.Writer with file descriptor function
type FDWriter interface {
io.Writer
Fd() uintptr
}
// Logger struct definition
type Logger struct {
mu sync.RWMutex
out FDWriter
color bool
debug bool
buf strings.Builder
}
type prefix struct {
Plain string
Color string
}
const (
_plainError = "[ ERROR ] "
_plainWarn = "[ WARN ] "
_plainInfo = "[ INFO ] "
_plainDebug = "[ DEBUG ] "
_plainFatal = "[ FATAL ] "
)
var (
_prefixError = prefix{
Plain: _plainError,
Color: colorful.Red(_plainError),
}
_prefixWarn = prefix{
Plain: _plainWarn,
Color: colorful.Orange(_plainWarn),
}
_prefixInfo = prefix{
Plain: _plainInfo,
Color: colorful.Green(_plainInfo),
}
_prefixDebug = prefix{
Plain: _plainDebug,
Color: colorful.Purple(_plainDebug),
}
_prefixFatal = prefix{
Plain: _plainFatal,
Color: colorful.Gray(_plainFatal),
}
)
// New returns new Logger instance with predefined writer output and
// automatically detect terminal coloring support
func New(out FDWriter, debug bool) *Logger {
return &Logger{
color: terminal.IsTerminal(int(out.Fd())),
out: out,
debug: debug,
buf: strings.Builder{},
}
}
func (l *Logger) output(prefix prefix, data string) (err error) {
l.mu.Lock()
defer l.mu.Unlock()
l.buf.Reset()
if l.color {
if _, err = l.buf.WriteString(prefix.Color); err != nil {
return
}
} else {
if _, err = l.buf.WriteString(prefix.Plain); err != nil {
return
}
}
if _, err = l.buf.WriteString(data); err != nil {
return
}
if data[len(data)-1] != '\n' {
l.buf.WriteString("\n")
}
_, err = l.out.Write([]byte(l.buf.String()))
return
}
// Error print error message to output
func (l *Logger) Error(v ...interface{}) {
l.output(_prefixError, fmt.Sprintln(v...))
}
// Errorf print formatted error message to output
func (l *Logger) Errorf(format string, v ...interface{}) {
l.output(_prefixError, fmt.Sprintf(format, v...))
}
// Warn print warning message to output
func (l *Logger) Warn(v ...interface{}) {
l.output(_prefixWarn, fmt.Sprintln(v...))
}
// Warnf print formatted warning message to output
func (l *Logger) Warnf(format string, v ...interface{}) {
l.output(_prefixWarn, fmt.Sprintf(format, v...))
}
// Info print informational message to output
func (l *Logger) Info(v ...interface{}) {
l.output(_prefixInfo, fmt.Sprintln(v...))
}
// Infof print formatted informational message to output
func (l *Logger) Infof(format string, v ...interface{}) {
l.output(_prefixInfo, fmt.Sprintf(format, v...))
}
// Debug print debug message to output if debug output enabled
func (l *Logger) Debug(v ...interface{}) {
if l.debug {
l.output(_prefixDebug, fmt.Sprintln(v...))
}
}
// Debugf print formatted debug message to output if debug output enabled
func (l *Logger) Debugf(format string, v ...interface{}) {
if l.debug {
l.output(_prefixDebug, fmt.Sprintf(format, v...))
}
}
// Fatal print fatal message to output and then exit(1)
func (l *Logger) Fatal(v ...interface{}) {
l.output(_prefixFatal, fmt.Sprintln(v...))
os.Exit(1)
}
// Fatalf print formatted fatal message to output and then exit(1)
func (l *Logger) Fatalf(format string, v ...interface{}) {
l.output(_prefixFatal, fmt.Sprintf(format, v...))
os.Exit(1)
}