klog/log.go

267 lines
4.8 KiB
Go
Raw Permalink Normal View History

2021-11-03 19:02:27 +00:00
package klog
2021-11-01 14:38:30 +00:00
import (
2021-11-03 05:51:59 +00:00
"encoding/json"
2021-11-01 14:38:30 +00:00
"fmt"
"io"
"os"
2021-11-02 07:26:10 +00:00
"sync"
2021-11-01 14:38:30 +00:00
"time"
"github.com/mattn/go-isatty"
)
2021-11-05 07:41:54 +00:00
type Llevel int
2021-11-01 14:38:30 +00:00
const (
2021-11-05 07:41:54 +00:00
Lerror Llevel = 1 << iota
2021-11-01 14:41:11 +00:00
Ldebug
2021-11-01 14:38:30 +00:00
Lwarn
Linfo
2021-11-01 14:41:11 +00:00
)
2021-11-02 07:26:10 +00:00
var lock sync.Mutex
2021-11-01 14:38:30 +00:00
var PROD = true
2021-11-08 08:45:19 +00:00
var STACKSKIP = 0
2021-11-01 14:38:30 +00:00
var LEVEL = Lerror | Linfo
type H map[string]interface{}
type Ldata struct {
Message string
2021-11-05 07:41:54 +00:00
Time time.Time
Level Llevel
2021-11-01 14:38:30 +00:00
// Caller only evaluates in DEBUG, and ERROR calls
Caller string
// Stack only eval when !PROD and {DEBUG, ERROR}
Stack string
2021-11-05 08:31:11 +00:00
Fields H
2021-11-01 14:38:30 +00:00
Color bool
}
2021-11-01 18:07:05 +00:00
type Logger struct {
2021-11-05 07:41:54 +00:00
System string
2021-11-01 14:38:30 +00:00
color bool
2021-11-02 07:26:10 +00:00
explicit bool
2021-11-01 14:38:30 +00:00
err io.Writer
out io.Writer
2021-11-05 07:41:54 +00:00
printer Printer
subs []*Logger
}
type Printer func(io.Writer, *Ldata, *Logger)
func DefaultPrinter() Printer {
return func(w io.Writer, d *Ldata, l *Logger) {
var level string
caller := ""
sys := ""
if l.System != "" {
sys = fmt.Sprintf("(%s)", l.System)
}
2021-11-10 07:48:44 +00:00
fields := ""
2021-11-05 07:41:54 +00:00
if d.Fields != nil {
b, err := json.Marshal(d.Fields)
if err != nil {
2021-11-10 07:48:44 +00:00
fields = l.M(string(b), FgHiGreen)
2021-11-05 07:41:54 +00:00
}
}
2021-11-10 07:48:44 +00:00
stack := ""
if d.Stack != "" {
stack = l.M(d.Stack, FgRed)
}
2021-11-05 07:41:54 +00:00
switch d.Level {
case Lerror:
level = l.M("ERROR", FgHiRed)
2021-11-05 07:41:54 +00:00
caller = d.Caller
case Ldebug:
level = l.M("DEBUG", FgHiMagenta)
2021-11-05 07:41:54 +00:00
caller = d.Caller
case Lwarn:
level = l.M("WARN ", FgHiYellow)
2021-11-05 07:41:54 +00:00
case Linfo:
level = l.M("INFO ", FgHiBlue)
2021-11-05 07:41:54 +00:00
}
_, err := fmt.Fprintf(w, "%s [%s]%s%s %s%s\n%s",
d.Time.Format("2006/01/02 15:04:05"),
level, l.M(sys, FgHiCyan),
2021-11-10 07:48:44 +00:00
caller, d.Message, fields,
stack,
2021-11-05 07:41:54 +00:00
)
if err != nil {
fmt.Println(err)
}
}
}
2021-11-04 02:35:56 +00:00
2021-11-05 07:41:54 +00:00
func (l *Logger) output(lev Llevel, depth int, fields H, v ...interface{}) {
if LEVEL&lev == 0 {
return
}
msg := fmt.Sprint(v...)
data := &Ldata{
2021-11-05 08:31:11 +00:00
Fields: fields,
2021-11-05 07:41:54 +00:00
Message: msg,
Level: lev,
Time: time.Now(),
Color: l.color,
}
2021-11-08 08:45:19 +00:00
if !PROD {
switch lev {
case Lerror:
if STACKSKIP == 0 {
data.Stack = Stack()
2021-11-08 08:49:23 +00:00
} else if STACKSKIP > 0 {
2021-11-08 08:45:19 +00:00
data.Stack = StackSkip(STACKSKIP)
}
data.Caller = Caller(depth)
case Ldebug:
data.Caller = Caller(depth)
// disable stack trace on debug
// data.Stack = Stack()
2021-11-05 07:41:54 +00:00
}
}
lock.Lock()
defer lock.Unlock()
if lev == Lerror || lev == Ldebug {
l.printer(l.err, data, l)
} else {
l.printer(l.out, data, l)
}
2021-11-01 14:38:30 +00:00
}
2021-11-02 03:08:23 +00:00
func New(name string) *Logger {
2021-11-01 18:07:05 +00:00
l := &Logger{
2021-11-05 07:41:54 +00:00
System: name,
err: os.Stderr,
out: os.Stdout,
color: true,
printer: DefaultPrinter(),
2021-11-01 14:38:30 +00:00
}
2021-11-05 07:41:54 +00:00
l.guessColor()
2021-11-01 14:38:30 +00:00
return l
}
2021-11-01 18:07:05 +00:00
func (l *Logger) Sub(sys string) *Logger {
ret := &Logger{
2021-11-05 07:41:54 +00:00
System: sys,
err: l.err,
out: l.out,
color: l.color,
printer: l.printer,
2021-11-01 14:41:11 +00:00
}
2021-11-02 03:08:23 +00:00
if l.subs == nil {
l.subs = make([]*Logger, 0)
}
l.subs = append(l.subs, ret)
2021-11-01 14:41:11 +00:00
return ret
}
2021-11-01 18:07:05 +00:00
func (l *Logger) guessColor() {
2021-11-01 16:50:15 +00:00
l.color = true
2021-11-01 14:38:30 +00:00
if w, ok := l.out.(*os.File); !ok || os.Getenv("TERM") == "dumb" ||
(!isatty.IsTerminal(w.Fd()) && !isatty.IsCygwinTerminal(w.Fd())) {
l.color = false
}
2021-11-01 16:50:15 +00:00
if w, ok := l.err.(*os.File); !ok || os.Getenv("TERM") == "dumb" ||
(!isatty.IsTerminal(w.Fd()) && !isatty.IsCygwinTerminal(w.Fd())) {
l.color = false
}
2021-11-01 14:38:30 +00:00
}
2021-11-01 18:07:05 +00:00
func (l *Logger) SetColor(c bool) {
2021-11-02 07:26:10 +00:00
l.explicit = true
2021-11-01 14:38:30 +00:00
l.color = c
}
2021-11-02 07:26:10 +00:00
func (l *Logger) SetColorAll(c bool) {
for _, v := range getAllOffsprings(l) {
v.SetColor(c)
}
}
2021-11-01 18:07:05 +00:00
func (l *Logger) SetErrOutput(err io.Writer) {
2021-11-01 16:50:15 +00:00
l.err = err
2021-11-05 07:41:54 +00:00
l.guessColor()
2021-11-01 16:50:15 +00:00
}
2021-11-02 03:08:23 +00:00
func (l *Logger) SetErrOutputAll(err io.Writer) {
for _, v := range getAllOffsprings(l) {
2021-11-05 07:41:54 +00:00
v.SetErrOutput(err)
2021-11-02 03:08:23 +00:00
}
}
2021-11-01 18:07:05 +00:00
func (l *Logger) SetOutput(out io.Writer) {
2021-11-01 16:50:15 +00:00
l.out = out
2021-11-05 07:41:54 +00:00
l.guessColor()
2021-11-01 16:50:15 +00:00
}
2021-11-02 03:08:23 +00:00
func (l *Logger) SetOutputAll(out io.Writer) {
for _, v := range getAllOffsprings(l) {
2021-11-05 07:41:54 +00:00
v.SetOutput(out)
2021-11-02 03:08:23 +00:00
}
}
func (l *Logger) GetPrinter() Printer {
return l.printer
}
2021-11-05 07:41:54 +00:00
func (l *Logger) SetPrinter(p Printer) {
l.printer = p
2021-11-01 16:50:15 +00:00
}
2021-11-05 07:41:54 +00:00
func (l *Logger) SetPrinterAll(p Printer) {
2021-11-02 03:08:23 +00:00
for _, v := range getAllOffsprings(l) {
2021-11-05 07:41:54 +00:00
v.SetPrinter(p)
2021-11-01 14:38:30 +00:00
}
}
2021-11-05 07:41:54 +00:00
// func (l *Logger) DefaultFuncMap() template.FuncMap {
// funcMap := template.FuncMap{
// "Time": func() string { return time.Now().Format("2006/01/02 15:04:05") },
// "json": func(i interface{}) (string, error) { r, err := json.Marshal(i); return string(r), err },
// }
// return funcMap
// }
2021-11-01 14:38:30 +00:00
2021-11-01 18:07:05 +00:00
func (l *Logger) ErrorF(fields H, v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Lerror, 3, fields, v...)
2021-11-01 14:38:30 +00:00
}
2021-11-01 18:07:05 +00:00
func (l *Logger) Error(v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Lerror, 3, H{}, v...)
2021-11-01 14:38:30 +00:00
}
2021-11-01 18:07:05 +00:00
func (l *Logger) DebugF(fields H, v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Ldebug, 3, fields, v...)
2021-11-01 14:38:30 +00:00
}
2021-11-01 18:07:05 +00:00
func (l *Logger) Debug(v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Ldebug, 3, H{}, v...)
2021-11-01 14:38:30 +00:00
}
2021-11-01 14:41:11 +00:00
2021-11-01 18:07:05 +00:00
func (l *Logger) WarnF(fields H, v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Lwarn, 3, fields, v...)
2021-11-01 14:41:11 +00:00
}
2021-11-01 18:07:05 +00:00
func (l *Logger) Warn(v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Lwarn, 3, H{}, v...)
2021-11-01 14:41:11 +00:00
}
2021-11-01 18:07:05 +00:00
func (l *Logger) InfoF(fields H, v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Linfo, 3, fields, v...)
2021-11-01 14:41:11 +00:00
}
2021-11-01 18:07:05 +00:00
func (l *Logger) Info(v ...interface{}) {
2021-11-05 07:41:54 +00:00
l.output(Linfo, 3, H{}, v...)
2021-11-01 14:41:11 +00:00
}