solislog

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: MIT Imports: 14 Imported by: 0

README

solislog

Go Reference Go Report Card

solislog is a small template-based contextual logger for Go. It focuses on readable console output, contextual fields, simple templates, optional colors, optional JSON output, and an API that stays close to normal Go patterns. The goal is not to compete with zap, zerolog, or slog on performance. The goal is to keep logging simple, readable, and pleasant to use in small and medium Go projects.

Features

  • Multiple handlers per logger
  • Per-handler log level filtering
  • Per-handler templates
  • Colorized text output with tags like <red>...</red> and <level>...</level>
  • Built-in template fields: {time}, {level}, {message}, {extra}
  • Caller metadata fields: {file}, {path}, {line}, {function}, {caller}
  • Custom contextual fields through {extra[key]}
  • Optional JSON output mode
  • BeforeHook and AfterHook for per-handler record processing
  • ErrorHandler for write errors
  • Bind(...) for creating child loggers with merged extra fields
  • Contextualize(...) and FromContext(...) for passing loggers through context.Context
  • Simple log methods: Debug, Info, Warning, Error, Fatal
  • Safe concurrent use by multiple goroutines

Installation

go get github.com/DasKaroWow/solislog

Quick start

package main

import (
    "os"
    "github.com/DasKaroWow/solislog"
)

func main() {
    logger := solislog.NewLogger(
        nil,
        solislog.NewHandler(os.Stdout, solislog.InfoLevel, nil),
    )

    logger.Info("hello from solislog")
}

Passing nil handler options uses the default template:

{time} | {level} | {message}\n

Example output:

2026-05-05T15:30:00+03:00 | INFO | hello from solislog

Colored output

Templates support ANSI color tags:

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

Supported colors: <black>...</black>, <red>...</red>, <green>...</green>, <yellow>...</yellow>, <blue>...</blue>, <magenta>...</magenta>, <cyan>...</cyan>, <white>...</white>, <gray>...</gray>

Special color tag: <level>...</level> <level> chooses a color based on the record level:

  • DEBUG → gray
  • INFO → cyan
  • WARNING → yellow
  • ERROR → red
  • FATAL → magenta

Example: <level>{level}</level> | {message}

Templates

Built-in fields:

  • {time}
  • {level}
  • {message}
  • {extra}
  • {file}
  • {path}
  • {line}
  • {function}
  • {caller}

Extra fields:

  • {extra[source]}
  • {extra[id]}
  • {extra[path]}

Template examples:

{time} | {level} | {message}
{caller} | {level} | {message}
{time} | <level>{level}</level> | {message}
<gray>{time}</gray> | <gray>{caller}</gray> | <level>{level}</level> | source={extra[source]} | {message}
{level} | {message} | extra={extra}

Escaping is done with \:

\<red\>     renders literal <red>
\{level\}   renders literal {level}

Invalid templates panic during handler creation. This includes unknown placeholders, unknown colors, empty placeholders, empty extra keys, unclosed placeholders, unclosed color tags, and mismatched color tags.

Caller metadata

solislog can render metadata about the source location where the log call was made. Enable it by setting WithCaller: true in HandlerOptions.

  • {file} base file name, for example main.go
  • {path} full source file path
  • {line} source line number
  • {function} full Go function name
  • {caller} compact source location in the form file:line

Example:

logger := solislog.NewLogger(
    nil,
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template:   "<gray>{caller}</gray> | <level>{level}</level> | {message}\n",
        WithCaller: true,
    }),
)

logger.Info("server started")

Example output:

main.go:14 | INFO | server started

Caller metadata also works in JSON mode:

logger := solislog.NewLogger(
    nil,
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        JSON:       true,
        WithCaller: true,
        Template:   "{level} {message} {caller} {file} {line} {function}",
    }),
)

Extra fields

Extra fields are stored as:

type Extra map[string]string

Individual extra fields can be rendered with {extra[key]}:

logger := solislog.NewLogger(
    solislog.Extra{
        "service": "api",
        "env":     "dev",
    },
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template: "<level>{level}</level> | service={extra[service]} env={extra[env]} | {message}\n",
    }),
)

logger.Info("server started")

The full extra map can be rendered with {extra}:

logger := solislog.NewLogger(
    solislog.Extra{
        "service": "api",
        "env":     "dev",
    },
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template: "{level} | {message} | extra={extra}\n",
    }),
)

logger.Info("hello")

Example output:

INFO | hello | extra={"env":"dev","service":"api"}

Binding extra fields

Use Bind(...) to create a child logger with additional or overridden extra fields.

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]} | {message}\n",
    }),
)

requestLogger := base.Bind(solislog.Extra{
    "request_id": "req-123",
})

requestLogger.Info("request received")
base.Info("base logger still has no request_id")

Bind(...) does not copy or replace handlers. The child logger uses the same shared core and only changes the attached extra fields. If extra is empty (nil or zero length), the same logger instance is returned. If a key already exists, the bound value overrides it for the child logger only.

Contextual logging

Contextualize(...) creates a bound logger and stores it in context.Context. This is useful at request, update, job, or operation boundaries.

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

    requestLogger := base.Bind(solislog.Extra{
        "request_id": "req-123",
    })

    ctx := context.Background()
    ctx = requestLogger.Contextualize(ctx, solislog.Extra{
        "user_id": "42",
    })

    handleRequest(ctx)
}

func handleRequest(ctx context.Context) {
    logger, ok := solislog.FromContext(ctx)
    if !ok {
        return
    }
    logger.Info("request received")
    processRequest(ctx)
}

func processRequest(ctx context.Context) {
    logger, ok := solislog.FromContext(ctx)
    if !ok {
        return
    }
    logger.Info("processing request")
}

JSON output

Set HandlerOptions.JSON to true to render records as JSON. In JSON mode, the template is used as a field list. Plain text is ignored. Only placeholders become JSON fields.

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,
        Template:   "{time} {level} {message} {extra[service]} {extra[env]} {extra}",
    }),
)

logger.Info("json message")

Example output:

{"time":"2026-05-05T15:30:00+03:00","level":"INFO","message":"json message","service":"api","env":"dev","extra":{"env":"dev","service":"api"}}

JSON field behavior:

  • {time}"time"
  • {level}"level"
  • {message}"message"
  • {file}"file"
  • {path}"path"
  • {line}"line"
  • {function}"function"
  • {caller}"caller"
  • {extra} → full extra object
  • {extra[id]} → flat field named "id"

For example: Template: "{level} {extra[id]} {extra}" renders fields like:

{"level":"INFO","id":"123","extra":{"id":"123"}}

Color tags are ignored in JSON mode: <red>{level}</red> <level>{message}</level> is equivalent to: {level} {message} for JSON output.

Hooks

Handlers can define hooks for custom per-handler processing.

BeforeHook runs before the record is rendered. It receives a mutable *solislog.Record, so it can change the message or add extra fields.

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

logger.Info("hook changed this message")

AfterHook runs after rendering and receives both the record and the rendered log line.

logger := solislog.NewLogger(
    nil,
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template: "{level} | {message}\n",
        AfterHook: func(record *solislog.Record, msg []byte, successful bool) {
            // Count metrics, inspect the final line, or mirror it elsewhere.
            _ = msg
            _ = successful
        },
    }),
)

When a logger has multiple handlers, each handler gets its own cloned record before running BeforeHook. A hook on one handler does not mutate the record used by another handler. AfterHook and ErrorHandler callbacks run after the logger unlocks its shared core, so hooks can safely log again if needed.

Write error handling

ErrorHandler can be used to observe write errors from a handler's io.Writer.

logger := solislog.NewLogger(
    nil,
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template: "{level} | {message}\n",
        ErrorHandler: func(record *solislog.Record, msg []byte, err error) {
            // Handle or report the write error.
            _ = record
            _ = msg
            _ = err
        },
    }),
)

If ErrorHandler is nil, write errors are ignored.

Multiple handlers

A single logger can write the same record through multiple handlers. Each handler has its own writer, level, template, time settings, and output mode.

logger := solislog.NewLogger(
    solislog.Extra{
        "service": "api",
    },
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template: "<level>{level}</level> | {message}\n",
    }),
    solislog.NewHandler(os.Stdout, solislog.ErrorLevel, &solislog.HandlerOptions{
        Template: "<red>{level}</red> | service={extra[service]} | {message}\n",
    }),
)

logger.Info("server started")
logger.Error("request failed")

The first handler receives INFO and above. The second handler receives only ERROR and above.

Time format and location

Each handler can configure its own time format and location.

loc, err := time.LoadLocation("Europe/Helsinki")
if err != nil {
    panic(err)
}

logger := solislog.NewLogger(
    nil,
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template:   "{time} | {level} | {message}\n",
        TimeFormat: time.DateTime,
        Location:   loc,
    }),
)

logger.Info("hello")

TimeFormat uses Go's standard time layout system.

Defaults:

Template   = "{time} | {level} | {message}\n"
TimeFormat = time.RFC3339
Location   = time.Local
JSON       = false
WithCaller = false

Log levels

Current levels:

  • solislog.DebugLevel
  • solislog.InfoLevel
  • solislog.WarningLevel
  • solislog.ErrorLevel
  • solislog.FatalLevel

A handler writes records whose level is equal to or higher than the handler's configured level.

logger := solislog.NewLogger(
    nil,
    solislog.NewHandler(os.Stdout, solislog.WarningLevel, &solislog.HandlerOptions{
        Template: "<level>{level}</level> | {message}\n",
    }),
)

logger.Info("ignored")
logger.Warning("written")
logger.Error("written")

Fatal(...) logs with FatalLevel and then exits the process with status code 1.

Concurrent use

Logger methods are safe to call from multiple goroutines. A base logger and all loggers created from it with Bind(...) share the same core, so their writes are serialized through that shared core.

logger := solislog.NewLogger(
    nil,
    solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
        Template: "{level} | {message}\n",
    }),
)

go logger.Info("from goroutine 1")
go logger.Info("from goroutine 2")

This guarantee applies to loggers that share the same solislog core. If the same raw io.Writer is manually shared between completely separate logger instances, synchronization of that shared writer is still the caller's responsibility.

Handler options

NewHandler requires an output writer and a level. Everything else is configured through HandlerOptions.

type HandlerOptions struct {
    Template     string
    TimeFormat   string
    Location     *time.Location
    JSON         bool
    WithCaller   bool
    ReadOnly     bool
    ErrorHandler ErrorHandlerFunc
    BeforeHook   BeforeHookFunc
    AfterHook    AfterHookFunc
}

A handler accepts any io.Writer, so file logging, buffers, custom writers, and rotation wrappers can be provided outside of solislog.

handler := solislog.NewHandler(os.Stdout, solislog.InfoLevel, &solislog.HandlerOptions{
    Template:   "{time} | <level>{level}</level> | {message}\n",
    TimeFormat: time.RFC3339,
    Location:   time.Local,
    JSON:       false,
})

Performance

Benchmark Iterations Time/op Memory/op Allocations/op
LoggerInfoText 6 279 595 202.8 ns 144 B 2
LoggerInfoWithExtra 4 314 960 269.7 ns 160 B 2
LoggerInfoJSON 417 164 2 818 ns 921 B 32
LoggerInfoFilteredOut 616 645 734 1.907 ns 0 B 0
LoggerInfoParallel 15 734 155 76.94 ns 144 B 2
BoundLoggerInfo 4 775 455 246.7 ns 160 B 2
LoggerInfoMultipleHandlers 1 248 891 954.8 ns 296 B 11
LoggerInfoLockedWriter 6 340 326 187.0 ns 144 B 2

To regenerate the output yourself, run:

go test -benchmem -bench . ./...

Current limitations

solislog intentionally keeps the core small. Not included in the core package:

  • file rotation helpers
  • framework-specific middleware
  • async logging with queues or workers
  • complex structured field types
  • advanced template formatting or alignment

File rotation can be added through any custom io.Writer. Framework integration can be built on top of Bind(...) and Contextualize(...).

License

MIT License.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AfterHookFunc added in v0.6.0

type AfterHookFunc func(record *Record, msg []byte, successful bool)

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

type ErrorHandlerFunc func(record *Record, msg []byte, err error)

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

type Extra map[string]string

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

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
)

func (Level) String

func (level Level) String() string

String returns the uppercase text representation of the level.

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

func FromContext(ctx context.Context) (*Logger, bool)

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

func NewLogger(defaultExtra Extra, handlers ...Handler) *Logger

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")
}
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`.
}

func (*Logger) AddHandler added in v0.2.0

func (logger *Logger) AddHandler(handler Handler)

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

func (logger *Logger) Bind(extra Extra) *Logger

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

func (logger *Logger) Contextualize(ctx context.Context, extra Extra) context.Context

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

func (*Logger) Debug

func (logger *Logger) Debug(message string)

Debug logs a message at DebugLevel.

func (*Logger) Debugf added in v1.1.1

func (logger *Logger) Debugf(format string, a ...any)

Debugf formats a message using fmt.Sprintf and logs it at DebugLevel.

func (*Logger) Error

func (logger *Logger) Error(message string)

Error logs a message at ErrorLevel.

func (*Logger) Errorf added in v1.1.1

func (logger *Logger) Errorf(format string, a ...any)

Errorf formats a message using fmt.Sprintf and logs it at ErrorLevel.

func (*Logger) Fatal added in v0.2.1

func (logger *Logger) Fatal(message string)

Fatal logs a message at FatalLevel and exits the process with status code 1.

func (*Logger) Fatalf added in v1.1.1

func (logger *Logger) Fatalf(format string, a ...any)

Fatalf formats a message using fmt.Sprintf, logs it at FatalLevel, and exits the process with status code 1.

func (*Logger) Info

func (logger *Logger) Info(message string)

Info logs a message at InfoLevel.

func (*Logger) Infof added in v1.1.1

func (logger *Logger) Infof(format string, a ...any)

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`.
}

func (*Logger) Warning

func (logger *Logger) Warning(message string)

Warning logs a message at WarningLevel.

func (*Logger) Warningf added in v1.1.1

func (logger *Logger) Warningf(format string, a ...any)

Warningf formats a message using fmt.Sprintf and logs it at WarningLevel.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL