You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
starlog/starlog.go

705 lines
14 KiB
Go

5 years ago
package starlog
import (
"errors"
5 years ago
"fmt"
4 years ago
"io"
"math/rand"
5 years ago
"os"
"path/filepath"
5 years ago
"runtime"
5 years ago
"strconv"
"strings"
4 years ago
"sync"
5 years ago
"time"
4 years ago
"b612.me/starmap"
4 years ago
"github.com/mattn/go-colorable"
5 years ago
)
5 years ago
5 years ago
const (
LvDebug = iota
LvInfo
LvNotice
LvWarning
LvError
LvCritical
LvPanic
LvFatal
)
5 years ago
5 years ago
var (
levels = map[int]string{
LvDebug: "DEBUG",
LvInfo: "INFO",
LvNotice: "NOTICE",
LvWarning: "WARNING",
LvError: "ERROR",
LvCritical: "CRITICAL",
LvPanic: "PANIC",
LvFatal: "FATAL",
5 years ago
}
4 years ago
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},
5 years ago
}
4 years ago
stdLock sync.Mutex
logmaps sync.Map
5 years ago
)
4 years ago
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
4 years ago
//handleFunc
stopChan chan int
setChan chan int
4 years ago
outshow io.Writer
LogLevel int
4 years ago
handleFunc func([]Attr, string)
4 years ago
StdFuncColor bool
logbuf string
BufSize int
4 years ago
stacks starmap.StarStack
}
type logTran struct {
color []Attr
log string
4 years ago
}
var Std = New(nil)
var StdFile *os.File
4 years ago
func init() {
Std.DoShow = true
Std.Flag = "MAN"
Std.isStd = true
4 years ago
logmaps.Store("std", Std)
}
4 years ago
func Close() error {
if StdFile == nil {
return errors.New("File not Open")
}
if err := Std.Flush(); err != nil {
return err
}
return StdFile.Close()
4 years ago
}
func New(out io.Writer) *StarLogger {
rand.Seed(time.Now().UnixNano())
4 years ago
logger := new(StarLogger)
logger.DoShow = false
logger.mu = new(sync.Mutex)
logger.lock = new(sync.Mutex)
4 years ago
logger.ShowLevel = true
logger.ShowLine = true
logger.DoWrite = true
logger.ShowThread = true
logger.ShowFunc = false
4 years ago
logger.out = out
logger.outshow = colorable.NewColorableStdout()
logger.StdFuncColor = true
logger.BufSize = 0
logger.Flag = "MAN"
4 years ago
logger.stopChan, logger.setChan = make(chan int), make(chan int)
go logger.runTransfer()
logmaps.Store(fmt.Sprint(time.Now().UnixNano()), logger)
4 years ago
return logger
}
4 years ago
func (logger *StarLogger) SetHandleFunc(funcs func([]Attr, string)) {
if logger.handleFunc == nil {
logger.setChan <- 1
}
logger.handleFunc = funcs
}
func (logger *StarLogger) GetHandleFunc() func([]Attr, string) {
return logger.handleFunc
}
func (logger *StarLogger) Flush() error {
logger.mu.Lock()
defer logger.mu.Unlock()
logger.write(logger.logbuf)
logger.logbuf = ""
return nil
}
4 years ago
func (logger *StarLogger) Close() error {
logger.stopChan <- 1
logmaps.Range(func(k, v interface{}) bool {
if v.(*StarLogger) == logger {
logmaps.Delete(k)
return false
}
return true
})
logger = nil
return nil
}
func (logger *StarLogger) runTransfer() {
if logger.handleFunc == nil {
select {
case <-logger.stopChan:
return
case <-logger.setChan:
}
}
for {
select {
case <-logger.stopChan:
return
default:
}
if logger.handleFunc == nil {
time.Sleep(time.Millisecond * 100)
continue
}
poped := logger.stacks.MustPop()
if poped == nil {
time.Sleep(time.Millisecond * 20)
continue
}
val := poped.(logTran)
logger.handleFunc(val.color, val.log)
}
}
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)})
4 years ago
logger2.stopChan, logger2.setChan = make(chan int), make(chan int)
logger2.handleFunc = logger.handleFunc
go logger2.runTransfer()
if logger2.Flag == "MAN" {
logger2.Flag = "RYZ"
}
4 years ago
logmaps.Store(fmt.Sprint(time.Now().UnixNano()), logger2)
return logger2
}
4 years ago
func (logger *StarLogger) write(logstr string) {
if (!logger.DoWrite) || (logger.out == nil) {
return
}
i := 0
for logger.switching {
5 years ago
time.Sleep(time.Millisecond * 100)
4 years ago
i++
if i > 20 {
return
}
5 years ago
}
4 years ago
if &(logger.out) == nil {
5 years ago
return
5 years ago
}
4 years ago
logger.out.Write([]byte(logstr))
}
func (logger *StarLogger) OutPut(logstr string) {
logger.out.Write([]byte(logstr))
5 years ago
}
5 years ago
4 years ago
func (logger *StarLogger) output(level int, logstr string) {
5 years ago
var logs string
var skip int = 2
4 years ago
logger.mu.Lock()
defer logger.mu.Unlock()
if level < logger.LogLevel {
5 years ago
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, ".")
5 years ago
fname = filepath.Base(fname)
4 years ago
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 + ">"
5 years ago
}
if logger.ShowThread {
logs += " |" + logger.Flag + "|"
}
if logger.ShowLevel {
logs += " " + `[` + levels[level] + `]`
}
logs += " " + logstr
4 years ago
if logger.DoShow {
logcolor := NewColor(Colors[level]...)
logcolor.Fprint(logger.outshow, logs)
5 years ago
}
4 years ago
if logger.handleFunc != nil {
//logger.handleFunc(Colors[level], logs)
logger.stacks.Push(logTran{Colors[level], logs})
5 years ago
}
4 years ago
if logger.DoWrite {
if logger.BufSize == 0 {
logger.write(logs)
} else {
logger.logbuf += logs
if len(logger.logbuf) >= logger.BufSize {
logger.write(logs)
}
}
5 years ago
}
5 years ago
}
4 years ago
func (logger *StarLogger) Debug(str ...interface{}) {
strs := fmt.Sprint(str...)
logger.output(LvDebug, strs)
5 years ago
}
5 years ago
4 years ago
func Debug(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Debug(str...)
5 years ago
}
5 years ago
4 years ago
func (logger *StarLogger) Debugf(format string, str ...interface{}) {
strs := fmt.Sprintf(format, str...)
logger.output(LvDebug, strs)
5 years ago
}
4 years ago
func Debugf(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Debugf(format, str...)
5 years ago
}
5 years ago
4 years ago
func (logger *StarLogger) Debugln(str ...interface{}) {
strs := fmt.Sprintln(str...)
logger.output(LvDebug, strs)
5 years ago
}
4 years ago
func Debugln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Debugln(str...)
5 years ago
}
4 years ago
func (logger *StarLogger) Info(str ...interface{}) {
5 years ago
strs := fmt.Sprint(str...)
4 years ago
logger.output(LvInfo, strs)
5 years ago
}
4 years ago
func Info(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Info(str...)
5 years ago
}
4 years ago
func (logger *StarLogger) Infof(format string, str ...interface{}) {
strs := fmt.Sprintf(format, str...)
logger.output(LvInfo, strs)
5 years ago
}
4 years ago
func Infof(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Infof(format, str...)
5 years ago
}
4 years ago
func (logger *StarLogger) Infoln(str ...interface{}) {
strs := fmt.Sprintln(str...)
logger.output(LvInfo, strs)
5 years ago
}
func Infoln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Infoln(str...)
5 years ago
}
4 years ago
func (logger *StarLogger) Notice(str ...interface{}) {
5 years ago
strs := fmt.Sprint(str...)
4 years ago
logger.output(LvNotice, strs)
5 years ago
}
4 years ago
func Notice(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Notice(str...)
}
func (logger *StarLogger) Noticef(format string, str ...interface{}) {
5 years ago
strs := fmt.Sprintf(format, str...)
4 years ago
logger.output(LvNotice, strs)
5 years ago
}
4 years ago
func Noticef(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Noticef(format, str...)
}
func (logger *StarLogger) Noticeln(str ...interface{}) {
5 years ago
strs := fmt.Sprintln(str...)
4 years ago
logger.output(LvNotice, strs)
5 years ago
}
4 years ago
func Noticeln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Noticeln(str...)
}
func (logger *StarLogger) Warning(str ...interface{}) {
5 years ago
strs := fmt.Sprint(str...)
4 years ago
logger.output(LvWarning, strs)
5 years ago
}
4 years ago
func Warning(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Warning(str...)
}
func (logger *StarLogger) Warningf(format string, str ...interface{}) {
5 years ago
strs := fmt.Sprintf(format, str...)
4 years ago
logger.output(LvWarning, strs)
5 years ago
}
4 years ago
func Warningf(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Warningf(format, str...)
}
func (logger *StarLogger) Warningln(str ...interface{}) {
5 years ago
strs := fmt.Sprintln(str...)
4 years ago
logger.output(LvWarning, strs)
5 years ago
}
4 years ago
func Warningln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Warningln(str...)
}
func (logger *StarLogger) Error(str ...interface{}) {
5 years ago
strs := fmt.Sprint(str...)
4 years ago
logger.output(LvError, strs)
5 years ago
}
4 years ago
func Error(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Error(str...)
}
func (logger *StarLogger) Errorf(format string, str ...interface{}) {
5 years ago
strs := fmt.Sprintf(format, str...)
4 years ago
logger.output(LvError, strs)
5 years ago
}
4 years ago
func Errorf(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Errorf(format, str...)
}
func (logger *StarLogger) Errorln(str ...interface{}) {
5 years ago
strs := fmt.Sprintln(str...)
4 years ago
logger.output(LvError, strs)
5 years ago
}
4 years ago
func Errorln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Errorln(str...)
}
func (logger *StarLogger) Critical(str ...interface{}) {
5 years ago
strs := fmt.Sprint(str...)
4 years ago
logger.output(LvCritical, strs)
5 years ago
}
4 years ago
func Critical(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Critical(str...)
}
func (logger *StarLogger) Criticalf(format string, str ...interface{}) {
5 years ago
strs := fmt.Sprintf(format, str...)
4 years ago
logger.output(LvCritical, strs)
5 years ago
}
4 years ago
func Criticalf(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Criticalf(format, str...)
}
func (logger *StarLogger) Criticalln(str ...interface{}) {
5 years ago
strs := fmt.Sprintln(str...)
4 years ago
logger.output(LvCritical, strs)
5 years ago
}
4 years ago
func Criticalln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Criticalln(str...)
}
func (logger *StarLogger) Fatal(str ...interface{}) {
5 years ago
strs := fmt.Sprint(str...)
4 years ago
logger.output(LvFatal, strs)
5 years ago
os.Exit(9)
}
4 years ago
func Fatal(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Fatal(str...)
}
func (logger *StarLogger) Fatalf(format string, str ...interface{}) {
5 years ago
strs := fmt.Sprintf(format, str...)
4 years ago
logger.output(LvFatal, strs)
5 years ago
os.Exit(9)
}
4 years ago
func Fatalf(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Fatalf(format, str...)
}
func (logger *StarLogger) Fatalln(str ...interface{}) {
5 years ago
strs := fmt.Sprintln(str...)
4 years ago
logger.output(LvFatal, strs)
5 years ago
os.Exit(9)
}
4 years ago
func Fatalln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Fatalln(str...)
}
func (logger *StarLogger) Panic(str ...interface{}) {
5 years ago
strs := fmt.Sprint(str...)
4 years ago
logger.output(LvPanic, strs)
5 years ago
panic(str)
}
4 years ago
func Panic(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Panic(str...)
}
func (logger *StarLogger) Panicf(format string, str ...interface{}) {
5 years ago
strs := fmt.Sprintf(format, str...)
4 years ago
logger.output(LvPanic, strs)
panic(fmt.Sprintf(format, str...))
}
func Panicf(format string, str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Panicf(format, str...)
}
func (logger *StarLogger) Panicln(str ...interface{}) {
strs := fmt.Sprintln(str...)
logger.output(LvPanic, strs)
panic(fmt.Sprintln(str...))
5 years ago
}
func Panicln(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
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{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
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{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Printf(format, str...)
}
func (logger *StarLogger) Println(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
5 years ago
strs := fmt.Sprintln(str...)
4 years ago
logger.OutPut(strs)
}
func Println(str ...interface{}) {
4 years ago
stdLock.Lock()
defer stdLock.Unlock()
Std.isStd = true
4 years ago
Std.Println(str...)
}
func StdPrint(c []Attr, str ...interface{}) {
Std.lock.Lock()
defer Std.lock.Unlock()
colorstr := NewColor(c...)
colorstr.Print(str...)
4 years ago
if Std.StdFuncColor && Std.handleFunc != nil {
go Std.handleFunc(c, fmt.Sprint(str...))
4 years ago
}
}
func StdPrintf(c []Attr, format string, str ...interface{}) {
Std.lock.Lock()
defer Std.lock.Unlock()
colorstr := NewColor(c...)
colorstr.Printf(format, str...)
4 years ago
if Std.StdFuncColor && Std.handleFunc != nil {
go Std.handleFunc(c, fmt.Sprintf(format, str...))
4 years ago
}
}
func StdPrintln(c []Attr, str ...interface{}) {
Std.lock.Lock()
defer Std.lock.Unlock()
colorstr := NewColor(c...)
colorstr.Println(str...)
4 years ago
if Std.StdFuncColor && Std.handleFunc != nil {
go Std.handleFunc(c, fmt.Sprintln(str...))
4 years ago
}
}
func (logger *StarLogger) SwitchOut(out io.Writer) {
logger.lock.Lock()
defer logger.lock.Unlock()
logger.switching = true
logger.out = out
logger.switching = false
5 years ago
}
4 years ago
func (logger *StarLogger) SetSwitching(out bool) {
logger.lock.Lock()
defer logger.lock.Unlock()
logger.switching = out
}
func SetSwitchingAll(out bool) {
logmaps.Range(func(k, v interface{}) bool {
v.(*StarLogger).SetSwitching(out)
return true
})
}
func SwitchOutAll(out io.Writer) {
logmaps.Range(func(k, v interface{}) bool {
v.(*StarLogger).SwitchOut(out)
return true
})
}
func SethandleFuncAll(fn func([]Attr, string)) {
logmaps.Range(func(k, v interface{}) bool {
v.(*StarLogger).handleFunc = fn
return true
})
}
5 years ago
func SetLogFile(path string) error {
var err error
StdFile, err = os.Create(path)
Std.out = StdFile
4 years ago
Std.switching = false
5 years ago
return err
}
func SwitchFile(path string) error {
4 years ago
Std.switching = true
5 years ago
return SetLogFile(path)
5 years ago
}