feat: add message replacement for log records
Add Logger.AddReplacer to mask or normalize message text before records reach writers. Document replacement behavior in README and package GoDoc, and update the example. Also fix JSON writer edge cases: - avoid panic on empty message lists - preserve newline semantics when the last message already ends with n - keep original message argument types for custom writers when no replacers are configured Update dependencies and add release notes for the next release.
This commit is contained in:
@@ -11,6 +11,7 @@ Russian version: [README_ru.md](README_ru.md)
|
||||
- `stdout`, files, and arbitrary external `io.Writer` values.
|
||||
- Optional timestamps for text output.
|
||||
- Compact traceback metadata for text writers and full traceback slices for JSON.
|
||||
- Message replacement for masking secrets or normalizing output.
|
||||
- Explicit ownership rules for writer closing.
|
||||
|
||||
## Installation
|
||||
@@ -35,7 +36,8 @@ func main() {
|
||||
Prefix("API").
|
||||
Level(slog.DEBUG).
|
||||
PrintTraceback(true).
|
||||
JsonPretty(true)
|
||||
JsonPretty(true).
|
||||
AddReplacer("SOME_SECRET", "<redacted>")
|
||||
|
||||
text := logger.CreateTextStdoutWriter()
|
||||
jsonFile, err := logger.CreateJsonFileWriter("logs/app.json")
|
||||
@@ -49,6 +51,7 @@ func main() {
|
||||
logger.Warnln("cache miss")
|
||||
logger.Errorln("request failed")
|
||||
logger.Debugln("debug details")
|
||||
logger.Infoln("token", "SOME_SECRET")
|
||||
|
||||
if err := logger.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -116,12 +119,31 @@ JSON writers emit objects with this shape:
|
||||
|
||||
When `JsonPretty(true)` is enabled, JSON is indented.
|
||||
|
||||
## Message replacement
|
||||
|
||||
`AddReplacer(old, new)` replaces matching text in every message before the
|
||||
record reaches any writer. Replacement rules are applied in the order they are
|
||||
added.
|
||||
|
||||
```go
|
||||
logger := slog.CreateLogger().
|
||||
Level(slog.DEBUG).
|
||||
AddReplacer("SOME_SECRET", "<redacted>").
|
||||
AddReplacer("user@example.com", "<email>")
|
||||
|
||||
logger.Infoln("login token:", "SOME_SECRET")
|
||||
```
|
||||
|
||||
This writes `<redacted>` instead of `SOME_SECRET` in both text and JSON output.
|
||||
An empty `old` value is ignored.
|
||||
|
||||
## API summary
|
||||
|
||||
- `Info`, `Warn`, `Error`, `Debug`, and `Fatal` accept a list of values.
|
||||
- `Infof`, `Warnf`, `Errorf`, `Debugf`, and `Fatalf` use `fmt.Sprintf`.
|
||||
- The `*ln` methods preserve newline semantics, which is useful for `stdout`, Docker, and line-based collectors.
|
||||
- `Fatal`, `Fatalf`, and `Fatalln` call `os.Exit(1)` after writing the message.
|
||||
- `AddReplacer` masks or rewrites message text before records are sent to writers.
|
||||
|
||||
## Traceback behavior
|
||||
|
||||
|
||||
Reference in New Issue
Block a user