forked from goffee/core
Added Level type - A custom int type with constants DEBUG, INFO, WARNING, ERROR in increasing severity order.
Added `minLevel` field to Logger struct to track the minimum level threshold. Added `SetLevel()` and `GetLevel()` methods for dynamically changing/reading the log level at runtime.
This commit is contained in:
parent
5e389115fc
commit
0da7ea8ab1
3 changed files with 331 additions and 24 deletions
7
core.go
7
core.go
|
|
@ -293,7 +293,6 @@ func (app *App) makeHTTPRouterHandlerFunc(h Controller, ms []Hook) httprouter.Ha
|
||||||
for _, header := range ctx.Response.headers {
|
for _, header := range ctx.Response.headers {
|
||||||
w.Header().Add(header.key, header.val)
|
w.Header().Add(header.key, header.val)
|
||||||
}
|
}
|
||||||
logger.CloseLogsFile()
|
|
||||||
var ct string
|
var ct string
|
||||||
if ctx.Response.overrideContentType != "" {
|
if ctx.Response.overrideContentType != "" {
|
||||||
ct = ctx.Response.overrideContentType
|
ct = ctx.Response.overrideContentType
|
||||||
|
|
@ -334,7 +333,7 @@ func (n notFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
res := "{\"message\": \"Not Found\"}"
|
res := "{\"message\": \"Not Found\"}"
|
||||||
loggr.Error("Not Found")
|
loggr.Error("Not Found")
|
||||||
loggr.Error(debug.Stack())
|
//loggr.Error(debug.Stack())
|
||||||
w.Header().Add(CONTENT_TYPE, CONTENT_TYPE_JSON)
|
w.Header().Add(CONTENT_TYPE, CONTENT_TYPE_JSON)
|
||||||
w.Write([]byte(res))
|
w.Write([]byte(res))
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +343,7 @@ func (n methodNotAllowed) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
res := "{\"message\": \"Method not allowed\"}"
|
res := "{\"message\": \"Method not allowed\"}"
|
||||||
loggr.Error("Method not allowed")
|
loggr.Error("Method not allowed")
|
||||||
loggr.Error(debug.Stack())
|
//loggr.Error(debug.Stack())
|
||||||
w.Header().Add(CONTENT_TYPE, CONTENT_TYPE_JSON)
|
w.Header().Add(CONTENT_TYPE, CONTENT_TYPE_JSON)
|
||||||
w.Write([]byte(res))
|
w.Write([]byte(res))
|
||||||
}
|
}
|
||||||
|
|
@ -372,7 +371,7 @@ var panicHandler = func(w http.ResponseWriter, r *http.Request, e interface{}) {
|
||||||
shrtMsg := fmt.Sprintf("%v", e)
|
shrtMsg := fmt.Sprintf("%v", e)
|
||||||
loggr.Error(shrtMsg)
|
loggr.Error(shrtMsg)
|
||||||
fmt.Println(shrtMsg)
|
fmt.Println(shrtMsg)
|
||||||
loggr.Error(string(debug.Stack()))
|
//loggr.Error(string(debug.Stack()))
|
||||||
var res string
|
var res string
|
||||||
if env.GetVarOtherwiseDefault("APP_ENV", "local") == PRODUCTION {
|
if env.GetVarOtherwiseDefault("APP_ENV", "local") == PRODUCTION {
|
||||||
res = "{\"message\": \"internal error\"}"
|
res = "{\"message\": \"internal error\"}"
|
||||||
|
|
|
||||||
151
logger/logger.go
151
logger/logger.go
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2021 Harran Ali <harran.m@gmail.com>. All rights reserved.
|
// Copyright (c) 2026 Zeni Kim <zenik@smarteching.com>
|
||||||
// Use of this source code is governed by MIT-style
|
// Use of this source code is governed by MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -8,16 +8,68 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// logs file
|
// logs file
|
||||||
var logsFile *os.File
|
var logsFile *os.File
|
||||||
|
|
||||||
|
// ANSI color codes for terminal output
|
||||||
|
const (
|
||||||
|
colorReset = "\033[0m"
|
||||||
|
colorRed = "\033[31m"
|
||||||
|
colorYellow = "\033[33m"
|
||||||
|
colorBlue = "\033[34m"
|
||||||
|
colorCyan = "\033[36m"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Level represents a log severity level.
|
||||||
|
type Level int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEBUG Level = iota
|
||||||
|
INFO
|
||||||
|
WARNING
|
||||||
|
ERROR
|
||||||
|
)
|
||||||
|
|
||||||
|
// String returns the string representation of a log level.
|
||||||
|
func (l Level) String() string {
|
||||||
|
switch l {
|
||||||
|
case DEBUG:
|
||||||
|
return "debug"
|
||||||
|
case INFO:
|
||||||
|
return "info"
|
||||||
|
case WARNING:
|
||||||
|
return "warning"
|
||||||
|
case ERROR:
|
||||||
|
return "error"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// coloredWriter wraps an io.Writer and replaces plain log prefixes with ANSI-colored ones
|
||||||
|
// in the output stream. The original bytes pass through unmodified to any additional writers.
|
||||||
|
type coloredWriter struct {
|
||||||
|
writer io.Writer
|
||||||
|
plain string
|
||||||
|
colored string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *coloredWriter) Write(p []byte) (n int, err error) {
|
||||||
|
// Replace the plain prefix with the colored version in the output
|
||||||
|
colored := strings.Replace(string(p), w.plain, w.colored, 1)
|
||||||
|
return w.writer.Write([]byte(colored))
|
||||||
|
}
|
||||||
|
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
|
minLevel Level
|
||||||
infoLogger *log.Logger
|
infoLogger *log.Logger
|
||||||
warningLogger *log.Logger
|
warningLogger *log.Logger
|
||||||
errorLogger *log.Logger
|
errorLogger *log.Logger
|
||||||
debugLogger *log.Logger
|
debugLogger *log.Logger
|
||||||
|
file *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
var l *Logger
|
var l *Logger
|
||||||
|
|
@ -40,9 +92,36 @@ func (f LogFileDriver) GetTarget() interface{} {
|
||||||
return f.FilePath
|
return f.FilePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// levelPrefixes returns the plain and colored (with ANSI escapes) prefix strings for a given level.
|
||||||
|
func levelPrefixes(level Level) (plain, colored string) {
|
||||||
|
switch level {
|
||||||
|
case INFO:
|
||||||
|
return "info: ", colorBlue + "INFO" + colorReset + ": "
|
||||||
|
case DEBUG:
|
||||||
|
return "debug: ", colorCyan + "DEBUG" + colorReset + ": "
|
||||||
|
case WARNING:
|
||||||
|
return "warning: ", colorYellow + "WARNING" + colorReset + ": "
|
||||||
|
case ERROR:
|
||||||
|
return "error: ", colorRed + "ERROR" + colorReset + ": "
|
||||||
|
default:
|
||||||
|
return "info: ", "INFO: "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLogger creates a new Logger with the given driver and a minimum level of DEBUG (all levels logged).
|
||||||
func NewLogger(driver LogsDriver) *Logger {
|
func NewLogger(driver LogsDriver) *Logger {
|
||||||
|
stdoutEnabled := os.Getenv("LOG_STDOUT_ENABLE") == "true"
|
||||||
|
return NewLoggerWithStdout(driver, DEBUG, stdoutEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLoggerWithStdout creates a new Logger with the given driver, minimum log level,
|
||||||
|
// and optionally writes to stdout in addition to the target file.
|
||||||
|
// When stdoutEnabled is true, log messages are written to both the target and stdout.
|
||||||
|
// ANSI color codes are applied to log prefixes in terminal output only.
|
||||||
|
func NewLoggerWithStdout(driver LogsDriver, minLevel Level, stdoutEnabled bool) *Logger {
|
||||||
if driver.GetTarget() == nil {
|
if driver.GetTarget() == nil {
|
||||||
l = &Logger{
|
l = &Logger{
|
||||||
|
minLevel: minLevel,
|
||||||
infoLogger: log.New(io.Discard, "info: ", log.LstdFlags),
|
infoLogger: log.New(io.Discard, "info: ", log.LstdFlags),
|
||||||
warningLogger: log.New(io.Discard, "warning: ", log.LstdFlags),
|
warningLogger: log.New(io.Discard, "warning: ", log.LstdFlags),
|
||||||
errorLogger: log.New(io.Discard, "error: ", log.LstdFlags),
|
errorLogger: log.New(io.Discard, "error: ", log.LstdFlags),
|
||||||
|
|
@ -54,41 +133,103 @@ func NewLogger(driver LogsDriver) *Logger {
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("something wrong with the file path")
|
panic("something wrong with the file path")
|
||||||
}
|
}
|
||||||
logsFile, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
|
var err error
|
||||||
|
logsFile, err = os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if stdoutEnabled {
|
||||||
|
// Build each logger with a MultiWriter: the file gets the original plain output,
|
||||||
|
// stdout gets the output with ANSI-colored prefixes.
|
||||||
|
infoPlain, infoColored := levelPrefixes(INFO)
|
||||||
|
debugPlain, debugColored := levelPrefixes(DEBUG)
|
||||||
|
warnPlain, warnColored := levelPrefixes(WARNING)
|
||||||
|
errPlain, errColored := levelPrefixes(ERROR)
|
||||||
|
|
||||||
l = &Logger{
|
l = &Logger{
|
||||||
|
minLevel: minLevel,
|
||||||
|
infoLogger: log.New(
|
||||||
|
io.MultiWriter(logsFile, &coloredWriter{writer: os.Stdout, plain: infoPlain, colored: infoColored}),
|
||||||
|
infoPlain, log.LstdFlags,
|
||||||
|
),
|
||||||
|
warningLogger: log.New(
|
||||||
|
io.MultiWriter(logsFile, &coloredWriter{writer: os.Stdout, plain: warnPlain, colored: warnColored}),
|
||||||
|
warnPlain, log.LstdFlags,
|
||||||
|
),
|
||||||
|
errorLogger: log.New(
|
||||||
|
io.MultiWriter(logsFile, &coloredWriter{writer: os.Stdout, plain: errPlain, colored: errColored}),
|
||||||
|
errPlain, log.LstdFlags,
|
||||||
|
),
|
||||||
|
debugLogger: log.New(
|
||||||
|
io.MultiWriter(logsFile, &coloredWriter{writer: os.Stdout, plain: debugPlain, colored: debugColored}),
|
||||||
|
debugPlain, log.LstdFlags,
|
||||||
|
),
|
||||||
|
file: logsFile,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No stdout: all output goes to file with plain prefixes
|
||||||
|
l = &Logger{
|
||||||
|
minLevel: minLevel,
|
||||||
infoLogger: log.New(logsFile, "info: ", log.LstdFlags),
|
infoLogger: log.New(logsFile, "info: ", log.LstdFlags),
|
||||||
warningLogger: log.New(logsFile, "warning: ", log.LstdFlags),
|
warningLogger: log.New(logsFile, "warning: ", log.LstdFlags),
|
||||||
errorLogger: log.New(logsFile, "error: ", log.LstdFlags),
|
errorLogger: log.New(logsFile, "error: ", log.LstdFlags),
|
||||||
debugLogger: log.New(logsFile, "debug: ", log.LstdFlags),
|
debugLogger: log.New(logsFile, "debug: ", log.LstdFlags),
|
||||||
|
file: logsFile,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLoggerWithLevel creates a new Logger with the given driver and minimum log level.
|
||||||
|
// Messages below the minimum level will be discarded. Stdout output is disabled by default.
|
||||||
|
func NewLoggerWithLevel(driver LogsDriver, minLevel Level) *Logger {
|
||||||
|
stdoutEnabled := os.Getenv("LOG_STDOUT_ENABLE") == "true"
|
||||||
|
return NewLoggerWithStdout(driver, minLevel, stdoutEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLevel sets the minimum log level for the logger.
|
||||||
|
// Messages below this level will be discarded.
|
||||||
|
func (l *Logger) SetLevel(level Level) {
|
||||||
|
l.minLevel = level
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLevel returns the current minimum log level.
|
||||||
|
func (l *Logger) GetLevel() Level {
|
||||||
|
return l.minLevel
|
||||||
|
}
|
||||||
|
|
||||||
func ResolveLogger() *Logger {
|
func ResolveLogger() *Logger {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) Info(msg interface{}) {
|
func (l *Logger) Info(msg interface{}) {
|
||||||
|
if l.minLevel <= INFO {
|
||||||
l.infoLogger.Println(msg)
|
l.infoLogger.Println(msg)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Logger) Debug(msg interface{}) {
|
func (l *Logger) Debug(msg interface{}) {
|
||||||
|
if l.minLevel <= DEBUG {
|
||||||
l.debugLogger.Println(msg)
|
l.debugLogger.Println(msg)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Logger) Warning(msg interface{}) {
|
func (l *Logger) Warning(msg interface{}) {
|
||||||
|
if l.minLevel <= WARNING {
|
||||||
l.warningLogger.Println(msg)
|
l.warningLogger.Println(msg)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Logger) Error(msg interface{}) {
|
func (l *Logger) Error(msg interface{}) {
|
||||||
|
if l.minLevel <= ERROR {
|
||||||
l.errorLogger.Println(msg)
|
l.errorLogger.Println(msg)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func CloseLogsFile() {
|
func (l *Logger) Close() error {
|
||||||
if logsFile != nil {
|
if l.file != nil {
|
||||||
defer logsFile.Close()
|
return l.file.Close()
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ func TestInfo(t *testing.T) {
|
||||||
t.Error("error testing info")
|
t.Error("error testing info")
|
||||||
}
|
}
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
CloseLogsFile()
|
l.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ func TestWarning(t *testing.T) {
|
||||||
t.Error("failed testing warning")
|
t.Error("failed testing warning")
|
||||||
}
|
}
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
CloseLogsFile()
|
l.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ func TestDebug(t *testing.T) {
|
||||||
t.Error("error testing debug")
|
t.Error("error testing debug")
|
||||||
}
|
}
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
CloseLogsFile()
|
l.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,6 +128,173 @@ func TestError(t *testing.T) {
|
||||||
t.Error("failed testing error")
|
t.Error("failed testing error")
|
||||||
}
|
}
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
CloseLogsFile()
|
l.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLevelFiltering(t *testing.T) {
|
||||||
|
t.Run("NewLoggerWithLevel_DEBUG", func(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), uuid.NewString())
|
||||||
|
l := NewLoggerWithLevel(&LogFileDriver{FilePath: path}, DEBUG)
|
||||||
|
l.Debug("debug-msg")
|
||||||
|
l.Info("info-msg")
|
||||||
|
l.Warning("warn-msg")
|
||||||
|
l.Error("err-msg")
|
||||||
|
l.Close()
|
||||||
|
|
||||||
|
b, _ := os.ReadFile(path)
|
||||||
|
content := string(b)
|
||||||
|
if !strings.Contains(content, "debug-msg") {
|
||||||
|
t.Error("expected debug-msg to be logged at DEBUG level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "info-msg") {
|
||||||
|
t.Error("expected info-msg to be logged at DEBUG level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "warn-msg") {
|
||||||
|
t.Error("expected warn-msg to be logged at DEBUG level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "err-msg") {
|
||||||
|
t.Error("expected err-msg to be logged at DEBUG level")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NewLoggerWithLevel_INFO", func(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), uuid.NewString())
|
||||||
|
l := NewLoggerWithLevel(&LogFileDriver{FilePath: path}, INFO)
|
||||||
|
l.Debug("debug-msg")
|
||||||
|
l.Info("info-msg")
|
||||||
|
l.Warning("warn-msg")
|
||||||
|
l.Error("err-msg")
|
||||||
|
l.Close()
|
||||||
|
|
||||||
|
b, _ := os.ReadFile(path)
|
||||||
|
content := string(b)
|
||||||
|
if strings.Contains(content, "debug-msg") {
|
||||||
|
t.Error("debug-msg should NOT be logged at INFO minimum level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "info-msg") {
|
||||||
|
t.Error("expected info-msg to be logged at INFO level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "warn-msg") {
|
||||||
|
t.Error("expected warn-msg to be logged at INFO level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "err-msg") {
|
||||||
|
t.Error("expected err-msg to be logged at INFO level")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NewLoggerWithLevel_WARNING", func(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), uuid.NewString())
|
||||||
|
l := NewLoggerWithLevel(&LogFileDriver{FilePath: path}, WARNING)
|
||||||
|
l.Debug("debug-msg")
|
||||||
|
l.Info("info-msg")
|
||||||
|
l.Warning("warn-msg")
|
||||||
|
l.Error("err-msg")
|
||||||
|
l.Close()
|
||||||
|
|
||||||
|
b, _ := os.ReadFile(path)
|
||||||
|
content := string(b)
|
||||||
|
if strings.Contains(content, "debug-msg") {
|
||||||
|
t.Error("debug-msg should NOT be logged at WARNING minimum level")
|
||||||
|
}
|
||||||
|
if strings.Contains(content, "info-msg") {
|
||||||
|
t.Error("info-msg should NOT be logged at WARNING minimum level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "warn-msg") {
|
||||||
|
t.Error("expected warn-msg to be logged at WARNING level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "err-msg") {
|
||||||
|
t.Error("expected err-msg to be logged at WARNING level")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NewLoggerWithLevel_ERROR", func(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), uuid.NewString())
|
||||||
|
l := NewLoggerWithLevel(&LogFileDriver{FilePath: path}, ERROR)
|
||||||
|
l.Debug("debug-msg")
|
||||||
|
l.Info("info-msg")
|
||||||
|
l.Warning("warn-msg")
|
||||||
|
l.Error("err-msg")
|
||||||
|
l.Close()
|
||||||
|
|
||||||
|
b, _ := os.ReadFile(path)
|
||||||
|
content := string(b)
|
||||||
|
if strings.Contains(content, "debug-msg") {
|
||||||
|
t.Error("debug-msg should NOT be logged at ERROR minimum level")
|
||||||
|
}
|
||||||
|
if strings.Contains(content, "info-msg") {
|
||||||
|
t.Error("info-msg should NOT be logged at ERROR minimum level")
|
||||||
|
}
|
||||||
|
if strings.Contains(content, "warn-msg") {
|
||||||
|
t.Error("warn-msg should NOT be logged at ERROR minimum level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "err-msg") {
|
||||||
|
t.Error("expected err-msg to be logged at ERROR level")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("SetLevel_dynamically", func(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), uuid.NewString())
|
||||||
|
l := NewLogger(&LogFileDriver{FilePath: path})
|
||||||
|
|
||||||
|
// Default is DEBUG, so debug messages are logged
|
||||||
|
l.Debug("debug-msg-before")
|
||||||
|
l.SetLevel(WARNING)
|
||||||
|
l.Debug("debug-msg-after")
|
||||||
|
l.Info("info-msg-after")
|
||||||
|
l.Warning("warn-msg-after")
|
||||||
|
l.Error("err-msg-after")
|
||||||
|
l.Close()
|
||||||
|
|
||||||
|
b, _ := os.ReadFile(path)
|
||||||
|
content := string(b)
|
||||||
|
if !strings.Contains(content, "debug-msg-before") {
|
||||||
|
t.Error("expected debug-msg-before to be logged before level change")
|
||||||
|
}
|
||||||
|
if strings.Contains(content, "debug-msg-after") {
|
||||||
|
t.Error("debug-msg-after should NOT be logged after setting level to WARNING")
|
||||||
|
}
|
||||||
|
if strings.Contains(content, "info-msg-after") {
|
||||||
|
t.Error("info-msg-after should NOT be logged after setting level to WARNING")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "warn-msg-after") {
|
||||||
|
t.Error("expected warn-msg-after to be logged at WARNING level")
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "err-msg-after") {
|
||||||
|
t.Error("expected err-msg-after to be logged at WARNING level")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLevelString(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
level Level
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{DEBUG, "debug"},
|
||||||
|
{INFO, "info"},
|
||||||
|
{WARNING, "warning"},
|
||||||
|
{ERROR, "error"},
|
||||||
|
{Level(99), "unknown"},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
if got := tt.level.String(); got != tt.want {
|
||||||
|
t.Errorf("Level(%d).String() = %q, want %q", tt.level, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetLevel(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), uuid.NewString())
|
||||||
|
l := NewLoggerWithLevel(&LogFileDriver{FilePath: path}, WARNING)
|
||||||
|
defer l.Close()
|
||||||
|
|
||||||
|
if l.GetLevel() != WARNING {
|
||||||
|
t.Errorf("GetLevel() = %d, want %d", l.GetLevel(), WARNING)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.SetLevel(INFO)
|
||||||
|
if l.GetLevel() != INFO {
|
||||||
|
t.Errorf("GetLevel() after SetLevel(INFO) = %d, want %d", l.GetLevel(), INFO)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue