FILE / ScuroNeko/SNekLog
README_ru.md
Исходный файл и его история в репозитории.
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
224 lines
8.1 KiB
Markdown
224 lines
8.1 KiB
Markdown
# SNekLog (ScuroNeko Logger)
|
||
|
||
Небольшой структурированный логгер для Go с текстовым и JSON-выводом, несколькими writer'ами и настраиваемыми traceback-метаданными.
|
||
|
||
English version: [README.md](README.md)
|
||
|
||
## Возможности
|
||
|
||
- Одновременная запись в несколько destinations.
|
||
- Текстовый и JSON-форматы.
|
||
- `stdout`, файлы и любые внешние `io.Writer`.
|
||
- Опциональные timestamp'ы для текстового вывода.
|
||
- Компактный traceback для текстовых writer'ов и полный traceback для JSON.
|
||
- Замена текста в сообщениях для маскирования секретов или нормализации вывода.
|
||
- Явные правила владения writer'ами при `Close()`.
|
||
|
||
## Установка
|
||
|
||
```bash
|
||
go get git.scuroneko.dev/scuroneko/sneklog/v2
|
||
```
|
||
|
||
## Быстрый старт
|
||
|
||
```go
|
||
package main
|
||
|
||
import (
|
||
"log"
|
||
|
||
"git.scuroneko.dev/scuroneko/sneklog/v2"
|
||
)
|
||
|
||
func main() {
|
||
logger := sneklog.NewLogger().
|
||
SetName("API").
|
||
SetLevel(sneklog.DEBUG).
|
||
AddReplacer("SOME_SECRET", "<redacted>")
|
||
|
||
text := logger.CreateTextStdoutWriter()
|
||
jsonFile, err := logger.CreateJsonFileWriter("logs/app.json")
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
logger.AddWriters(text, jsonFile)
|
||
|
||
logger.Infoln("service started")
|
||
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)
|
||
}
|
||
}
|
||
```
|
||
|
||
## Значения по умолчанию
|
||
|
||
`NewLogger()` создает логгер со следующими настройками:
|
||
|
||
- `Prefix("LOG")`
|
||
- `Level(sneklog.FATAL)`
|
||
- `JsonPretty(false)`
|
||
- текстовый formatter: `sneklog.DefaultTextFormatter`
|
||
- JSON formatter: `sneklog.DefaultJsonFormatter`
|
||
|
||
`CreateLogger()` по-прежнему доступен для обратной совместимости.
|
||
|
||
Важно: в текущей модели уровней `Level(sneklog.FATAL)` пропускает `INFO`, `WARN`, `ERROR` и `FATAL`, но не `DEBUG`. Чтобы включить все сообщения, используйте `Level(sneklog.DEBUG)`.
|
||
|
||
Если нужна классическая threshold-фильтрация, включите `SetThresholdMode(true)` и
|
||
задавайте уровни через `NewThresholdLogLevel(...)` или
|
||
`NewThresholdLogLevelWithColors(...)`.
|
||
|
||
## Writer'ы и владение
|
||
|
||
`Logger.Close()` закрывает только writer'ы, которые логгер создал сам:
|
||
|
||
- `CreateTextFileWriter(...)`
|
||
- `CreateJsonFileWriter(...)`
|
||
|
||
Внешние writer'ы не закрываются:
|
||
|
||
- `CreateTextWriter(existingWriter)`
|
||
- `CreateJsonWriter(existingWriter)`
|
||
- `CreateTextStdoutWriter()`
|
||
- `CreateJsonStdoutWriter()`
|
||
|
||
Это позволяет безопасно подключать `bytes.Buffer`, сетевые writer'ы и другие уже управляемые ресурсы.
|
||
|
||
## Форматы вывода
|
||
|
||
Текстовый writer формирует записи вида:
|
||
|
||
```text
|
||
2026-03-17T14:05:09+03:00 info API: service started
|
||
```
|
||
|
||
Используйте `SetFormatter` у writer'а, чтобы настроить timestamp'ы, traceback-поля, цвета и шаблон сообщения.
|
||
|
||
JSON writer записывает объект со следующими полями:
|
||
|
||
```json
|
||
{
|
||
"time": "2026-03-17T14:05:09.123456789+03:00",
|
||
"level": "info",
|
||
"prefix": "API",
|
||
"message": "service started",
|
||
"traceback": [
|
||
{
|
||
"method": "main",
|
||
"filename": "main.go",
|
||
"line": 27,
|
||
"signature": "main.main",
|
||
"fullPath": "/path/to/main.go"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
Если включен `JsonPretty(true)`, JSON выводится с отступами.
|
||
|
||
## Кастомные уровни и цвета
|
||
|
||
Можно создавать собственные уровни и назначать им ANSI, 256-color или RGB-цвета, а также текстовые атрибуты вроде `Bold` и `Italic`.
|
||
|
||
```go
|
||
httpDelete := sneklog.NewLogLevel(0, "delete")
|
||
httpDelete.SetBackgroundRGB(128, 0, 0)
|
||
httpDelete.AddAttribute(sneklog.Italic).AddAttribute(sneklog.Bold)
|
||
|
||
httpCache := sneklog.NewLogLevel(0, "cache")
|
||
httpCache.SetForeground256Color(214)
|
||
```
|
||
|
||
Так как setter'ы `LogLevel` изменяют уровень на месте, их нужно вызывать на переменной, а не на временном результате `NewLogLevel(...)`.
|
||
Короткие формы вроде `SetFgColor` и `SetBgColor` сохранены для обратной совместимости.
|
||
|
||
Для стандартных severity также есть отдельные helper'ы:
|
||
|
||
```go
|
||
access := sneklog.NewInfoLogLevelWithColors("access", sneklog.FgCyan, sneklog.BgNone)
|
||
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-методов доступны готовые уровни:
|
||
|
||
```go
|
||
level := sneklog.LogLevelForMethod(http.MethodPost)
|
||
logger.Print(level, "POST /users")
|
||
```
|
||
|
||
При сравнении уровней:
|
||
|
||
- используйте `SameLevel`, если важен только legacy severity index;
|
||
- используйте `SameThreshold`, если важна только threshold-фильтрация;
|
||
- используйте `Equal`, если нужно полное совпадение конфигурации, включая threshold, цвета и атрибуты.
|
||
|
||
## Замена сообщений
|
||
|
||
`AddReplacer(old, new)` заменяет найденный текст в каждом сообщении до того,
|
||
как запись попадет в writer'ы. Правила замены применяются в порядке добавления.
|
||
|
||
```go
|
||
logger := sneklog.CreateLogger().
|
||
Level(sneklog.DEBUG).
|
||
AddReplacer("SOME_SECRET", "<redacted>").
|
||
AddReplacer("user@example.com", "<email>")
|
||
|
||
logger.Infoln("login token:", "SOME_SECRET")
|
||
```
|
||
|
||
В текстовом и JSON-выводе вместо `SOME_SECRET` будет записано `<redacted>`.
|
||
Пустое значение `old` игнорируется.
|
||
|
||
## API кратко
|
||
|
||
- `Info`, `Warn`, `Error`, `Debug`, `Fatal` принимают список значений.
|
||
- `Infof`, `Warnf`, `Errorf`, `Debugf`, `Fatalf` используют `fmt.Sprintf`.
|
||
- `Printf(level, format, args...)` форматирует сообщение для явного `LogLevel`.
|
||
- Методы `*ln` добавляют семантику перевода строки, что удобно для `stdout`, Docker и line-based collectors.
|
||
- `Fatal`, `Fatalf` и `Fatalln` вызывают `os.Exit(1)` после записи сообщения.
|
||
- `AddReplacer` маскирует или переписывает текст сообщений перед отправкой в writer'ы.
|
||
|
||
## Поведение traceback
|
||
|
||
- Текстовые writer'ы используют ближайший пользовательский stack frame.
|
||
- JSON writer'ы получают полный traceback.
|
||
- Внутренние frame'ы `sneklog` и `runtime` фильтруются из traceback.
|
||
|
||
## Пример из репозитория
|
||
|
||
См. [examples/main.go](examples/main.go).
|
||
|
||
## Лицензия
|
||
|
||
Проект распространяется под GNU GPLv3. См. [LICENSE](LICENSE).
|