Documentation
¶
Index ¶
- type AfterHookFunc
- type BeforeHookFunc
- type ErrorHandlerFunc
- type Extra
- type Handler
- type HandlerOptions
- type Level
- type Logger
- func (logger *Logger) AddHandler(handler Handler)
- func (logger *Logger) Bind(extra Extra) *Logger
- func (logger *Logger) Contextualize(ctx context.Context, extra Extra) context.Context
- func (logger *Logger) Debug(message string)
- func (logger *Logger) Debugf(format string, a ...any)
- func (logger *Logger) Error(message string)
- func (logger *Logger) Errorf(format string, a ...any)
- func (logger *Logger) Fatal(message string)
- func (logger *Logger) Fatalf(format string, a ...any)
- func (logger *Logger) Info(message string)
- func (logger *Logger) Infof(format string, a ...any)
- func (logger *Logger) Warning(message string)
- func (logger *Logger) Warningf(format string, a ...any)
- type Record
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AfterHookFunc ¶ added in v0.6.0
AfterHookFunc is called after a record is rendered.
The rendered argument contains the final rendered output written by the handler.
type BeforeHookFunc ¶ added in v0.6.0
type BeforeHookFunc func(record *Record)
BeforeHookFunc is called before a record is rendered.
It can modify the record, for example by changing Message or adding Extra fields.
type ErrorHandlerFunc ¶ added in v0.5.1
ErrorHandlerFunc is called when a log record cannot be written.
The err argument contains the write error returned by the underlying writer. The msg argument contains the already rendered log message that failed to write.
ErrorHandlerFunc is optional. If it is nil, write errors are ignored.
type Extra ¶ added in v0.2.0
Extra stores contextual key-value fields attached to log records.
Extra values can be rendered with template placeholders such as {extra[user_id]} or as a full JSON object with {extra}.
type Handler ¶ added in v0.2.0
type Handler struct {
// contains filtered or unexported fields
}
Handler defines where and how log records are written.
Each handler has its own output writer, minimum level, template, time formatting settings, and output mode.
func NewHandler ¶ added in v0.2.0
func NewHandler(out io.Writer, level Level, options *HandlerOptions) Handler
NewHandler creates a handler for the given writer and minimum level.
If options is nil, the handler uses the default text template, RFC3339 time format, and local time zone.
type HandlerOptions ¶ added in v0.4.0
type HandlerOptions struct {
// Template defines the output fields and their order.
//
// In text mode, text and placeholders are rendered as a log line.
// In JSON mode, placeholders define the JSON fields and their order;
// plain text parts are ignored.
Template string
// TimeFormat defines how the {time} placeholder is formatted.
//
// If empty, time.RFC3339 is used.
TimeFormat string
// Location defines the time zone used for the {time} placeholder.
//
// If nil, time.Local is used.
Location *time.Location
// JSON enables JSON output mode.
JSON bool
// WithCaller enables caller fields in template.
WithCaller bool
// ErrorHandler handles write errors.
//
// If nil, write errors are ignored.
ErrorHandler ErrorHandlerFunc
// BeforeHook is called before rendering a log record.
//
// NOTE: The record is passed by reference. Modifying it affects ONLY this handler's output.
// If this handler has no BeforeHook, the record is shared (read-only) for performance.
BeforeHook BeforeHookFunc
// AfterHook is called after rendering a log record.
//
// It receives the record and the rendered output.
AfterHook AfterHookFunc
// ReadOnly skips record cloning. Mutating the record in this mode breaks handler isolation.
ReadOnly bool
}
HandlerOptions configures a Handler.
A nil HandlerOptions value passed to NewHandler uses the default template, RFC3339 time format, local time zone, and text output mode.
Example (Hooks) ¶
ExampleHandlerOptions_hooks demonstrates BeforeHook and AfterHook usage, per-handler record isolation, and caller metadata injection.
package main
import (
"os"
"strings"
"github.com/DasKaroWow/solislog"
)
func main() {
logger := solislog.NewLogger(
solislog.Extra{"service": "api"},
solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
Template: "<gray>{caller}</gray> | <level>{level}</level> | service={extra[service]} hook={extra[hook]} | {message}\n",
WithCaller: true,
BeforeHook: func(record *solislog.Record) {
record.Message = strings.ToUpper(record.Message)
record.Extra["hook"] = "before"
},
AfterHook: func(record *solislog.Record, msg []byte, successful bool) {
// Example side effect: count metrics, send rendered output elsewhere,
// or inspect the final rendered log line.
_ = msg
},
}),
// Second handler receives the original record (no hooks applied to it)
solislog.NewHandler(os.Stdout, solislog.InfoLevel, nil),
)
logger.Info("hook changed this message only in first handler")
}
Output:
type Level ¶
type Level int
Level represents the severity of a log message.
const ( // DebugLevel is used for detailed diagnostic messages. DebugLevel Level = iota // InfoLevel is used for general informational messages. InfoLevel // WarningLevel is used for messages about unexpected but non-fatal situations. WarningLevel // ErrorLevel is used for errors that should be visible to the caller. ErrorLevel // FatalLevel is used for fatal errors. // // Logger.Fatal logs the message and then exits the process with status code 1. FatalLevel )
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger writes log messages to one or more handlers.
A Logger keeps default contextual fields in Extra and shares its handler configuration with loggers created by Bind or Contextualize.
func FromContext ¶
FromContext returns a logger stored in ctx by Contextualize.
The second return value reports whether a logger was found.
func NewLogger ¶ added in v0.2.0
NewLogger creates a logger with default extra fields and handlers.
The provided Extra is copied, so later changes to the original map do not affect the logger. Handlers can also be added later with AddHandler.
Example (Json) ¶
ExampleNewLogger_json shows how to configure a JSON output handler with custom time formatting and timezone.
package main
import (
"os"
"time"
"github.com/DasKaroWow/solislog"
)
func main() {
loc, err := time.LoadLocation("Europe/Helsinki")
if err != nil {
panic(err)
}
logger := solislog.NewLogger(
solislog.Extra{
"service": "api",
"env": "dev",
},
solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
JSON: true,
TimeFormat: time.RFC3339,
Location: loc,
// In JSON mode, plain text in the template is ignored.
// Placeholders define the JSON fields and their order.
Template: "{time} {level} {message} {extra[service]} {extra[env]} {extra}",
}),
)
logger.Info("json message")
}
Output:
Example (Text) ¶
ExampleNewLogger_text demonstrates a basic text logger with ANSI colors, extra fields, and multiple log levels.
package main
import (
"os"
"github.com/DasKaroWow/solislog"
)
func main() {
logger := solislog.NewLogger(
solislog.Extra{
"service": "api",
"env": "dev",
},
solislog.NewHandler(os.Stdout, solislog.DebugLevel, &solislog.HandlerOptions{
Template: "<gray>{time}</gray> | <level>{level}</level> | service={extra[service]} env={extra[env]} | {message}\n",
}),
)
logger.Debug("debug message")
logger.Info("server started")
logger.Warning("slow request")
logger.Error("request failed")
// NOTE: // Output: is intentionally omitted because the template
// contains {time} and ANSI escape codes, which change per run.
// The function will still compile and run during `go test`.
}
Output:
func (*Logger) AddHandler ¶ added in v0.2.0
AddHandler adds a handler to the logger.
The handler is added to the logger's shared core, so it is also used by loggers created from this logger with Bind or Contextualize.
func (*Logger) Bind ¶ added in v0.2.0
Bind returns a new logger with additional contextual fields. If extra is empty (nil or zero length), the same logger instance is returned.
The returned logger shares handlers with the original logger. If extra contains keys that already exist on the logger, the new values override the old ones for the returned logger only.
func (*Logger) Contextualize ¶
Contextualize returns a context containing a bound logger.
The stored logger shares handlers with the original logger and includes the provided extra fields.
Example ¶
ExampleLogger_Contextualize demonstrates binding extra fields to a logger, storing it in a context, and retrieving it in downstream functions.
package main
import (
"context"
"os"
"github.com/DasKaroWow/solislog"
)
func main() {
base := solislog.NewLogger(
solislog.Extra{"service": "api"},
solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
Template: "<level>{level}</level> | service={extra[service]} request_id={extra[request_id]} user_id={extra[user_id]} | {message}\n",
}),
)
// Bind request-specific fields
requestLogger := base.Bind(solislog.Extra{"request_id": "req-123"})
// Inject into context
ctx := context.Background()
ctx = requestLogger.Contextualize(ctx, solislog.Extra{"user_id": "42"})
// Pass context through layers
handleRequestCtx(ctx)
}
// Helpers for the context example (unexported, scoped to tests)
func handleRequestCtx(ctx context.Context) {
logger, ok := solislog.FromContext(ctx)
if !ok {
return
}
logger.Info("request received")
processRequestCtx(ctx)
}
func processRequestCtx(ctx context.Context) {
logger, ok := solislog.FromContext(ctx)
if !ok {
return
}
logger.Info("processing request")
}
Output:
func (*Logger) Debugf ¶ added in v1.1.1
Debugf formats a message using fmt.Sprintf and logs it at DebugLevel.
func (*Logger) Errorf ¶ added in v1.1.1
Errorf formats a message using fmt.Sprintf and logs it at ErrorLevel.
func (*Logger) Fatal ¶ added in v0.2.1
Fatal logs a message at FatalLevel and exits the process with status code 1.
func (*Logger) Fatalf ¶ added in v1.1.1
Fatalf formats a message using fmt.Sprintf, logs it at FatalLevel, and exits the process with status code 1.
func (*Logger) Infof ¶ added in v1.1.1
Infof formats a message using fmt.Sprintf and logs it at InfoLevel.
Example ¶
ExampleLogger_Infof demonstrates formatted logging.
package main
import (
"os"
"github.com/DasKaroWow/solislog"
)
func main() {
logger := solislog.NewLogger(
nil,
solislog.NewHandler(os.Stdout, solislog.InfoLevel, nil),
)
logger.Infof("user %s logged in from %s", "alice", "192.0.2.1")
// NOTE: // Output: is intentionally omitted because the template
// contains {time} and ANSI escape codes, which change per run.
// The function will still compile and run during `go test`.
}
Output:
type Record ¶ added in v0.6.0
type Record struct {
// Time is the moment when the log record was created.
Time time.Time
// Level is the severity of the log record.
Level Level
// Extra contains contextual key-value fields attached to the logger.
Extra Extra
// Message is the log message text passed to the logger.
Message string
// File is the base name of the source file where the log call was made.
File string
// Path is the full source file path where the log call was made.
Path string
// Line is the source line number where the log call was made.
Line int
// Function is the full function name where the log call was made.
Function string
// Caller is the compact source location in the form "file:line".
Caller string
}
Record contains all data used to render a single log entry.
A Record is passed to hooks before and after rendering. Before hooks may modify the record before it is rendered by a handler.