feat: refact default logger
This commit is contained in:
parent
16541e377c
commit
d4fe4e0112
11
go.mod
11
go.mod
@ -1,3 +1,14 @@
|
|||||||
module github.com/loveuer/nf
|
module github.com/loveuer/nf
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/fatih/color v1.17.0
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
golang.org/x/sys v0.18.0 // indirect
|
||||||
|
)
|
||||||
|
13
go.sum
13
go.sum
@ -0,0 +1,13 @@
|
|||||||
|
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||||
|
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
@ -2,9 +2,11 @@ package nf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"github.com/google/uuid"
|
||||||
|
"github.com/loveuer/nf/nft/log"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,51 +29,44 @@ func NewRecover(enableStackTrace bool) HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogger() HandlerFunc {
|
func NewLogger(traceHeader ...string) HandlerFunc {
|
||||||
l := log.New(os.Stdout, "[NF] ", 0)
|
Header := "X-Trace-ID"
|
||||||
|
if len(traceHeader) > 0 && traceHeader[0] != "" {
|
||||||
durationFormat := func(num int64) string {
|
Header = traceHeader[0]
|
||||||
var (
|
|
||||||
unit = "ns"
|
|
||||||
)
|
|
||||||
|
|
||||||
if num > 1000 {
|
|
||||||
num = num / 1000
|
|
||||||
unit = "µs"
|
|
||||||
}
|
|
||||||
|
|
||||||
if num > 1000 {
|
|
||||||
num = num / 1000
|
|
||||||
unit = "ms"
|
|
||||||
}
|
|
||||||
|
|
||||||
if num > 1000 {
|
|
||||||
num = num / 1000
|
|
||||||
unit = "s"
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%3d %2s", num, unit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(c *Ctx) error {
|
return func(c *Ctx) error {
|
||||||
start := time.Now()
|
var (
|
||||||
|
now = time.Now()
|
||||||
|
trace = c.Get(Header)
|
||||||
|
logFn func(msg string, data ...any)
|
||||||
|
ip = c.IP()
|
||||||
|
)
|
||||||
|
|
||||||
|
if trace == "" {
|
||||||
|
trace = uuid.Must(uuid.NewV7()).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
c.SetHeader(Header, trace)
|
||||||
|
|
||||||
|
traces := strings.Split(trace, "-")
|
||||||
|
shortTrace := traces[len(traces)-1]
|
||||||
|
|
||||||
err := c.Next()
|
err := c.Next()
|
||||||
|
duration := time.Since(now)
|
||||||
|
|
||||||
var (
|
msg := fmt.Sprintf("NF | %s | %15s | %3d | %s | %6s | %s", shortTrace, ip, c.StatusCode, HumanDuration(duration.Nanoseconds()), c.Method(), c.Path())
|
||||||
duration = time.Now().Sub(start).Nanoseconds()
|
|
||||||
status = c.StatusCode
|
|
||||||
path = c.path
|
|
||||||
method = c.Request.Method
|
|
||||||
)
|
|
||||||
|
|
||||||
l.Printf("%s | %5s | %d | %s | %s",
|
switch {
|
||||||
start.Format("06/01/02T15:04:05"),
|
case c.StatusCode >= 500:
|
||||||
method,
|
logFn = log.Error
|
||||||
status,
|
case c.StatusCode >= 400:
|
||||||
durationFormat(duration),
|
logFn = log.Warn
|
||||||
path,
|
default:
|
||||||
)
|
logFn = log.Info
|
||||||
|
}
|
||||||
|
|
||||||
|
logFn(msg)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
67
nft/log/default.go
Normal file
67
nft/log/default.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nilLogger = func(prefix, timestamp, msg string, data ...any) {}
|
||||||
|
normalLogger = func(prefix, timestamp, msg string, data ...any) {
|
||||||
|
fmt.Printf(prefix+"| "+timestamp+" | "+msg+"\n", data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
panicLogger = func(prefix, timestamp, msg string, data ...any) {
|
||||||
|
panic(fmt.Sprintf(prefix+"| "+timestamp+" | "+msg+"\n", data...))
|
||||||
|
}
|
||||||
|
|
||||||
|
fatalLogger = func(prefix, timestamp, msg string, data ...any) {
|
||||||
|
fmt.Printf(prefix+"| "+timestamp+" | "+msg+"\n", data...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultLogger = &logger{
|
||||||
|
Mutex: sync.Mutex{},
|
||||||
|
timeFormat: "2006-01-02T15:04:05",
|
||||||
|
writer: os.Stdout,
|
||||||
|
level: LogLevelInfo,
|
||||||
|
debug: nilLogger,
|
||||||
|
info: normalLogger,
|
||||||
|
warn: normalLogger,
|
||||||
|
error: normalLogger,
|
||||||
|
panic: panicLogger,
|
||||||
|
fatal: fatalLogger,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetTimeFormat(format string) {
|
||||||
|
defaultLogger.SetTimeFormat(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetLogLevel(level LogLevel) {
|
||||||
|
defaultLogger.SetLogLevel(level)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Debug(msg string, data ...any) {
|
||||||
|
defaultLogger.Debug(msg, data...)
|
||||||
|
}
|
||||||
|
func Info(msg string, data ...any) {
|
||||||
|
defaultLogger.Info(msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Warn(msg string, data ...any) {
|
||||||
|
defaultLogger.Warn(msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Error(msg string, data ...any) {
|
||||||
|
defaultLogger.Error(msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Panic(msg string, data ...any) {
|
||||||
|
defaultLogger.Panic(msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fatal(msg string, data ...any) {
|
||||||
|
defaultLogger.Fatal(msg, data...)
|
||||||
|
}
|
115
nft/log/log.go
Normal file
115
nft/log/log.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LogLevel uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
LogLevelDebug = iota
|
||||||
|
LogLevelInfo
|
||||||
|
LogLevelWarn
|
||||||
|
LogLevelError
|
||||||
|
LogLevelPanic
|
||||||
|
LogLevelFatal
|
||||||
|
)
|
||||||
|
|
||||||
|
type logger struct {
|
||||||
|
sync.Mutex
|
||||||
|
timeFormat string
|
||||||
|
writer io.Writer
|
||||||
|
level LogLevel
|
||||||
|
debug func(prefix, timestamp, msg string, data ...any)
|
||||||
|
info func(prefix, timestamp, msg string, data ...any)
|
||||||
|
warn func(prefix, timestamp, msg string, data ...any)
|
||||||
|
error func(prefix, timestamp, msg string, data ...any)
|
||||||
|
panic func(prefix, timestamp, msg string, data ...any)
|
||||||
|
fatal func(prefix, timestamp, msg string, data ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
red = color.New(color.FgRed)
|
||||||
|
hired = color.New(color.FgHiRed)
|
||||||
|
green = color.New(color.FgGreen)
|
||||||
|
yellow = color.New(color.FgYellow)
|
||||||
|
white = color.New(color.FgWhite)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *logger) SetTimeFormat(format string) {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
l.timeFormat = format
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) SetLogLevel(level LogLevel) {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
if level > LogLevelDebug {
|
||||||
|
l.debug = nilLogger
|
||||||
|
} else {
|
||||||
|
l.debug = normalLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
if level > LogLevelInfo {
|
||||||
|
l.info = nilLogger
|
||||||
|
} else {
|
||||||
|
l.info = normalLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
if level > LogLevelWarn {
|
||||||
|
l.warn = nilLogger
|
||||||
|
} else {
|
||||||
|
l.warn = normalLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
if level > LogLevelError {
|
||||||
|
l.error = nilLogger
|
||||||
|
} else {
|
||||||
|
l.error = normalLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
if level > LogLevelPanic {
|
||||||
|
l.panic = nilLogger
|
||||||
|
} else {
|
||||||
|
l.panic = panicLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
if level > LogLevelFatal {
|
||||||
|
l.fatal = nilLogger
|
||||||
|
} else {
|
||||||
|
l.fatal = fatalLogger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) Debug(msg string, data ...any) {
|
||||||
|
l.debug(white.Sprint("Debug "), time.Now().Format(l.timeFormat), msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) Info(msg string, data ...any) {
|
||||||
|
l.info(green.Sprint("Info "), time.Now().Format(l.timeFormat), msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) Warn(msg string, data ...any) {
|
||||||
|
l.warn(yellow.Sprint("Warn "), time.Now().Format(l.timeFormat), msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) Error(msg string, data ...any) {
|
||||||
|
l.error(red.Sprint("Error "), time.Now().Format(l.timeFormat), msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) Panic(msg string, data ...any) {
|
||||||
|
l.panic(hired.Sprint("Panic "), time.Now().Format(l.timeFormat), msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) Fatal(msg string, data ...any) {
|
||||||
|
l.fatal(hired.Sprint("Fatal "), time.Now().Format(l.timeFormat), msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type WroteLogger interface {
|
||||||
|
Info(msg string, data ...any)
|
||||||
|
}
|
21
nft/log/new.go
Normal file
21
nft/log/new.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() *logger {
|
||||||
|
return &logger{
|
||||||
|
Mutex: sync.Mutex{},
|
||||||
|
timeFormat: "2006-01-02T15:04:05",
|
||||||
|
writer: os.Stdout,
|
||||||
|
level: LogLevelInfo,
|
||||||
|
debug: nilLogger,
|
||||||
|
info: normalLogger,
|
||||||
|
warn: normalLogger,
|
||||||
|
error: normalLogger,
|
||||||
|
panic: panicLogger,
|
||||||
|
fatal: fatalLogger,
|
||||||
|
}
|
||||||
|
}
|
21
util.go
21
util.go
@ -202,3 +202,24 @@ func bufApp(buf *[]byte, s string, w int, c byte) {
|
|||||||
}
|
}
|
||||||
b[w] = c
|
b[w] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HumanDuration(nano int64) string {
|
||||||
|
duration := float64(nano)
|
||||||
|
unit := "ns"
|
||||||
|
if duration >= 1000 {
|
||||||
|
duration /= 1000
|
||||||
|
unit = "us"
|
||||||
|
}
|
||||||
|
|
||||||
|
if duration >= 1000 {
|
||||||
|
duration /= 1000
|
||||||
|
unit = "ms"
|
||||||
|
}
|
||||||
|
|
||||||
|
if duration >= 1000 {
|
||||||
|
duration /= 1000
|
||||||
|
unit = " s"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%6.2f%s", duration, unit)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user