# 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", "") 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", ""). AddReplacer("user@example.com", "") logger.Infoln("login token:", "SOME_SECRET") ``` В текстовом и JSON-выводе вместо `SOME_SECRET` будет записано ``. Пустое значение `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).