(new): add threshold-based log level filtering and docs
Golang lint / lint (push) Successful in 1m36s
Golang lint / lint (push) Successful in 1m36s
- add threshold-aware LogLevel constructors - add Logger.SetThresholdMode and SameThreshold - preserve legacy SameLevel behavior for compatibility - extend tests for threshold mode and compatibility - update README and release notes for v2.2.0
This commit is contained in:
@@ -71,6 +71,10 @@ func main() {
|
|||||||
|
|
||||||
Important: with the current level ordering, `Level(sneklog.FATAL)` allows `INFO`, `WARN`, `ERROR`, and `FATAL`, but not `DEBUG`. Use `Level(sneklog.DEBUG)` to enable every level.
|
Important: with the current level ordering, `Level(sneklog.FATAL)` allows `INFO`, `WARN`, `ERROR`, and `FATAL`, but not `DEBUG`. Use `Level(sneklog.DEBUG)` to enable every level.
|
||||||
|
|
||||||
|
If you want classic threshold filtering instead, call `SetThresholdMode(true)` and
|
||||||
|
configure levels with `NewThresholdLogLevel(...)` or
|
||||||
|
`NewThresholdLogLevelWithColors(...)`.
|
||||||
|
|
||||||
## Writers and ownership
|
## Writers and ownership
|
||||||
|
|
||||||
`Logger.Close()` only closes writers created by the logger itself:
|
`Logger.Close()` only closes writers created by the logger itself:
|
||||||
@@ -142,6 +146,29 @@ access := sneklog.NewInfoLogLevelWithColors("access", sneklog.FgCyan, sneklog.Bg
|
|||||||
audit := sneklog.NewWarnLogLevel("audit")
|
audit := sneklog.NewWarnLogLevel("audit")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
These helpers keep the legacy severity index for backward compatibility and also
|
||||||
|
assign default threshold values:
|
||||||
|
|
||||||
|
- `INFO`: `th=10`
|
||||||
|
- `WARN`: `th=20`
|
||||||
|
- `ERROR`: `th=30`
|
||||||
|
- `FATAL`: `th=40`
|
||||||
|
- `DEBUG`: `th=0`
|
||||||
|
|
||||||
|
To define custom threshold-based levels explicitly:
|
||||||
|
|
||||||
|
```go
|
||||||
|
trace := sneklog.NewThresholdLogLevelWithColors(4, 5, "trace", sneklog.FgHiBlack, sneklog.BgNone)
|
||||||
|
audit := sneklog.NewThresholdLogLevel(1, 25, "audit")
|
||||||
|
|
||||||
|
logger := sneklog.NewLogger().
|
||||||
|
SetLevel(audit).
|
||||||
|
SetThresholdMode(true)
|
||||||
|
|
||||||
|
logger.Print(trace, "verbose trace") // filtered out
|
||||||
|
logger.Print(audit, "audit event") // allowed
|
||||||
|
```
|
||||||
|
|
||||||
HTTP method-specific predefined levels are available out of the box:
|
HTTP method-specific predefined levels are available out of the box:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -149,8 +176,11 @@ level := sneklog.LogLevelForMethod(http.MethodPost)
|
|||||||
logger.Print(level, "POST /users")
|
logger.Print(level, "POST /users")
|
||||||
```
|
```
|
||||||
|
|
||||||
When comparing levels, use `SameLevel` if only the severity matters and `Equal`
|
When comparing levels:
|
||||||
if the full configuration, including colors and attributes, must match.
|
|
||||||
|
- use `SameLevel` if only the legacy severity index matters;
|
||||||
|
- use `SameThreshold` if only threshold filtering matters;
|
||||||
|
- use `Equal` if the full configuration, including threshold, colors, and attributes, must match.
|
||||||
|
|
||||||
## Message replacement
|
## Message replacement
|
||||||
|
|
||||||
|
|||||||
+32
-3
@@ -71,6 +71,10 @@ func main() {
|
|||||||
|
|
||||||
Важно: в текущей модели уровней `Level(sneklog.FATAL)` пропускает `INFO`, `WARN`, `ERROR` и `FATAL`, но не `DEBUG`. Чтобы включить все сообщения, используйте `Level(sneklog.DEBUG)`.
|
Важно: в текущей модели уровней `Level(sneklog.FATAL)` пропускает `INFO`, `WARN`, `ERROR` и `FATAL`, но не `DEBUG`. Чтобы включить все сообщения, используйте `Level(sneklog.DEBUG)`.
|
||||||
|
|
||||||
|
Если нужна классическая threshold-фильтрация, включите `SetThresholdMode(true)` и
|
||||||
|
задавайте уровни через `NewThresholdLogLevel(...)` или
|
||||||
|
`NewThresholdLogLevelWithColors(...)`.
|
||||||
|
|
||||||
## Writer'ы и владение
|
## Writer'ы и владение
|
||||||
|
|
||||||
`Logger.Close()` закрывает только writer'ы, которые логгер создал сам:
|
`Logger.Close()` закрывает только writer'ы, которые логгер создал сам:
|
||||||
@@ -142,6 +146,29 @@ access := sneklog.NewInfoLogLevelWithColors("access", sneklog.FgCyan, sneklog.Bg
|
|||||||
audit := sneklog.NewWarnLogLevel("audit")
|
audit := sneklog.NewWarnLogLevel("audit")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Эти helper'ы сохраняют legacy severity index для обратной совместимости и
|
||||||
|
одновременно выставляют значения threshold по умолчанию:
|
||||||
|
|
||||||
|
- `INFO`: `th=10`
|
||||||
|
- `WARN`: `th=20`
|
||||||
|
- `ERROR`: `th=30`
|
||||||
|
- `FATAL`: `th=40`
|
||||||
|
- `DEBUG`: `th=0`
|
||||||
|
|
||||||
|
Чтобы явно создавать уровни для threshold-режима:
|
||||||
|
|
||||||
|
```go
|
||||||
|
trace := sneklog.NewThresholdLogLevelWithColors(4, 5, "trace", sneklog.FgHiBlack, sneklog.BgNone)
|
||||||
|
audit := sneklog.NewThresholdLogLevel(1, 25, "audit")
|
||||||
|
|
||||||
|
logger := sneklog.NewLogger().
|
||||||
|
SetLevel(audit).
|
||||||
|
SetThresholdMode(true)
|
||||||
|
|
||||||
|
logger.Print(trace, "verbose trace") // будет отфильтровано
|
||||||
|
logger.Print(audit, "audit event") // будет записано
|
||||||
|
```
|
||||||
|
|
||||||
Для HTTP-методов доступны готовые уровни:
|
Для HTTP-методов доступны готовые уровни:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -149,9 +176,11 @@ level := sneklog.LogLevelForMethod(http.MethodPost)
|
|||||||
logger.Print(level, "POST /users")
|
logger.Print(level, "POST /users")
|
||||||
```
|
```
|
||||||
|
|
||||||
Если нужно сравнить только severity, используйте `SameLevel`. Если нужно
|
При сравнении уровней:
|
||||||
полное совпадение конфигурации уровня, включая цвета и атрибуты, используйте
|
|
||||||
`Equal`.
|
- используйте `SameLevel`, если важен только legacy severity index;
|
||||||
|
- используйте `SameThreshold`, если важна только threshold-фильтрация;
|
||||||
|
- используйте `Equal`, если нужно полное совпадение конфигурации, включая threshold, цвета и атрибуты.
|
||||||
|
|
||||||
## Замена сообщений
|
## Замена сообщений
|
||||||
|
|
||||||
|
|||||||
+16
-5
@@ -1,6 +1,8 @@
|
|||||||
# Unreleased (planned v2.2.0)
|
# Unreleased (planned v2.2.0)
|
||||||
|
|
||||||
This release expands the public LogLevel API, adds HTTP method helpers, and improves package documentation and test coverage.
|
This release expands the public LogLevel API, adds optional threshold-based
|
||||||
|
filtering alongside the legacy severity ordering, and improves documentation
|
||||||
|
and test coverage.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
@@ -15,6 +17,9 @@ This release expands the public LogLevel API, adds HTTP method helpers, and impr
|
|||||||
- `NewFatalLogLevelWithColors`
|
- `NewFatalLogLevelWithColors`
|
||||||
- `NewDebugLogLevel`
|
- `NewDebugLogLevel`
|
||||||
- `NewDebugLogLevelWithColors`
|
- `NewDebugLogLevelWithColors`
|
||||||
|
- Added threshold-aware log level constructors:
|
||||||
|
- `NewThresholdLogLevel`
|
||||||
|
- `NewThresholdLogLevelWithColors`
|
||||||
- Added HTTP method-specific predefined log levels:
|
- Added HTTP method-specific predefined log levels:
|
||||||
- `HTTPGetLevel`
|
- `HTTPGetLevel`
|
||||||
- `HTTPHeadLevel`
|
- `HTTPHeadLevel`
|
||||||
@@ -28,24 +33,30 @@ This release expands the public LogLevel API, adds HTTP method helpers, and impr
|
|||||||
- `HTTPUnknownLevel`
|
- `HTTPUnknownLevel`
|
||||||
- Added `LogLevelForMethod(method string) LogLevel` to map HTTP methods to predefined log levels.
|
- Added `LogLevelForMethod(method string) LogLevel` to map HTTP methods to predefined log levels.
|
||||||
- Added `Logger.Printf(level, format, args...)` for formatted logging with an explicit log level.
|
- Added `Logger.Printf(level, format, args...)` for formatted logging with an explicit log level.
|
||||||
- Added `LogLevel.SameLevel` and `LogLevel.Equal` for severity-only and full level comparisons.
|
- Added `Logger.SetThresholdMode(bool)` to switch filtering from legacy severity-index ordering to threshold-based ordering.
|
||||||
|
- Added `LogLevel.SameLevel`, `LogLevel.SameThreshold`, and `LogLevel.Equal` for severity-only, threshold-only, and full level comparisons.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Refactored log level definitions into a dedicated `levels.go` file.
|
- Refactored log level definitions into a dedicated `levels.go` file.
|
||||||
- Unified `Logger.Print` and `Logger.Println` through a shared internal implementation without changing their behavior.
|
- Unified `Logger.Print` and `Logger.Println` through a shared internal implementation without changing their behavior.
|
||||||
- Expanded test coverage for `Logger.Printf`, HTTP level mapping, and new level constructors.
|
- Common helper constructors such as `NewInfoLogLevel` now also assign threshold values while preserving legacy severity indexes.
|
||||||
|
- `LogLevel.Equal` now includes threshold configuration in full equality checks.
|
||||||
|
- Expanded test coverage for `Logger.Printf`, HTTP level mapping, constructor behavior, threshold filtering, and backward compatibility.
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
- Improved GoDoc coverage for exported types, constructors, formatters, colors, HTTP helpers, and time layouts.
|
- Improved GoDoc coverage for exported types, constructors, formatters, colors, HTTP helpers, and time layouts.
|
||||||
- Documented level comparison helpers and explicit-level formatted logging.
|
- Documented threshold mode, threshold-aware constructors, level comparison helpers, and explicit-level formatted logging.
|
||||||
- Expanded inline documentation for formatter tokens and default formatter behavior.
|
- Expanded inline documentation for formatter tokens and default formatter behavior.
|
||||||
|
- Updated English and Russian README files with threshold-mode examples and comparison guidance.
|
||||||
|
|
||||||
### Compatibility
|
### Compatibility
|
||||||
|
|
||||||
- No breaking API changes.
|
- No breaking API changes.
|
||||||
- Existing `Print`, `Println`, predefined levels, and color APIs remain compatible.
|
- Existing `Print`, `Println`, predefined levels, `Level/SetLevel`, and color APIs remain compatible.
|
||||||
|
- Legacy severity ordering remains the default; threshold filtering is enabled only when `SetThresholdMode(true)` is called.
|
||||||
|
- `SameLevel` remains severity-only for backward compatibility, even when levels carry threshold metadata.
|
||||||
|
|
||||||
# v2.1.0
|
# v2.1.0
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
// io.Writer values through CreateTextWriter or CreateJsonWriter remain owned by
|
// io.Writer values through CreateTextWriter or CreateJsonWriter remain owned by
|
||||||
// the caller and are not closed by the logger.
|
// the caller and are not closed by the logger.
|
||||||
//
|
//
|
||||||
// LogLevel values can be compared with SameLevel when only severity matters or
|
// LogLevel values can be compared with SameLevel when only the legacy severity
|
||||||
|
// index matters, with SameThreshold when only threshold filtering matters, or
|
||||||
// with Equal when the full level configuration must match.
|
// with Equal when the full level configuration must match.
|
||||||
package sneklog
|
package sneklog
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ func (l *Logger) Debugln(m ...any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) print(level LogLevel, newline bool, m ...any) {
|
func (l *Logger) print(level LogLevel, newline bool, m ...any) {
|
||||||
if l.level.n < level.n {
|
if l.threshold && l.level.th < level.th {
|
||||||
|
return
|
||||||
|
} else if l.level.n < level.n {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(l.writers) == 0 {
|
if len(l.writers) == 0 {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ var (
|
|||||||
// LogLevel describes a logging severity.
|
// LogLevel describes a logging severity.
|
||||||
type LogLevel struct {
|
type LogLevel struct {
|
||||||
n uint8
|
n uint8
|
||||||
|
th uint8
|
||||||
t string
|
t string
|
||||||
|
|
||||||
fg FgColor
|
fg FgColor
|
||||||
@@ -26,53 +27,68 @@ type LogLevel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewLogLevel creates a log level without predefined colors.
|
// NewLogLevel creates a log level without predefined colors.
|
||||||
|
// Deprecated: use NewThresholdLogLevel. This function will be removed in v3.
|
||||||
func NewLogLevel(index uint8, name string) LogLevel {
|
func NewLogLevel(index uint8, name string) LogLevel {
|
||||||
return NewLogLevelWithColors(index, name, 0, 0)
|
return NewLogLevelWithColors(index, name, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLogLevelWithColors creates a log level with ANSI foreground and background colors.
|
// NewLogLevelWithColors creates a log level with ANSI foreground and background colors.
|
||||||
|
// Deprecated: use NewThresholdLogLevelWithColors. This function will be removed in v3.
|
||||||
func NewLogLevelWithColors(index uint8, name string, fg FgColor, bg BgColor) LogLevel {
|
func NewLogLevelWithColors(index uint8, name string, fg FgColor, bg BgColor) LogLevel {
|
||||||
return LogLevel{n: index, t: name, fg: fg, bg: bg, attrs: []Attribute{}}
|
return LogLevel{n: index, t: name, fg: fg, bg: bg, attrs: []Attribute{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewThresholdLogLevel creates a log level with both a legacy severity index and
|
||||||
|
// a threshold value used when Logger.SetThresholdMode(true) is enabled.
|
||||||
|
func NewThresholdLogLevel(index, th uint8, name string) LogLevel {
|
||||||
|
return NewThresholdLogLevelWithColors(index, th, name, FgNone, BgNone)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewThresholdLogLevelWithColors creates a log level with both a legacy
|
||||||
|
// severity index and a threshold value, plus ANSI foreground and background
|
||||||
|
// colors.
|
||||||
|
func NewThresholdLogLevelWithColors(index, th uint8, name string, fg FgColor, bg BgColor) LogLevel {
|
||||||
|
return LogLevel{n: index, th: th, t: name, fg: fg, bg: bg, attrs: []Attribute{}}
|
||||||
|
}
|
||||||
|
|
||||||
// NewInfoLogLevel creates an info-level log level without predefined colors.
|
// NewInfoLogLevel creates an info-level log level without predefined colors.
|
||||||
func NewInfoLogLevel(name string) LogLevel { return NewLogLevel(0, name) }
|
func NewInfoLogLevel(name string) LogLevel { return NewThresholdLogLevel(0, 10, name) }
|
||||||
|
|
||||||
// NewInfoLogLevelWithColors creates an info-level log level with ANSI colors.
|
// NewInfoLogLevelWithColors creates an info-level log level with ANSI colors.
|
||||||
func NewInfoLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
func NewInfoLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
||||||
return NewLogLevelWithColors(0, name, fg, bg)
|
return NewThresholdLogLevelWithColors(0, 10, name, fg, bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWarnLogLevel creates a warn-level log level without predefined colors.
|
// NewWarnLogLevel creates a warn-level log level without predefined colors.
|
||||||
func NewWarnLogLevel(name string) LogLevel { return NewLogLevel(1, name) }
|
func NewWarnLogLevel(name string) LogLevel { return NewThresholdLogLevel(1, 20, name) }
|
||||||
|
|
||||||
// NewWarnLogLevelWithColors creates a warn-level log level with ANSI colors.
|
// NewWarnLogLevelWithColors creates a warn-level log level with ANSI colors.
|
||||||
func NewWarnLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
func NewWarnLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
||||||
return NewLogLevelWithColors(1, name, fg, bg)
|
return NewThresholdLogLevelWithColors(1, 20, name, fg, bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewErrorLogLevel creates an error-level log level without predefined colors.
|
// NewErrorLogLevel creates an error-level log level without predefined colors.
|
||||||
func NewErrorLogLevel(name string) LogLevel { return NewLogLevel(2, name) }
|
func NewErrorLogLevel(name string) LogLevel { return NewThresholdLogLevel(2, 30, name) }
|
||||||
|
|
||||||
// NewErrorLogLevelWithColors creates an error-level log level with ANSI colors.
|
// NewErrorLogLevelWithColors creates an error-level log level with ANSI colors.
|
||||||
func NewErrorLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
func NewErrorLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
||||||
return NewLogLevelWithColors(2, name, fg, bg)
|
return NewThresholdLogLevelWithColors(2, 30, name, fg, bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFatalLogLevel creates a fatal-level log level without predefined colors.
|
// NewFatalLogLevel creates a fatal-level log level without predefined colors.
|
||||||
func NewFatalLogLevel(name string) LogLevel { return NewLogLevel(3, name) }
|
func NewFatalLogLevel(name string) LogLevel { return NewThresholdLogLevel(3, 40, name) }
|
||||||
|
|
||||||
// NewFatalLogLevelWithColors creates a fatal-level log level with ANSI colors.
|
// NewFatalLogLevelWithColors creates a fatal-level log level with ANSI colors.
|
||||||
func NewFatalLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
func NewFatalLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
||||||
return NewLogLevelWithColors(3, name, fg, bg)
|
return NewThresholdLogLevelWithColors(3, 40, name, fg, bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDebugLogLevel creates a debug-level log level without predefined colors.
|
// NewDebugLogLevel creates a debug-level log level without predefined colors.
|
||||||
func NewDebugLogLevel(name string) LogLevel { return NewLogLevel(4, name) }
|
func NewDebugLogLevel(name string) LogLevel { return NewThresholdLogLevel(4, 0, name) }
|
||||||
|
|
||||||
// NewDebugLogLevelWithColors creates a debug-level log level with ANSI colors.
|
// NewDebugLogLevelWithColors creates a debug-level log level with ANSI colors.
|
||||||
func NewDebugLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
func NewDebugLogLevelWithColors(name string, fg FgColor, bg BgColor) LogLevel {
|
||||||
return NewLogLevelWithColors(4, name, fg, bg)
|
return NewThresholdLogLevelWithColors(4, 0, name, fg, bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetName returns the lowercase textual representation of the level.
|
// GetName returns the lowercase textual representation of the level.
|
||||||
@@ -198,13 +214,21 @@ func (l *LogLevel) GetAttributes() []Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SameLevel reports whether two log levels have the same severity index.
|
// SameLevel reports whether two log levels have the same severity index.
|
||||||
|
// Deprecated: use SameThreshold for threshold-only comparisons or Equal for the
|
||||||
|
// full level configuration. SameLevel remains severity-only for backward
|
||||||
|
// compatibility and ignores threshold values.
|
||||||
func (l *LogLevel) SameLevel(other LogLevel) bool {
|
func (l *LogLevel) SameLevel(other LogLevel) bool {
|
||||||
return l.n == other.n
|
return l.n == other.n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SameThreshold reports whether two log levels have the same threshold value.
|
||||||
|
func (l *LogLevel) SameThreshold(other LogLevel) bool {
|
||||||
|
return l.th == other.th
|
||||||
|
}
|
||||||
|
|
||||||
// Equal reports whether two log levels have identical configuration.
|
// Equal reports whether two log levels have identical configuration.
|
||||||
func (l *LogLevel) Equal(other LogLevel) bool {
|
func (l *LogLevel) Equal(other LogLevel) bool {
|
||||||
if l.t != other.t || l.n != other.n {
|
if l.t != other.t || l.n != other.n || l.th != other.th {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if l.fg != other.fg || l.bg != other.bg {
|
if l.fg != other.fg || l.bg != other.bg {
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ type MethodTraceback struct {
|
|||||||
type Logger struct {
|
type Logger struct {
|
||||||
prefix string
|
prefix string
|
||||||
level LogLevel
|
level LogLevel
|
||||||
|
|
||||||
writers []LoggerWriter
|
writers []LoggerWriter
|
||||||
replacers []replacer
|
replacers []replacer
|
||||||
|
|
||||||
jsonPretty bool
|
jsonPretty bool
|
||||||
|
threshold bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateLogger creates a logger with default settings.
|
// CreateLogger creates a logger with default settings.
|
||||||
@@ -82,6 +84,13 @@ func (l *Logger) SetJSONPretty(b bool) *Logger {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetThresholdMode switches Logger.Print filtering from legacy severity-index
|
||||||
|
// ordering to LogLevel threshold ordering.
|
||||||
|
func (l *Logger) SetThresholdMode(b bool) *Logger {
|
||||||
|
l.threshold = b
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
// AddWriters appends multiple writers to the logger.
|
// AddWriters appends multiple writers to the logger.
|
||||||
func (l *Logger) AddWriters(writers ...LoggerWriter) *Logger {
|
func (l *Logger) AddWriters(writers ...LoggerWriter) *Logger {
|
||||||
l.writers = append(l.writers, writers...)
|
l.writers = append(l.writers, writers...)
|
||||||
|
|||||||
+80
-5
@@ -120,6 +120,77 @@ func TestLoggerPrintfFormatsMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoggerUsesSeverityOrderingWhenThresholdModeIsDisabled(t *testing.T) {
|
||||||
|
writer := &stubLoggerWriter{}
|
||||||
|
logger := CreateLogger().
|
||||||
|
SetLevel(NewThresholdLogLevel(1, 0, "warn")).
|
||||||
|
AddWriter(writer)
|
||||||
|
|
||||||
|
logger.Print(NewThresholdLogLevel(0, 100, "info"))
|
||||||
|
logger.Print(NewThresholdLogLevel(2, 0, "error"))
|
||||||
|
|
||||||
|
if writer.printCalls != 1 {
|
||||||
|
t.Fatalf("severity mode should allow only lower-or-equal severity levels, got %d writes", writer.printCalls)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoggerUsesThresholdOrderingWhenThresholdModeIsEnabled(t *testing.T) {
|
||||||
|
writer := &stubLoggerWriter{}
|
||||||
|
logger := CreateLogger().
|
||||||
|
SetLevel(NewThresholdLogLevel(4, 20, "custom")).
|
||||||
|
SetThresholdMode(true).
|
||||||
|
AddWriter(writer)
|
||||||
|
|
||||||
|
logger.Print(NewThresholdLogLevel(4, 10, "debug"))
|
||||||
|
logger.Print(NewThresholdLogLevel(0, 30, "info"))
|
||||||
|
|
||||||
|
if writer.printCalls != 1 {
|
||||||
|
t.Fatalf("threshold mode should allow only entries at or below the configured threshold, got %d writes", writer.printCalls)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeprecatedLevelMethodKeepsLegacySeverityBehavior(t *testing.T) {
|
||||||
|
writer := &stubLoggerWriter{}
|
||||||
|
logger := CreateLogger().
|
||||||
|
Level(FATAL).
|
||||||
|
AddWriter(writer)
|
||||||
|
|
||||||
|
logger.Print(INFO, "info")
|
||||||
|
logger.Print(WARN, "warn")
|
||||||
|
logger.Print(ERROR, "error")
|
||||||
|
logger.Print(FATAL, "fatal")
|
||||||
|
logger.Print(DEBUG, "debug")
|
||||||
|
|
||||||
|
if writer.printCalls != 4 {
|
||||||
|
t.Fatalf("Level(FATAL) should keep legacy behavior and allow INFO/WARN/ERROR/FATAL only, got %d writes", writer.printCalls)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSameLevelIgnoresThresholdDifferencesForCompatibility(t *testing.T) {
|
||||||
|
legacy := NewLogLevel(1, "warn")
|
||||||
|
threshold := NewThresholdLogLevel(1, 20, "warn")
|
||||||
|
|
||||||
|
if !legacy.SameLevel(threshold) {
|
||||||
|
t.Fatalf("SameLevel() should continue comparing only severity index")
|
||||||
|
}
|
||||||
|
if legacy.Equal(threshold) {
|
||||||
|
t.Fatalf("Equal() should distinguish levels with different threshold configuration")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSameThresholdComparesOnlyThresholdValue(t *testing.T) {
|
||||||
|
first := NewThresholdLogLevel(1, 20, "warn")
|
||||||
|
second := NewThresholdLogLevel(9, 20, "custom")
|
||||||
|
third := NewThresholdLogLevel(1, 30, "warn")
|
||||||
|
|
||||||
|
if !first.SameThreshold(second) {
|
||||||
|
t.Fatalf("SameThreshold() should ignore severity and compare threshold only")
|
||||||
|
}
|
||||||
|
if first.SameThreshold(third) {
|
||||||
|
t.Fatalf("SameThreshold() should detect different threshold values")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLogLevelForMethodReturnsExpectedLevels(t *testing.T) {
|
func TestLogLevelForMethodReturnsExpectedLevels(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -153,12 +224,13 @@ func TestNewLevelConstructorsSetExpectedSeverity(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
got LogLevel
|
got LogLevel
|
||||||
want LogLevel
|
want LogLevel
|
||||||
|
wantTh uint8
|
||||||
}{
|
}{
|
||||||
{name: "info", got: NewInfoLogLevel("custom"), want: INFO},
|
{name: "info", got: NewInfoLogLevel("custom"), want: INFO, wantTh: 10},
|
||||||
{name: "warn", got: NewWarnLogLevel("custom"), want: WARN},
|
{name: "warn", got: NewWarnLogLevel("custom"), want: WARN, wantTh: 20},
|
||||||
{name: "error", got: NewErrorLogLevel("custom"), want: ERROR},
|
{name: "error", got: NewErrorLogLevel("custom"), want: ERROR, wantTh: 30},
|
||||||
{name: "fatal", got: NewFatalLogLevel("custom"), want: FATAL},
|
{name: "fatal", got: NewFatalLogLevel("custom"), want: FATAL, wantTh: 40},
|
||||||
{name: "debug", got: NewDebugLogLevel("custom"), want: DEBUG},
|
{name: "debug", got: NewDebugLogLevel("custom"), want: DEBUG, wantTh: 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -166,6 +238,9 @@ func TestNewLevelConstructorsSetExpectedSeverity(t *testing.T) {
|
|||||||
if tt.got.n != tt.want.n {
|
if tt.got.n != tt.want.n {
|
||||||
t.Fatalf("%s severity = %d, want %d", tt.name, tt.got.n, tt.want.n)
|
t.Fatalf("%s severity = %d, want %d", tt.name, tt.got.n, tt.want.n)
|
||||||
}
|
}
|
||||||
|
if tt.got.th != tt.wantTh {
|
||||||
|
t.Fatalf("%s threshold = %d, want %d", tt.name, tt.got.th, tt.wantTh)
|
||||||
|
}
|
||||||
if tt.got.GetName() != "custom" {
|
if tt.got.GetName() != "custom" {
|
||||||
t.Fatalf("%s constructor should preserve name, got %q", tt.name, tt.got.GetName())
|
t.Fatalf("%s constructor should preserve name, got %q", tt.name, tt.got.GetName())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user