Complete rewrite of the library.

This commit is contained in:
2023-12-12 21:30:26 +00:00
parent 3217edf37f
commit 4fc826c1f6
27 changed files with 1153 additions and 1372 deletions
+134
View File
@@ -0,0 +1,134 @@
package libpack_logging
import (
"os"
"strings"
"sync"
"time"
"github.com/gookit/goutil/envutil"
"github.com/rs/zerolog"
)
type LogConfig struct {
baseLogger zerolog.Logger
errorLogger zerolog.Logger
nopLogger zerolog.Logger
mu sync.Mutex
minLevel zerolog.Level
}
func init() {
zerolog.TimeFieldFormat = time.RFC3339
zerolog.MessageFieldName = "msg"
zerolog.TimestampFieldName = "ts"
zerolog.LevelFieldName = "level"
zerolog.LevelFatalValue = "critical"
}
func getMinLogLevel() zerolog.Level {
levelStr := strings.ToLower(envutil.Getenv("LOG_LEVEL", "info"))
return matchLogLevel(levelStr)
}
// Add function set the minimum log level instead of using environment variable
func (lc *LogConfig) SetLogLevel(level string) {
lc.mu.Lock()
defer lc.mu.Unlock()
lc.minLevel = matchLogLevel(level)
}
// Match the log level provided as string with the log level provided as zerolog.Level
func matchLogLevel(level string) zerolog.Level {
switch level {
case "debug":
return zerolog.DebugLevel
case "warn":
return zerolog.WarnLevel
case "error":
return zerolog.ErrorLevel
case "critical":
return zerolog.FatalLevel
default:
return zerolog.InfoLevel
}
}
func NewLogger() *LogConfig {
zl := zerolog.New(os.Stdout).With().Timestamp().Logger()
// Determine the minimum log level from environment variable
return &LogConfig{
baseLogger: zl,
errorLogger: zl.Output(os.Stderr),
nopLogger: zerolog.Nop(),
minLevel: getMinLogLevel(),
}
}
func (lc *LogConfig) getLogger(level zerolog.Level) zerolog.Logger {
if level >= zerolog.ErrorLevel {
return lc.errorLogger
}
if level < lc.minLevel {
return lc.nopLogger
}
return lc.baseLogger
}
func (lc *LogConfig) Log(level zerolog.Level, message string, fields []map[string]interface{}) {
if level < lc.minLevel {
return
}
logger := lc.getLogger(level)
event := logger.WithLevel(level).CallerSkipFrame(3)
if len(fields) == 0 {
event.Msg(message)
return
}
field := fields[0]
for k, val := range field {
switch v := val.(type) {
case string:
event.Str(k, v)
case int:
event.Int(k, v)
case float64:
event.Float64(k, v)
default:
event.Interface(k, v)
}
}
event.Msg(message)
}
func (lc *LogConfig) Info(message string, fields ...map[string]interface{}) {
lc.Log(zerolog.InfoLevel, message, fields)
}
func (lc *LogConfig) Debug(message string, fields ...map[string]interface{}) {
lc.Log(zerolog.DebugLevel, message, fields)
}
func (lc *LogConfig) Warn(message string, fields ...map[string]interface{}) {
lc.Log(zerolog.WarnLevel, message, fields)
}
// alias Warning to Warn
func (lc *LogConfig) Warning(message string, fields ...map[string]interface{}) {
lc.Warn(message, fields...)
}
func (lc *LogConfig) Error(message string, fields ...map[string]interface{}) {
lc.Log(zerolog.ErrorLevel, message, fields)
}
func (lc *LogConfig) Critical(message string, fields ...map[string]interface{}) {
lc.Log(zerolog.FatalLevel, message, fields)
os.Exit(1)
}
// alias Fatal to Critical
func (lc *LogConfig) Fatal(message string, fields ...map[string]interface{}) {
lc.Critical(message, fields...)
}
+32
View File
@@ -0,0 +1,32 @@
package libpack_logging
import (
"os"
"testing"
)
func BenchmarkNewLogger(b *testing.B) {
for i := 0; i < b.N; i++ {
NewLogger()
}
}
func BenchmarkInfoLog(b *testing.B) {
oldEnv := os.Getenv("LOG_LEVEL")
os.Setenv("LOG_LEVEL", "info")
oldStdout := os.Stdout
oldStderr := os.Stderr
os.Stdout, _ = os.Open(os.DevNull)
os.Stderr, _ = os.Open(os.DevNull)
defer func() {
os.Stdout = oldStdout
os.Stderr = oldStderr
os.Setenv("LOG_LEVEL", oldEnv)
}()
testsLogger := NewLogger()
b.ResetTimer()
for i := 0; i < b.N; i++ {
testsLogger.Info("test", map[string]interface{}{"test": "test"})
}
}