|
|
|
package starlog
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"math/rand"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/mattn/go-colorable"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
LvDebug = iota
|
|
|
|
LvInfo
|
|
|
|
LvNotice
|
|
|
|
LvWarning
|
|
|
|
LvError
|
|
|
|
LvCritical
|
|
|
|
LvPanic
|
|
|
|
LvFatal
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
levels = map[int]string{
|
|
|
|
LvDebug: "DEBUG",
|
|
|
|
LvInfo: "INFO",
|
|
|
|
LvNotice: "NOTICE",
|
|
|
|
LvWarning: "WARNING",
|
|
|
|
LvError: "ERROR",
|
|
|
|
LvCritical: "CRITICAL",
|
|
|
|
LvPanic: "PANIC",
|
|
|
|
LvFatal: "FATAL",
|
|
|
|
}
|
|
|
|
Colors = map[int][]Attr{
|
|
|
|
LvDebug: []Attr{FgWhite},
|
|
|
|
LvInfo: []Attr{FgGreen},
|
|
|
|
LvNotice: []Attr{FgBlue},
|
|
|
|
LvWarning: []Attr{FgYellow},
|
|
|
|
LvError: []Attr{FgMagenta},
|
|
|
|
LvCritical: []Attr{FgRed, Bold},
|
|
|
|
LvPanic: []Attr{FgRed, Bold},
|
|
|
|
LvFatal: []Attr{FgRed},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
type StarLogger struct {
|
|
|
|
mu *sync.Mutex
|
|
|
|
lock *sync.Mutex
|
|
|
|
Flag string
|
|
|
|
out io.Writer
|
|
|
|
ShowLine bool
|
|
|
|
ShowLevel bool
|
|
|
|
ShowFunc bool
|
|
|
|
ShowThread bool
|
|
|
|
DoWrite bool
|
|
|
|
DoShow bool
|
|
|
|
switching bool
|
|
|
|
isStd bool
|
|
|
|
//HandleFunc
|
|
|
|
waiting chan int
|
|
|
|
outshow io.Writer
|
|
|
|
LogLevel int
|
|
|
|
HandleFunc func([]Attr, string)
|
|
|
|
StdFuncColor bool
|
|
|
|
logbuf string
|
|
|
|
BufSize int
|
|
|
|
}
|
|
|
|
|
|
|
|
var Std = New(nil)
|
|
|
|
var StdFile *os.File
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
Std.DoShow = true
|
|
|
|
Std.Flag = "MAN"
|
|
|
|
Std.isStd = true
|
|
|
|
}
|
|
|
|
func Close() error {
|
|
|
|
if StdFile == nil {
|
|
|
|
return errors.New("File not Open")
|
|
|
|
}
|
|
|
|
if err := Std.Flush(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return StdFile.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(out io.Writer) *StarLogger {
|
|
|
|
rand.Seed(time.Now().UnixNano())
|
|
|
|
logger := new(StarLogger)
|
|
|
|
logger.DoShow = false
|
|
|
|
logger.mu = new(sync.Mutex)
|
|
|
|
logger.lock = new(sync.Mutex)
|
|
|
|
logger.ShowLevel = true
|
|
|
|
logger.ShowLine = true
|
|
|
|
logger.DoWrite = true
|
|
|
|
logger.ShowThread = true
|
|
|
|
logger.ShowFunc = false
|
|
|
|
logger.out = out
|
|
|
|
logger.outshow = colorable.NewColorableStdout()
|
|
|
|
logger.StdFuncColor = true
|
|
|
|
logger.BufSize = 0
|
|
|
|
logger.Flag = "MAN"
|
|
|
|
return logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Flush() error {
|
|
|
|
logger.mu.Lock()
|
|
|
|
defer logger.mu.Unlock()
|
|
|
|
logger.write(logger.logbuf)
|
|
|
|
logger.logbuf = ""
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewFlag() *StarLogger {
|
|
|
|
return Std.NewFlag()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) NewFlag() *StarLogger {
|
|
|
|
logger2 := new(StarLogger)
|
|
|
|
logger2.out = logger.out
|
|
|
|
logger2.ShowThread = logger.ShowThread
|
|
|
|
logger2.ShowFunc = logger.ShowFunc
|
|
|
|
logger2.DoShow = logger.DoShow
|
|
|
|
logger2.ShowLevel = logger.ShowLevel
|
|
|
|
logger2.ShowLine = logger.ShowLine
|
|
|
|
logger2.DoWrite = logger.DoWrite
|
|
|
|
logger2.outshow = logger.outshow
|
|
|
|
logger2.mu = logger.mu
|
|
|
|
logger2.lock = logger.lock
|
|
|
|
logger2.Flag = string([]byte{uint8(rand.Intn(26) + 65), uint8(rand.Intn(26) + 65), uint8(rand.Intn(26) + 65)})
|
|
|
|
if logger2.Flag == "MAN" {
|
|
|
|
logger2.Flag = "RYZ"
|
|
|
|
}
|
|
|
|
return logger2
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) write(logstr string) {
|
|
|
|
if (!logger.DoWrite) || (logger.out == nil) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
i := 0
|
|
|
|
for logger.switching {
|
|
|
|
time.Sleep(time.Millisecond * 100)
|
|
|
|
i++
|
|
|
|
if i > 20 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if &(logger.out) == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.out.Write([]byte(logstr))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) OutPut(logstr string) {
|
|
|
|
logger.out.Write([]byte(logstr))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) output(level int, logstr string) {
|
|
|
|
var logs string
|
|
|
|
var skip int = 2
|
|
|
|
logger.mu.Lock()
|
|
|
|
defer logger.mu.Unlock()
|
|
|
|
if level < logger.LogLevel {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if logger.isStd {
|
|
|
|
skip++
|
|
|
|
}
|
|
|
|
logger.isStd = false
|
|
|
|
pc, fname, line, ok := runtime.Caller(skip)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
funcname := runtime.FuncForPC(pc).Name()
|
|
|
|
funcname = filepath.Ext(funcname)
|
|
|
|
funcname = strings.TrimPrefix(funcname, ".")
|
|
|
|
fname = filepath.Base(fname)
|
|
|
|
date := time.Now().Format("2006-01-02 15:04:05.000 Mon")
|
|
|
|
logs = date
|
|
|
|
if logger.ShowLine {
|
|
|
|
logs += " " + fname + ":" + strconv.Itoa(line)
|
|
|
|
}
|
|
|
|
if logger.ShowFunc {
|
|
|
|
logs += " <" + funcname + ">"
|
|
|
|
}
|
|
|
|
if logger.ShowThread {
|
|
|
|
logs += " |" + logger.Flag + "|"
|
|
|
|
}
|
|
|
|
if logger.ShowLevel {
|
|
|
|
logs += " " + `[` + levels[level] + `]`
|
|
|
|
}
|
|
|
|
logs += " " + logstr
|
|
|
|
if logger.DoShow {
|
|
|
|
logcolor := NewColor(Colors[level]...)
|
|
|
|
logcolor.Fprint(logger.outshow, logs)
|
|
|
|
}
|
|
|
|
if logger.HandleFunc != nil {
|
|
|
|
go logger.HandleFunc(Colors[level], logs)
|
|
|
|
}
|
|
|
|
if logger.DoWrite {
|
|
|
|
if logger.BufSize == 0 {
|
|
|
|
logger.write(logs)
|
|
|
|
} else {
|
|
|
|
logger.logbuf += logs
|
|
|
|
if len(logger.logbuf) >= logger.BufSize {
|
|
|
|
logger.write(logs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Debug(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvDebug, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Debug(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Debug(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Debugf(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvDebug, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Debugf(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Debugf(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Debugln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvDebug, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Debugln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Debugln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Info(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvInfo, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Info(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Info(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Infof(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvInfo, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Infof(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Infof(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Infoln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvInfo, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Infoln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Infoln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Notice(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvNotice, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Notice(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Notice(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Noticef(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvNotice, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Noticef(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Noticef(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Noticeln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvNotice, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Noticeln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Noticeln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Warning(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvWarning, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Warning(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Warning(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Warningf(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvWarning, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Warningf(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Warningf(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Warningln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvWarning, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Warningln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Warningln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Error(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvError, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Error(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Error(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Errorf(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvError, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Errorf(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Errorf(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Errorln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvError, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Errorln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Errorln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Critical(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvCritical, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Critical(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Critical(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Criticalf(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvCritical, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Criticalf(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Criticalf(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Criticalln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvCritical, strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Criticalln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Criticalln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Fatal(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvFatal, strs)
|
|
|
|
os.Exit(9)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Fatal(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Fatal(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Fatalf(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvFatal, strs)
|
|
|
|
os.Exit(9)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Fatalf(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Fatalf(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Fatalln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvFatal, strs)
|
|
|
|
os.Exit(9)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Fatalln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Fatalln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Panic(str ...interface{}) {
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.output(LvPanic, strs)
|
|
|
|
panic(str)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Panic(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Panic(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Panicf(format string, str ...interface{}) {
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.output(LvPanic, strs)
|
|
|
|
panic(fmt.Sprintf(format, str...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func Panicf(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Panicf(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Panicln(str ...interface{}) {
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.output(LvPanic, strs)
|
|
|
|
panic(fmt.Sprintln(str...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func Panicln(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Panicln(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Print(str ...interface{}) {
|
|
|
|
logger.lock.Lock()
|
|
|
|
defer logger.lock.Unlock()
|
|
|
|
strs := fmt.Sprint(str...)
|
|
|
|
logger.OutPut(strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Print(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Print(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Printf(format string, str ...interface{}) {
|
|
|
|
logger.lock.Lock()
|
|
|
|
defer logger.lock.Unlock()
|
|
|
|
strs := fmt.Sprintf(format, str...)
|
|
|
|
logger.OutPut(strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Printf(format string, str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Printf(format, str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) Println(str ...interface{}) {
|
|
|
|
logger.lock.Lock()
|
|
|
|
defer logger.lock.Unlock()
|
|
|
|
strs := fmt.Sprintln(str...)
|
|
|
|
logger.OutPut(strs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Println(str ...interface{}) {
|
|
|
|
Std.isStd = true
|
|
|
|
Std.Println(str...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func StdPrint(c []Attr, str ...interface{}) {
|
|
|
|
Std.lock.Lock()
|
|
|
|
defer Std.lock.Unlock()
|
|
|
|
colorstr := NewColor(c...)
|
|
|
|
colorstr.Print(str...)
|
|
|
|
if Std.StdFuncColor && Std.HandleFunc != nil {
|
|
|
|
go Std.HandleFunc(c, fmt.Sprint(str...))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func StdPrintf(c []Attr, format string, str ...interface{}) {
|
|
|
|
Std.lock.Lock()
|
|
|
|
defer Std.lock.Unlock()
|
|
|
|
colorstr := NewColor(c...)
|
|
|
|
colorstr.Printf(format, str...)
|
|
|
|
if Std.StdFuncColor && Std.HandleFunc != nil {
|
|
|
|
go Std.HandleFunc(c, fmt.Sprintf(format, str...))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func StdPrintln(c []Attr, str ...interface{}) {
|
|
|
|
Std.lock.Lock()
|
|
|
|
defer Std.lock.Unlock()
|
|
|
|
colorstr := NewColor(c...)
|
|
|
|
colorstr.Println(str...)
|
|
|
|
if Std.StdFuncColor && Std.HandleFunc != nil {
|
|
|
|
go Std.HandleFunc(c, fmt.Sprintln(str...))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (logger *StarLogger) SwitchOut(out io.Writer) {
|
|
|
|
logger.lock.Lock()
|
|
|
|
defer logger.lock.Unlock()
|
|
|
|
logger.switching = true
|
|
|
|
logger.out = out
|
|
|
|
logger.switching = false
|
|
|
|
}
|
|
|
|
|
|
|
|
func SetLogFile(path string) error {
|
|
|
|
var err error
|
|
|
|
StdFile, err = os.Create(path)
|
|
|
|
Std.out = StdFile
|
|
|
|
Std.switching = false
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func SwitchFile(path string) error {
|
|
|
|
Std.switching = true
|
|
|
|
return SetLogFile(path)
|
|
|
|
}
|