feat: refact default logger
This commit is contained in:
		
							
								
								
									
										11
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								go.mod
									
									
									
									
									
								
							@@ -1,3 +1,14 @@
 | 
			
		||||
module github.com/loveuer/nf
 | 
			
		||||
 | 
			
		||||
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 (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"github.com/google/uuid"
 | 
			
		||||
	"github.com/loveuer/nf/nft/log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime/debug"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -27,51 +29,44 @@ func NewRecover(enableStackTrace bool) HandlerFunc {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewLogger() HandlerFunc {
 | 
			
		||||
	l := log.New(os.Stdout, "[NF] ", 0)
 | 
			
		||||
 | 
			
		||||
	durationFormat := func(num int64) string {
 | 
			
		||||
		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)
 | 
			
		||||
func NewLogger(traceHeader ...string) HandlerFunc {
 | 
			
		||||
	Header := "X-Trace-ID"
 | 
			
		||||
	if len(traceHeader) > 0 && traceHeader[0] != "" {
 | 
			
		||||
		Header = traceHeader[0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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()
 | 
			
		||||
		duration := time.Since(now)
 | 
			
		||||
 | 
			
		||||
		var (
 | 
			
		||||
			duration = time.Now().Sub(start).Nanoseconds()
 | 
			
		||||
			status   = c.StatusCode
 | 
			
		||||
			path     = c.path
 | 
			
		||||
			method   = c.Request.Method
 | 
			
		||||
		)
 | 
			
		||||
		msg := fmt.Sprintf("NF | %s | %15s | %3d | %s | %6s | %s", shortTrace, ip, c.StatusCode, HumanDuration(duration.Nanoseconds()), c.Method(), c.Path())
 | 
			
		||||
 | 
			
		||||
		l.Printf("%s | %5s | %d | %s | %s",
 | 
			
		||||
			start.Format("06/01/02T15:04:05"),
 | 
			
		||||
			method,
 | 
			
		||||
			status,
 | 
			
		||||
			durationFormat(duration),
 | 
			
		||||
			path,
 | 
			
		||||
		)
 | 
			
		||||
		switch {
 | 
			
		||||
		case c.StatusCode >= 500:
 | 
			
		||||
			logFn = log.Error
 | 
			
		||||
		case c.StatusCode >= 400:
 | 
			
		||||
			logFn = log.Warn
 | 
			
		||||
		default:
 | 
			
		||||
			logFn = log.Info
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		logFn(msg)
 | 
			
		||||
 | 
			
		||||
		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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user