| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- package log
- import (
- "fmt"
- "io"
- "os"
- "path"
- "runtime"
- "sync"
- "time"
- "strconv"
- "github.com/mattn/go-colorable"
- "github.com/mattn/go-isatty"
- "github.com/valyala/fasttemplate"
- "github.com/labstack/gommon/color"
- )
- type (
- Logger struct {
- prefix string
- level uint8
- output io.Writer
- template *fasttemplate.Template
- levels []string
- color color.Color
- mutex sync.Mutex
- }
- )
- const (
- DEBUG = iota
- INFO
- WARN
- ERROR
- FATAL
- OFF
- )
- var (
- global = New("-")
- defaultFormat = "time=${time_rfc3339}, level=${level}, prefix=${prefix}, file=${short_file}, " +
- "line=${line}, ${message}\n"
- )
- func New(prefix string) (l *Logger) {
- l = &Logger{
- level: INFO,
- prefix: prefix,
- template: l.newTemplate(defaultFormat),
- }
- l.SetOutput(colorable.NewColorableStdout())
- return
- }
- func (l *Logger) initLevels() {
- l.levels = []string{
- l.color.Blue("DEBUG"),
- l.color.Green("INFO"),
- l.color.Yellow("WARN"),
- l.color.Red("ERROR"),
- l.color.RedBg("FATAL"),
- }
- }
- func (l *Logger) newTemplate(format string) *fasttemplate.Template {
- return fasttemplate.New(format, "${", "}")
- }
- func (l *Logger) DisableColor() {
- l.color.Disable()
- l.initLevels()
- }
- func (l *Logger) EnableColor() {
- l.color.Enable()
- l.initLevels()
- }
- func (l *Logger) Prefix() string {
- return l.prefix
- }
- func (l *Logger) SetPrefix(p string) {
- l.prefix = p
- }
- func (l *Logger) Level() uint8 {
- return l.level
- }
- func (l *Logger) SetLevel(v uint8) {
- l.level = v
- }
- func (l *Logger) Output() io.Writer {
- return l.output
- }
- func (l *Logger) SetFormat(f string) {
- l.template = l.newTemplate(f)
- }
- func (l *Logger) SetOutput(w io.Writer) {
- l.output = w
- l.DisableColor()
- if w, ok := w.(*os.File); ok && isatty.IsTerminal(w.Fd()) {
- l.EnableColor()
- }
- }
- func (l *Logger) Print(i ...interface{}) {
- fmt.Fprintln(l.output, i...)
- }
- func (l *Logger) Printf(format string, args ...interface{}) {
- f := fmt.Sprintf("%s\n", format)
- fmt.Fprintf(l.output, f, args...)
- }
- func (l *Logger) Debug(i ...interface{}) {
- l.log(DEBUG, "", i...)
- }
- func (l *Logger) Debugf(format string, args ...interface{}) {
- l.log(DEBUG, format, args...)
- }
- func (l *Logger) Info(i ...interface{}) {
- l.log(INFO, "", i...)
- }
- func (l *Logger) Infof(format string, args ...interface{}) {
- l.log(INFO, format, args...)
- }
- func (l *Logger) Warn(i ...interface{}) {
- l.log(WARN, "", i...)
- }
- func (l *Logger) Warnf(format string, args ...interface{}) {
- l.log(WARN, format, args...)
- }
- func (l *Logger) Error(i ...interface{}) {
- l.log(ERROR, "", i...)
- }
- func (l *Logger) Errorf(format string, args ...interface{}) {
- l.log(ERROR, format, args...)
- }
- func (l *Logger) Fatal(i ...interface{}) {
- l.log(FATAL, "", i...)
- os.Exit(1)
- }
- func (l *Logger) Fatalf(format string, args ...interface{}) {
- l.log(FATAL, format, args...)
- os.Exit(1)
- }
- func DisableColor() {
- global.DisableColor()
- }
- func EnableColor() {
- global.EnableColor()
- }
- func Prefix() string {
- return global.Prefix()
- }
- func SetPrefix(p string) {
- global.SetPrefix(p)
- }
- func Level() uint8 {
- return global.Level()
- }
- func SetLevel(v uint8) {
- global.SetLevel(v)
- }
- func Output() io.Writer {
- return global.Output()
- }
- func SetOutput(w io.Writer) {
- global.SetOutput(w)
- }
- func SetFormat(f string) {
- global.SetFormat(f)
- }
- func Print(i ...interface{}) {
- global.Print(i...)
- }
- func Printf(format string, args ...interface{}) {
- global.Printf(format, args...)
- }
- func Debug(i ...interface{}) {
- global.Debug(i...)
- }
- func Debugf(format string, args ...interface{}) {
- global.Debugf(format, args...)
- }
- func Info(i ...interface{}) {
- global.Info(i...)
- }
- func Infof(format string, args ...interface{}) {
- global.Infof(format, args...)
- }
- func Warn(i ...interface{}) {
- global.Warn(i...)
- }
- func Warnf(format string, args ...interface{}) {
- global.Warnf(format, args...)
- }
- func Error(i ...interface{}) {
- global.Error(i...)
- }
- func Errorf(format string, args ...interface{}) {
- global.Errorf(format, args...)
- }
- func Fatal(i ...interface{}) {
- global.Fatal(i...)
- }
- func Fatalf(format string, args ...interface{}) {
- global.Fatalf(format, args...)
- }
- func (l *Logger) log(v uint8, format string, args ...interface{}) {
- l.mutex.Lock()
- defer l.mutex.Unlock()
- _, file, line, _ := runtime.Caller(3)
- if v >= l.level {
- message := ""
- if format == "" {
- message = fmt.Sprint(args...)
- } else {
- message = fmt.Sprintf(format, args...)
- }
- l.template.ExecuteFunc(l.output, func(w io.Writer, tag string) (int, error) {
- switch tag {
- case "time_rfc3339":
- return w.Write([]byte(time.Now().Format(time.RFC3339)))
- case "level":
- return w.Write([]byte(l.levels[v]))
- case "prefix":
- return w.Write([]byte(l.prefix))
- case "long_file":
- return w.Write([]byte(file))
- case "short_file":
- return w.Write([]byte(path.Base(file)))
- case "line":
- return w.Write([]byte(strconv.Itoa(line)))
- case "message":
- return w.Write([]byte(message))
- default:
- return w.Write([]byte(fmt.Sprintf("[unknown tag %s]", tag)))
- }
- })
- }
- }
|