FILE / ScuroNeko/SNekLog

README.md

Исходный файл и его история в репозитории.
FILE e6d15b530f892fe196da6203ba9383e21c5548fc
Files
SNekLog/README.md
T
ScuroNeko e6d15b530f
Golang lint / lint (push) Successful in 1m36s
(new): add threshold-based log level filtering and docs
- 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
2026-04-28 09:45:40 +03:00

6.1 KiB

SNekLog (ScuroNeko Logger)

Small structured logger for Go with text and JSON output, multiple writers, and optional traceback metadata.

Russian version: README_ru.md

Features

  • Fan out the same record to multiple destinations.
  • Text and JSON writers.
  • 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

go get git.scuroneko.dev/scuroneko/sneklog/v2

Quick start

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)
	}
}

Defaults

NewLogger() starts with:

  • Prefix("LOG")
  • Level(sneklog.FATAL)
  • JsonPretty(false)
  • text formatter: sneklog.DefaultTextFormatter
  • JSON formatter: sneklog.DefaultJsonFormatter

CreateLogger() is still available for backward compatibility.

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

Logger.Close() only closes writers created by the logger itself:

  • CreateTextFileWriter(...)
  • CreateJsonFileWriter(...)

The following writers remain owned by the caller and are not closed by Logger.Close():

  • CreateTextWriter(existingWriter)
  • CreateJsonWriter(existingWriter)
  • CreateTextStdoutWriter()
  • CreateJsonStdoutWriter()

This makes it safe to plug in bytes.Buffer, network writers, and other externally managed resources.

Output formats

Text writers render records like:

2026-03-17T14:05:09+03:00 info API: service started

Use SetFormatter on a writer to customize timestamps, traceback fields, colors, and message layout.

JSON writers emit objects with this shape:

{
  "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"
    }
  ]
}

When JsonPretty(true) is enabled, JSON is indented.

Custom levels and colors

You can define your own levels and assign ANSI, 256-color, or RGB colors, plus text attributes such as Bold or Italic.

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)

Because LogLevel setters mutate the level in place, call them on a variable, not on a temporary value returned by NewLogLevel(...). Short forms such as SetFgColor and SetBgColor remain available for backward compatibility.

Common severities also have dedicated helpers:

access := sneklog.NewInfoLogLevelWithColors("access", sneklog.FgCyan, sneklog.BgNone)
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:

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:

level := sneklog.LogLevelForMethod(http.MethodPost)
logger.Print(level, "POST /users")

When comparing levels:

  • 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

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.

logger := sneklog.CreateLogger().
	Level(sneklog.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.
  • Printf(level, format, args...) formats a message for an explicit LogLevel.
  • 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

  • Text writers use the nearest user stack frame.
  • JSON writers receive the full traceback slice.
  • Internal sneklog frames and runtime frames are filtered out.

Repository example

See examples/main.go.

License

This project is licensed under GNU GPLv3. See LICENSE.