log

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 4, 2026 License: Apache-2.0 Imports: 24 Imported by: 43

README

Go-Spring :: Log

English | 中文

The project has been officially released, welcome to use!

Go-Spring :: Log is a high-performance and extensible logging library designed specifically for the Go programming language. It offers flexible and structured logging capabilities, including context field extraction, multi-level logging configuration, and multiple output options, making it ideal for a wide range of server-side applications.

Features

  • Multi-Level Logging: Supports standard log levels such as Trace, Debug, Info, Warn, Error, Panic, and Fatal, suitable for debugging and monitoring in various scenarios.
  • Structured Logging: Records logs in a structured format with key fields like trace_id and span_id, making them easy to parse and analyze by log aggregation systems.
  • Context Integration: Extracts additional information from context.Context (e.g., request ID, user ID) and automatically attaches them to log entries.
  • Tag-Based Logging: Introduces a tag system to distinguish logs across different modules or business lines.
  • Plugin Architecture:
    • Appender: Supports multiple output targets including console and file.
    • Layout: Provides both plain text and JSON formatting for log output.
    • Logger: Offers both synchronous and asynchronous loggers; asynchronous mode avoids blocking the main thread.
  • Performance Optimizations: Utilizes buffer management and event pooling to minimize memory allocation overhead.
  • Dynamic Configuration Reload: Supports runtime reloading of logging configurations from external files.
  • Well-Tested: All core modules are covered with unit tests to ensure stability and reliability.

Core Concepts

Tag

Tag is the core concept in this logging library, used to categorize logs. You can register tag via the RegisterTag function and match them with regular expressions. This approach enables a unified logging API without the need to explicitly create logger instances, even for third-party libraries, allowing them to write logs in a standardized way.

Logger

A Logger is the actual component that processes logs. You can retrieve a logger instance using the GetLogger function, mainly for backward compatibility with older projects. This allows you to fetch a logger by name and use the Write function to record pre-formatted messages.

Contextual Field Extraction

You can configure functions to extract contextual data from context.Context and include them in log entries:

  • StringFromContext: extracts string values from the context (e.g., request ID).
  • FieldsFromContext: returns structured fields from the context, such as trace ID or user ID.

Installation

go get github.com/go-spring/log

Quick Start

Here's a simple example demonstrating how to use Go-Spring :: Log:

package main

import (
	"context"

	"github.com/go-spring/log"
)

func main() {
	// Set the function to extract fields from context.
	// You may also use StringFromContext if only strings are needed.
	log.FieldsFromContext = func(ctx context.Context) []log.Field {
		return []log.Field{
			log.String("trace_id", "0a882193682db71edd48044db54cae88"),
			log.String("span_id", "50ef0724418c0a66"),
		}
	}

	// Load configuration file
	err := log.RefreshFile("log.properties")
	if err != nil {
		panic(err)
	}

	ctx := context.Background()

	// Record logs
	log.Infof(ctx, log.TagAppDef, "This is an info message")
	log.Errorf(ctx, log.TagBizDef, "This is an error message")

    // Log with structured fields
    log.Info(ctx, log.TagAppDef,
        log.String("key1", "value1"),
        log.Int("key2", 123),
        log.Msg("structured log message"),
    )
}

Configuration

Go-Spring :: Log supports defining logging behavior via JSON, or YAML configuration files. For example:

bufferCap=1KB
bufferSize=1000

appender.file.type=File
appender.file.file=log.txt
appender.file.layout.type=JSONLayout

appender.console.type=Console
appender.console.layout.type=TextLayout

logger.root.type=Logger
logger.root.level=warn
logger.root.appenderRef.ref=console

logger.myLogger.type=AsyncLogger
logger.myLogger.level=trace
logger.myLogger.tag=_com_request_in,_com_request_*
logger.myLogger.bufferSize=${bufferSize}
logger.myLogger.appenderRef[0].ref=file

Plugin Development

Go-Spring :: Log offers rich plugin interfaces for developers to easily implement custom Appender, Layout, and Logger components.

License

Go-Spring :: Log is licensed under the Apache License 2.0.

Documentation

Overview

Package log is a high-performance and extensible logging library designed specifically for the Go programming language. It provides flexible and structured logging capabilities, including context field extraction, multi-level logging configuration, and multiple output options, making it ideal for server-side applications.

## Core Concepts:

Tag:

Tag is a core concept in the log package used to categorize logs. By registering a tag via the `RegisterTag` function, you can use regular expressions to match the user-defined tags. This approach allows for a unified API for logging without explicitly creating logger instances. Even third-party libraries can write logs without setting up a logger object.

Loggers:

A Logger is the object that actually handles the logging process. You can obtain a logger instance using the `GetLogger` function, which is mainly provided for compatibility with legacy projects. This allows you to directly retrieve a logger by its name and log pre-formatted messages using the `Write` function.

Context Field Extraction:

Contextual data can be extracted and included in log entries via configurable functions: - `log.StringFromContext`: Extracts a string value (e.g., a request ID) from the context. - `log.FieldsFromContext`: Returns a list of structured fields from the context, such as trace IDs or user IDs.

Configuration from File:

The `log.RefreshFile` function allows loading the logger's configuration from an external file (e.g., yaml or JSON).

Logger Initialization and Logging:

- Using `GetLogger`, you can fetch a logger instance (often for compatibility with older systems). - You can also register custom tags using `RegisterTag` to classify logs according to your needs.

Logging Messages:

The package provides various logging functions, such as `Tracef`, `Debugf`, `Infof`, `Warnf`, etc., which log messages at different levels (e.g., Trace, Debug, Info, Warn). These functions can either accept structured fields or formatted messages.

Structured Logging:

The logger also supports structured logging, where fields are captured as key-value pairs and logged with the message. The fields can be provided directly in the log functions or through a map.

## Examples:

Using a pre-registered tag:

log.Tracef(ctx, TagRequestOut, "hello %s", "world")
log.Debugf(ctx, TagRequestOut, "hello %s", "world")
log.Infof(ctx, TagRequestIn, "hello %s", "world")
log.Warnf(ctx, TagRequestIn, "hello %s", "world")
log.Errorf(ctx, TagRequestIn, "hello %s", "world")
log.Panicf(ctx, TagRequestIn, "hello %s", "world")
log.Fatalf(ctx, TagRequestIn, "hello %s", "world")

Using structured fields:

log.Trace(ctx, TagRequestOut, func() []log.Field {
	return []log.Field{
		log.Msgf("hello %s", "world"),
	}
})

log.Error(ctx, TagRequestIn, log.FieldsFromMap(map[string]any{
	"key1": "value1",
	"key2": "value2",
}))

Index

Constants

View Source
const (
	ValueTypeBool = ValueType(iota)
	ValueTypeInt64
	ValueTypeUint64
	ValueTypeFloat64
	ValueTypeString
	ValueTypeReflect
	ValueTypeArray
	ValueTypeObject
	ValueTypeFromMap
)
View Source
const (
	BufferFullPolicyBlock      = BufferFullPolicy(0) // Block until space is available
	BufferFullPolicyDiscard    = BufferFullPolicy(1) // Drop the new event or data
	BufferFullPolicyDropOldest = BufferFullPolicy(2) // Drop the oldest buffered item
)
View Source
const MsgKey = "msg"
View Source
const RootLoggerName = "root"

RootLoggerName defines the reserved name for the root logger. This is the default logger used when no specific logger is matched.

Variables

View Source
var (

	// TagAppDef is the default tag for application-related logs.
	TagAppDef = RegisterAppTag("def", "")

	// TagBizDef is the default tag for business-related logs.
	TagBizDef = RegisterBizTag("def", "")

	// ReportError is an optional hook function that is invoked whenever an error
	// occurs during logging. It can be overridden to handle error reporting, such as
	// logging the error to a separate error log or sending alerts.
	ReportError = func(err error) {}

	// TimeNow is an optional override function that provides a custom timestamp.
	// It can be replaced during testing or in special cases where a fixed time
	// is required, ensuring consistency in log events across test runs.
	TimeNow func(ctx context.Context) time.Time

	// StringFromContext is an optional hook to extract a string (e.g., trace ID)
	// from the context. This string will be attached to the log event.
	// Avoid performing complex calculations in this function.
	// It's recommended to use cached results for better performance.
	StringFromContext func(ctx context.Context) string

	// FieldsFromContext is an optional hook to extract structured fields
	// (e.g., trace ID, span ID, or request metadata) from the context.
	// Avoid performing complex calculations in this function.
	// It's recommended to use cached results for better performance.
	FieldsFromContext func(ctx context.Context) []Field
)
View Source
var (
	NoneLevel  = RegisterLevel(0, "NONE")    // No logging
	TraceLevel = RegisterLevel(100, "TRACE") // Very detailed logging, typically used for debugging
	DebugLevel = RegisterLevel(200, "DEBUG") // Debugging information useful during development
	InfoLevel  = RegisterLevel(300, "INFO")  // General informational messages about application progress
	WarnLevel  = RegisterLevel(400, "WARN")  // Warnings about potential issues or unusual situations
	ErrorLevel = RegisterLevel(500, "ERROR") // Errors that allow the application to continue running
	PanicLevel = RegisterLevel(600, "PANIC") // Severe issues that may cause a panic in the application
	FatalLevel = RegisterLevel(700, "FATAL") // Critical issues that will terminate the application
	MaxLevel   = RegisterLevel(999, "MAX")   // Maximum level (used as the upper bound for comparisons)
)
View Source
var (

	// Stdout is the standard output stream used by appenders.
	Stdout io.Writer = os.Stdout
)

Functions

func BuildTag added in v0.0.4

func BuildTag(mainType, subType, action string) string

BuildTag constructs a structured tag string from mainType, subType, and an optional action.

The resulting format is:

_<mainType>_<subType>
_<mainType>_<subType>_<action>

Example:

BuildTag("app", "startup", "init") -> "_app_startup_init"

func CloseFile added in v0.1.0

func CloseFile(f *File)

CloseFile decrements the reference count of f. When the count reaches zero, the file is closed.

func Debug

func Debug(ctx context.Context, tag *Tag, fn func() []Field)

Debug logs a message at DebugLevel using a lazy field generator. The generator function is only invoked if the level is enabled.

func Debugf

func Debugf(ctx context.Context, tag *Tag, format string, args ...any)

Debugf logs a formatted message at DebugLevel.

func Destroy added in v0.0.5

func Destroy()

Destroy gracefully shuts down all loggers and appenders, releases resources, and resets global state.

func EncodeFields added in v0.0.10

func EncodeFields(enc Encoder, fields []Field)

EncodeFields encodes a slice of Fields into the Encoder.

func Error

func Error(ctx context.Context, tag *Tag, fields ...Field)

Error logs structured fields at ErrorLevel.

func Errorf

func Errorf(ctx context.Context, tag *Tag, format string, args ...any)

Errorf logs a formatted message at ErrorLevel.

func FastCaller added in v0.1.0

func FastCaller(skip int) (file string, line int)

FastCaller returns the file name and line number of the calling function. It uses a cache to speed up the lookup.

func Fatal

func Fatal(ctx context.Context, tag *Tag, fields ...Field)

Fatal logs structured fields at FatalLevel.

func Fatalf

func Fatalf(ctx context.Context, tag *Tag, format string, args ...any)

Fatalf logs a formatted message at FatalLevel.

func GetAllTags

func GetAllTags() []string

GetAllTags returns the names of all registered tags.

func Info

func Info(ctx context.Context, tag *Tag, fields ...Field)

Info logs structured fields at InfoLevel.

func Infof

func Infof(ctx context.Context, tag *Tag, format string, args ...any)

Infof logs a formatted message at InfoLevel.

func Panic

func Panic(ctx context.Context, tag *Tag, fields ...Field)

Panic logs structured fields at PanicLevel.

func Panicf

func Panicf(ctx context.Context, tag *Tag, format string, args ...any)

Panicf logs a formatted message at PanicLevel.

func ParseHumanizeBytes

func ParseHumanizeBytes(s string) (int, error)

ParseHumanizeBytes parses a size string like "10KB" into bytes. Currently, only the "KB" unit is supported. Returns an error if the format is invalid, the unit is unsupported, or the value exceeds the allowed limit (10MB).

func Record

func Record(ctx context.Context, level Level, tag *Tag, skip int, fields ...Field)

Record logs a message at the given level for the given tag.

func Refresh added in v0.1.0

func Refresh(s flatten.Storage) error

Refresh rebuilds all loggers and appenders from the given configuration storage. It replaces the current runtime configuration atomically.

The process includes:

  1. Parsing logger and appender definitions
  2. Instantiating plugins
  3. Wiring appender references
  4. Starting new components
  5. Swapping in the new configuration
  6. Stopping old components

Returns an error if any step fails.

func RefreshConfig added in v0.0.6

func RefreshConfig(m map[string]string) error

RefreshConfig loads logging configuration from a flat map. It first expands inline expressions, then converts the result into a flatten.Storage and delegates to Refresh.

func RegisterConverter

func RegisterConverter[T any](fn Converter[T])

RegisterConverter registers a custom converter for type T.

func RegisterPlugin

func RegisterPlugin[T any](name string)

RegisterPlugin registers a plugin struct type with a given name and plugin type.

func Trace

func Trace(ctx context.Context, tag *Tag, fn func() []Field)

Trace logs a message at TraceLevel using a lazy field generator. The generator function is only invoked if the level is enabled.

func Tracef

func Tracef(ctx context.Context, tag *Tag, format string, args ...any)

Tracef logs a formatted message at TraceLevel.

func Warn

func Warn(ctx context.Context, tag *Tag, fields ...Field)

Warn logs structured fields at WarnLevel.

func Warnf

func Warnf(ctx context.Context, tag *Tag, format string, args ...any)

Warnf logs a formatted message at WarnLevel.

func WriteEvent added in v0.1.0

func WriteEvent(w io.Writer, e *Event, layout Layout)

WriteEvent writes a log event to the given io.Writer using the specified Layout. If e.RawBytes is not nil, it writes the raw bytes directly. Otherwise, the event is encoded using the layout into a temporary buffer. Any write errors are reported via ReportError.

func WriteLogString

func WriteLogString(out Writer, s string)

WriteLogString escapes and writes a string according to JSON rules.

Types

type Appender

type Appender interface {
	Lifecycle             // Start/Stop methods for resource management
	GetName() string      // Returns the appender's name
	Append(e *Event)      // Handles writing a log event
	ConcurrentSafe() bool // Returns true if the appender is concurrent-safe
}

Appender defines components responsible for writing log events. Implementations should document whether they are safe for concurrent use.

Append MUST NOT modify or retain references to the Event.

type AppenderBase added in v0.0.10

type AppenderBase struct {
	Name   string `PluginAttribute:"name"`
	Layout Layout `PluginElement:"layout,default=TextLayout"`
}

AppenderBase provides common configuration fields for all appenders.

func (*AppenderBase) GetName added in v0.0.10

func (c *AppenderBase) GetName() string

GetName returns the appender's name.

type AppenderRef

type AppenderRef struct {
	Appender
	Ref   string     `PluginAttribute:"ref"`
	Level LevelRange `PluginAttribute:"level,default="`
}

AppenderRef represents a reference to an Appender by name. During configuration loading, the Ref field is resolved and the corresponding Appender instance is injected into the Appender field.

Level optionally restricts the level range forwarded to this appender.

func (*AppenderRef) Append added in v0.1.0

func (c *AppenderRef) Append(e *Event)

Append forwards the event to the referenced appender if the level matches.

type AppenderRefs added in v0.1.0

type AppenderRefs interface {
	// GetAppenderRefs returns the logger's synchronization mode
	// and the list of appender references.
	//
	// In sync mode, appenders may be invoked concurrently by multiple goroutines,
	// so they must ensure thread safety.
	//
	// In async mode, appenders are invoked by a single background goroutine,
	// so they do not require strict thread safety.
	GetAppenderRefs() (syncMode bool, _ []*AppenderRef)
}

AppenderRefs is implemented by loggers that support appender references.

type ArrayValue

type ArrayValue interface {
	EncodeArray(enc Encoder)
}

ArrayValue is an interface for types that can be encoded as array.

type AsyncLogger added in v0.0.4

type AsyncLogger struct {
	LoggerBase
	AppenderRefs []*AppenderRef   `PluginElement:"appenderRef"`
	BufferSize   int              `PluginAttribute:"bufferSize,default=10000"`
	OnBufferFull BufferFullPolicy `PluginAttribute:"onBufferFull,default=discard"`
	// contains filtered or unexported fields
}

AsyncLogger is an asynchronous logger that buffers events in a channel and processes them in a background goroutine.

func (*AsyncLogger) Append added in v0.1.0

func (c *AsyncLogger) Append(e *Event)

Append enqueues a log event into the async buffer. Behavior on full buffer depends on BufferFullPolicy.

func (*AsyncLogger) GetAppenderRefs added in v0.1.0

func (c *AsyncLogger) GetAppenderRefs() (syncMode bool, _ []*AppenderRef)

GetAppenderRefs returns false for async mode and the appender references.

func (*AsyncLogger) GetDiscardCounter added in v0.0.5

func (c *AsyncLogger) GetDiscardCounter() int64

GetDiscardCounter returns the total number of discarded events.

func (*AsyncLogger) Start added in v0.0.4

func (c *AsyncLogger) Start() error

Start initializes the buffer and starts the background worker goroutine.

func (*AsyncLogger) Stop added in v0.0.4

func (c *AsyncLogger) Stop()

Stop gracefully shuts down the AsyncLogger. It guarantees that events already in the buffer before the stop signal are processed before the background worker goroutine exits.

type BaseLayout

type BaseLayout struct {
	FileLineMaxLength int `PluginAttribute:"fileLineMaxLength,default=48"`
}

BaseLayout provides common utilities for layouts, e.g., file:line formatting.

func (*BaseLayout) GetFileLine

func (c *BaseLayout) GetFileLine(e *Event) string

GetFileLine returns the "file:line" string for a log event. If the result exceeds FileLineMaxLength, the leading part is truncated and replaced with "...".

type BufferFullPolicy added in v0.0.5

type BufferFullPolicy int

BufferFullPolicy specifies how AsyncLogger behaves when its buffer is full.

func ParseBufferFullPolicy added in v0.0.5

func ParseBufferFullPolicy(s string) (BufferFullPolicy, error)

ParseBufferFullPolicy converts a string to a BufferFullPolicy.

type CallerType added in v0.1.0

type CallerType int

CallerType defines the type of caller information to retrieve.

const (
	// CallerTypeDefault indicates that the caller information should be retrieved
	// using the default method.
	CallerTypeDefault CallerType = iota

	// CallerTypeFast indicates that the caller information should be retrieved
	// using a faster but less accurate method.
	CallerTypeFast

	// CallerTypeNone indicates that no caller information should be retrieved.
	CallerTypeNone
)

func ParseCallerType added in v0.1.0

func ParseCallerType(s string) (CallerType, error)

ParseCallerType parses a string representation of a CallerType and returns the corresponding value.

type ConsoleAppender

type ConsoleAppender struct {
	AppenderBase
}

ConsoleAppender writes formatted log events to standard output.

func (*ConsoleAppender) Append

func (c *ConsoleAppender) Append(e *Event)

Append formats the event and writes it to standard output.

func (*ConsoleAppender) ConcurrentSafe added in v0.1.0

func (c *ConsoleAppender) ConcurrentSafe() bool

func (*ConsoleAppender) Start added in v0.1.0

func (c *ConsoleAppender) Start() error

func (*ConsoleAppender) Stop added in v0.1.0

func (c *ConsoleAppender) Stop()

type ConsoleLogger added in v0.1.0

type ConsoleLogger struct {
	LoggerBase

	Layout Layout `PluginElement:"layout,default=TextLayout"`
	// contains filtered or unexported fields
}

ConsoleLogger writes log events to standard output.

func (*ConsoleLogger) Append added in v0.1.0

func (c *ConsoleLogger) Append(e *Event)

Append writes the event to the console if its level is enabled.

func (*ConsoleLogger) Start added in v0.1.0

func (c *ConsoleLogger) Start() error

Start initializes the console appender and starts it.

func (*ConsoleLogger) Stop added in v0.1.0

func (c *ConsoleLogger) Stop()

Stop stops the console appender manually.

type Converter

type Converter[T any] func(string) (T, error)

Converter defines a function that converts a string to type T.

type DiscardAppender

type DiscardAppender struct {
	AppenderBase
}

DiscardAppender ignores all log events (no-op).

func (*DiscardAppender) Append added in v0.1.0

func (c *DiscardAppender) Append(e *Event)

func (*DiscardAppender) ConcurrentSafe added in v0.1.0

func (c *DiscardAppender) ConcurrentSafe() bool

func (*DiscardAppender) Start added in v0.1.0

func (c *DiscardAppender) Start() error

func (*DiscardAppender) Stop added in v0.1.0

func (c *DiscardAppender) Stop()

type DiscardLogger added in v0.1.0

type DiscardLogger struct {
	LoggerBase
}

DiscardLogger ignores all log events (no-op).

func (DiscardLogger) Append added in v0.1.0

func (d DiscardLogger) Append(e *Event)

func (DiscardLogger) Start added in v0.1.0

func (d DiscardLogger) Start() error

func (DiscardLogger) Stop added in v0.1.0

func (d DiscardLogger) Stop()

type Encoder

type Encoder interface {
	AppendEncoderBegin()
	AppendEncoderEnd()
	AppendObjectBegin()
	AppendObjectEnd()
	AppendArrayBegin()
	AppendArrayEnd()
	AppendKey(key string)
	AppendBool(v bool)
	AppendInt64(v int64)
	AppendUint64(v uint64)
	AppendFloat64(v float64)
	AppendString(v string)
	AppendReflect(v any)
}

Encoder defines the interface for structured logging encoders. Implementations control how log fields are serialized (e.g. JSON, text).

type Event

type Event struct {
	Level     Level     // The severity level of the log (e.g., INFO, ERROR, DEBUG)
	Time      time.Time // The timestamp when the event occurred
	File      string    // The source file where the log was triggered
	Line      int       // The line number in the source file
	Tag       string    // A tag used to categorize the log (e.g., subsystem name)
	Fields    []Field   // Custom fields provided specifically for this log event
	CtxString string    // String representation extracted from the context (e.g., trace ID)
	CtxFields []Field   // Additional structured fields extracted from the context (e.g., request ID, user ID)
	RawBytes  []byte    // Raw data, only used for Write operations, mutually exclusive with other fields
}

Event represents a single log entry. It contains both the log message context (e.g., time, file, line, tag) and structured metadata (fields and context values).

func (*Event) Reset

func (e *Event) Reset()

Reset clears the fields of the Event and returns it to the pool.

type Field

type Field struct {

	// The name of the field (e.g., "level", "message").
	Key string

	// The type of the value stored in the field (e.g., bool, int, string, etc.).
	Type ValueType

	// For numeric types, it stores the actual value.
	// For strings and arrays, it stores the length or relevant metadata.
	Num uint64

	// Holds the actual value based on the type:
	// - For strings, it stores a pointer to the string data.
	// - For arrays, it stores the slice of array elements.
	// - For other types, it stores the value directly.
	Any any
}

Field represents a structured log field with a key and a typed value.

func Any

func Any(key string, value any) Field

Any creates a Field from a value of any type by inspecting its dynamic type. It dispatches to the appropriate typed constructor based on the actual value. If the type is not explicitly handled, it falls back to using Reflect.

func Array

func Array(key string, val ArrayValue) Field

Array creates a Field with array type, using the ArrayValue interface.

func Bool

func Bool(key string, val bool) Field

Bool creates a Field for a boolean value.

func BoolPtr

func BoolPtr(key string, val *bool) Field

BoolPtr creates a Field from a *bool, or Nil if pointer is nil.

func Bools

func Bools(key string, val []bool) Field

Bools creates a Field with a slice of booleans.

func FieldsFromMap added in v0.0.4

func FieldsFromMap(m map[string]any) Field

FieldsFromMap creates a special Field that wraps a map[string]any. When encoded, it expands the map into individual key-value fields. This allows existing map structures to be easily converted into log fields without manually iterating through the map and adding each field individually.

func Float

func Float[T FloatType](key string, val T) Field

Float creates a Field for a float value.

func FloatPtr

func FloatPtr[T FloatType](key string, val *T) Field

FloatPtr creates a Field from a *float, or Nil if pointer is nil.

func Floats

func Floats[T FloatType](key string, val []T) Field

Floats creates a Field with a slice of float32 values.

func Int

func Int[T IntType](key string, val T) Field

Int creates a Field for an integer value.

func IntPtr

func IntPtr[T IntType](key string, val *T) Field

IntPtr creates a Field from a *int, or Nil if pointer is nil.

func Ints

func Ints[T IntType](key string, val []T) Field

Ints creates a Field with a slice of integers.

func Msg

func Msg(msg string) Field

Msg creates a string Field with the fixed key "msg".

func Msgf

func Msgf(format string, args ...any) Field

Msgf formats a message and creates a Field with the fixed key "msg".

func Nil

func Nil(key string) Field

Nil creates a Field whose value is nil (Type = ValueTypeReflect).

func Object

func Object(key string, fields ...Field) Field

Object creates a Field containing a variadic slice of Fields, treated as a nested object.

func Reflect

func Reflect(key string, val any) Field

Reflect wraps any value into a Field using reflection.

func String

func String(key string, val string) Field

String creates a Field for a string value.

func StringPtr

func StringPtr(key string, val *string) Field

StringPtr creates a Field from a *string, or Nil if pointer is nil.

func Strings

func Strings(key string, val []string) Field

Strings creates a Field with a slice of strings.

func Uint

func Uint[T UintType](key string, val T) Field

Uint creates a Field for an unsigned integer value.

func UintPtr

func UintPtr[T UintType](key string, val *T) Field

UintPtr creates a Field from a *uint, or Nil if pointer is nil.

func Uints

func Uints[T UintType](key string, val []T) Field

Uints creates a Field with a slice of unsigned integers.

func (Field) Encode

func (f Field) Encode(enc Encoder)

Encode encodes the Field into the Encoder based on its type.

type File added in v0.1.0

type File struct {
	// contains filtered or unexported fields
}

File is a reference-counted wrapper around *os.File. The underlying file must not be used directly. Use Write to perform writes.

func OpenFile added in v0.1.0

func OpenFile(name string) (*File, error)

OpenFile returns a shared File for the given name. If the file is already open, its reference count is increased. Otherwise, the file is opened and tracked.

func (*File) Name added in v0.1.0

func (f *File) Name() string

Name returns the name of the file.

func (*File) Write added in v0.1.0

func (f *File) Write(p []byte) (int, error)

Write writes to the file.

type FileAppender

type FileAppender struct {
	AppenderBase

	FileDir  string `PluginAttribute:"dir,default=./logs"`
	FileName string `PluginAttribute:"file"`
	// contains filtered or unexported fields
}

FileAppender writes formatted log events to a file in append mode.

func (*FileAppender) Append

func (c *FileAppender) Append(e *Event)

Append formats the log event and writes it to the file.

func (*FileAppender) ConcurrentSafe added in v0.1.0

func (c *FileAppender) ConcurrentSafe() bool

func (*FileAppender) Start

func (c *FileAppender) Start() error

Start opens the log file for appending.

func (*FileAppender) Stop

func (c *FileAppender) Stop()

Stop flushes and closes the file.

type FileLogger added in v0.1.0

type FileLogger struct {
	LoggerBase
	Layout   Layout `PluginElement:"layout,default=TextLayout"`
	FileDir  string `PluginAttribute:"dir,default=./logs"`
	FileName string `PluginAttribute:"file"`
	// contains filtered or unexported fields
}

FileLogger writes log events to a file.

func (*FileLogger) Append added in v0.1.0

func (c *FileLogger) Append(e *Event)

Append writes the log event to the file if its level is enabled.

func (*FileLogger) Start added in v0.1.0

func (c *FileLogger) Start() error

Start initializes the file appender and starts it.

func (*FileLogger) Stop added in v0.1.0

func (c *FileLogger) Stop()

Stop stops the file appender manually.

type FloatType

type FloatType interface {
	~float32 | ~float64
}

FloatType is the type of float32, float64.

type IntType

type IntType interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64
}

IntType is the type of int, int8, int16, int32, int64.

type JSONEncoder

type JSONEncoder struct {
	// contains filtered or unexported fields
}

JSONEncoder encodes log fields into standard JSON format.

func NewJSONEncoder

func NewJSONEncoder(out Writer) *JSONEncoder

NewJSONEncoder creates a new JSONEncoder.

func (*JSONEncoder) AppendArrayBegin

func (enc *JSONEncoder) AppendArrayBegin()

AppendArrayBegin writes the beginning of a JSON array.

func (*JSONEncoder) AppendArrayEnd

func (enc *JSONEncoder) AppendArrayEnd()

AppendArrayEnd writes the end of a JSON array.

func (*JSONEncoder) AppendBool

func (enc *JSONEncoder) AppendBool(v bool)

AppendBool writes a boolean value.

func (*JSONEncoder) AppendEncoderBegin

func (enc *JSONEncoder) AppendEncoderBegin()

AppendEncoderBegin writes the start of an encoder section.

func (*JSONEncoder) AppendEncoderEnd

func (enc *JSONEncoder) AppendEncoderEnd()

AppendEncoderEnd writes the end of an encoder section.

func (*JSONEncoder) AppendFloat64

func (enc *JSONEncoder) AppendFloat64(v float64)

AppendFloat64 writes a float64 value.

func (*JSONEncoder) AppendInt64

func (enc *JSONEncoder) AppendInt64(v int64)

AppendInt64 writes an int64 value.

func (*JSONEncoder) AppendKey

func (enc *JSONEncoder) AppendKey(key string)

AppendKey writes a JSON key.

func (*JSONEncoder) AppendObjectBegin

func (enc *JSONEncoder) AppendObjectBegin()

AppendObjectBegin writes the beginning of a JSON object.

func (*JSONEncoder) AppendObjectEnd

func (enc *JSONEncoder) AppendObjectEnd()

AppendObjectEnd writes the end of a JSON object.

func (*JSONEncoder) AppendReflect

func (enc *JSONEncoder) AppendReflect(v any)

AppendReflect marshals any Go value to JSON and writes it. If marshalling fails, the error message is written as a string.

func (*JSONEncoder) AppendString

func (enc *JSONEncoder) AppendString(v string)

AppendString writes a string value with proper escaping.

func (*JSONEncoder) AppendUint64

func (enc *JSONEncoder) AppendUint64(u uint64)

AppendUint64 writes an uint64 value.

func (*JSONEncoder) Reset

func (enc *JSONEncoder) Reset()

Reset resets the encoder's state.

type JSONLayout

type JSONLayout struct {
	BaseLayout
}

JSONLayout encodes a log event as a structured JSON object.

func (*JSONLayout) EncodeTo added in v0.1.0

func (c *JSONLayout) EncodeTo(e *Event, w Writer)

EncodeTo writes the log event to the provided writer in JSON format.

type JSONTokenType added in v0.0.10

type JSONTokenType int

JSONTokenType represents the type of the last token written to JSONEncoder. It is used to determine when separators (commas) are required.

const (
	JSONTokenUnknown JSONTokenType = iota
	JSONTokenObjectBegin
	JSONTokenObjectEnd
	JSONTokenArrayBegin
	JSONTokenArrayEnd
	JSONTokenKey
	JSONTokenValue
)

type Layout

type Layout interface {
	EncodeTo(e *Event, w Writer)
}

Layout defines how a log event is encoded into a writer. Implementations should write fully formatted log data to `w`. Layouts do NOT manage memory or buffering; callers are responsible.

type Level

type Level struct {
	// contains filtered or unexported fields
}

Level represents a logging severity level. Each level has a numeric code (for comparison) and a string name (for display).

func RegisterLevel added in v0.0.6

func RegisterLevel(code int32, name string) Level

RegisterLevel defines a new logging Level with the given code and name. The name is normalized to uppercase and stored in a global registry for lookup.

It must be called during initialization only and is not safe for concurrent use. It panics if the same name is registered with a different code.

Multiple names may share the same code (aliases). Such levels are considered equivalent in comparisons (by code), but remain distinct values.

func (Level) Code added in v0.0.6

func (l Level) Code() int32

Code returns the numeric code of the Level. Levels with higher codes represent higher severity.

func (Level) LowerName added in v0.1.0

func (l Level) LowerName() string

LowerName returns the lowercase name of the Level.

func (Level) UpperName added in v0.1.0

func (l Level) UpperName() string

UpperName returns the uppercase name of the Level.

type LevelRange added in v0.1.0

type LevelRange struct {
	MinLevel Level
	MaxLevel Level
}

LevelRange represents a range of log levels [MinLevel, MaxLevel).

func ParseLevelRange added in v0.1.0

func ParseLevelRange(s string) (LevelRange, error)

ParseLevelRange parses a string into a LevelRange.

Supported formats:

""           → [NONE, MAX)
"INFO"       → [INFO, MAX)
"INFO~ERROR" → [INFO, ERROR)

The comparison is case-insensitive. Returns an error for unknown levels.

func (LevelRange) Enable added in v0.1.0

func (c LevelRange) Enable(l Level) bool

Enable returns true if the given Level 'l' falls within the LevelRange. The check is inclusive of MinLevel and exclusive of MaxLevel.

type Lifecycle

type Lifecycle interface {
	Start() error
	Stop()
}

Lifecycle is an optional interface for plugin lifecycle hooks.

type Logger

type Logger interface {
	Lifecycle             // Start/Stop methods for resource management
	GetName() string      // Appender's name
	GetTags() []string    // Tags associated with this logger
	GetLevel() LevelRange // Level range handled by this logger
	Append(e *Event)      // Handles writing a log event
}

Logger is the interface implemented by all logger implementations. A Logger receives log events and forwards them to one or more appenders.

type LoggerBase added in v0.0.10

type LoggerBase struct {
	Name  string     `PluginAttribute:"name"`           // Logger name
	Tags  []string   `PluginAttribute:"tag,default=*"`  // Optional tags associated with this logger
	Level LevelRange `PluginAttribute:"level,default="` // Level range handled by this logger
}

LoggerBase contains fields shared by all logger configurations.

func (*LoggerBase) GetLevel added in v0.1.0

func (c *LoggerBase) GetLevel() LevelRange

func (*LoggerBase) GetName added in v0.0.10

func (c *LoggerBase) GetName() string

func (*LoggerBase) GetTags added in v0.1.0

func (c *LoggerBase) GetTags() []string

type LoggerWrapper added in v0.0.4

type LoggerWrapper struct {
	// contains filtered or unexported fields
}

LoggerWrapper wraps a Logger instance and allows atomic replacement of the underlying Logger at runtime. This ensures that concurrent readers always see a consistent Logger reference without needing locks.

func GetLogger added in v0.0.4

func GetLogger(name string) *LoggerWrapper

GetLogger retrieves an existing LoggerWrapper by name, or creates a new one if it does not exist yet. This function must be called only during the initialization phase.

func (*LoggerWrapper) Enable added in v0.1.0

func (m *LoggerWrapper) Enable(l Level) bool

Enable returns true if the given Level 'l' is enabled for this Logger. The check is inclusive of MinLevel and exclusive of MaxLevel.

func (*LoggerWrapper) Write added in v0.0.4

func (m *LoggerWrapper) Write(level Level, b []byte)

Write forwards the given byte slice to the currently active Logger with the specified level.

type Plugin

type Plugin struct {
	Name  string       // Name of the plugin
	Class reflect.Type // Underlying struct type
	File  string       // File where plugin was registered
	Line  int          // Line number where plugin was registered
}

Plugin represents metadata about a plugin type.

type PluginTag

type PluginTag string

PluginTag is a wrapper for parsing struct field tags.

func (PluginTag) Get

func (tag PluginTag) Get(key string) string

Get returns the value for a key or the first unnamed value.

func (PluginTag) Lookup

func (tag PluginTag) Lookup(key string) (value string, ok bool)

Lookup returns the value of a key in a tag and a boolean indicating existence.

type RollingFileAppender added in v0.1.0

type RollingFileAppender struct {
	AppenderBase

	FileDir  string        `PluginAttribute:"dir,default=./logs"`
	FileName string        `PluginAttribute:"file"`
	Interval time.Duration `PluginAttribute:"interval,default=1h"`
	MaxAge   time.Duration `PluginAttribute:"maxAge,default=168h"`
	SyncLock bool          `PluginAttribute:"syncLock,default=false"`
	// contains filtered or unexported fields
}

RollingFileAppender writes log events to files that rotate at fixed time intervals. It is safe for concurrent use only when Lock is true. If Lock is false, callers must ensure serialized access (e.g., via an async logger).

func (*RollingFileAppender) Append added in v0.1.0

func (c *RollingFileAppender) Append(e *Event)

Append formats the log event and writes it to the current file.

func (*RollingFileAppender) ConcurrentSafe added in v0.1.0

func (c *RollingFileAppender) ConcurrentSafe() bool

func (*RollingFileAppender) Start added in v0.1.0

func (c *RollingFileAppender) Start() error

Start opens the initial log file and prepares for rotation.

func (*RollingFileAppender) Stop added in v0.1.0

func (c *RollingFileAppender) Stop()

Stop flushes and closes the current file.

type RollingFileLogger added in v0.1.0

type RollingFileLogger struct {
	LoggerBase

	// Layout used to format log events.
	Layout Layout `PluginElement:"layout,default=TextLayout"`

	// Directory where log files are stored.
	// Defaults to "./logs".
	FileDir string `PluginAttribute:"dir,default=./logs"`

	// Base name of the log file.
	// Actual file names may include rotation suffixes.
	FileName string `PluginAttribute:"file"`

	// If true, warning and error logs are written to a separate file
	// with ".wf" suffix (e.g. app.log.wf).
	//
	// In this mode:
	//   - normal log file contains levels < WARN
	//   - ".wf" file contains WARN and above
	Separate bool `PluginAttribute:"separate,default=false"`

	// Rotation interval for log files.
	// A new file is created after each interval (e.g. 1h, 24h).
	Interval time.Duration `PluginAttribute:"interval,default=1h"`

	// Maximum retention duration for old log files.
	// Files older than this duration will be automatically removed.
	MaxAge time.Duration `PluginAttribute:"maxAge,default=168h"`

	// Whether to enable asynchronous logging.
	AsyncWrite bool `PluginAttribute:"async,default=false"`

	// Size of the buffer used in async mode.
	// Ignored if AsyncWrite is false.
	BufferSize int `PluginAttribute:"bufferSize,default=10000"`

	// Behavior when async buffer is full.
	// Ignored if AsyncWrite is false.
	OnBufferFull BufferFullPolicy `PluginAttribute:"onBufferFull,default=discard"`
	// contains filtered or unexported fields
}

RollingFileLogger writes log events to files with time-based rotation and optional level-based separation. It supports both synchronous and asynchronous modes.

func (*RollingFileLogger) Append added in v0.1.0

func (f *RollingFileLogger) Append(e *Event)

Append forwards the log event to the internal logger.

func (*RollingFileLogger) Start added in v0.1.0

func (f *RollingFileLogger) Start() error

Start initializes the internal logger and configures rolling file appenders. Depending on AsyncWrite, either SyncLogger or AsyncLogger will be used.

func (*RollingFileLogger) Stop added in v0.1.0

func (f *RollingFileLogger) Stop()

Stop stops all appenders managed by this logger and gracefully shuts down the logger.

type RollingFileWriter added in v0.1.0

type RollingFileWriter struct {
	// contains filtered or unexported fields
}

RollingFileWriter is the low-level sequential writer. It is NOT safe for concurrent use; synchronization is the responsibility of the caller/appender.

func (*RollingFileWriter) Close added in v0.1.0

func (w *RollingFileWriter) Close()

Close closes the current file.

func (*RollingFileWriter) Rotate added in v0.1.0

func (w *RollingFileWriter) Rotate() (*File, error)

Rotate creates a new log file if the current time exceeds the rotation interval. It returns the active file for writing. The previous file is closed asynchronously after a delay. This method is not concurrency-safe.

type SyncLogger added in v0.0.4

type SyncLogger struct {
	LoggerBase
	AppenderRefs []*AppenderRef `PluginElement:"appenderRef"`
}

SyncLogger is a synchronous logger that forwards events to appenders immediately in the caller goroutine.

func (*SyncLogger) Append added in v0.1.0

func (c *SyncLogger) Append(e *Event)

Append sends the event directly to appenders.

func (*SyncLogger) GetAppenderRefs added in v0.1.0

func (c *SyncLogger) GetAppenderRefs() (syncMode bool, _ []*AppenderRef)

GetAppenderRefs returns true for sync mode and the appender refs.

func (*SyncLogger) Start added in v0.0.4

func (c *SyncLogger) Start() error

func (*SyncLogger) Stop added in v0.0.4

func (c *SyncLogger) Stop()

type Tag

type Tag struct {
	// contains filtered or unexported fields
}

Tag represents a named log tag, used to categorize logs by subsystem, business domain, RPC interaction, and so on. Each Tag maintains a reference to a Logger instance.

func RegisterAppTag added in v0.0.4

func RegisterAppTag(subType, action string) *Tag

RegisterAppTag registers or retrieves a Tag intended for application-layer logs, which are typically used to log events related to the application lifecycle, such as startup, shutdown, or health checks.

  • subType: component or module name
  • action: lifecycle phase or behavior (optional)

func RegisterBizTag added in v0.0.4

func RegisterBizTag(subType, action string) *Tag

RegisterBizTag registers or retrieves a Tag intended for business-logic logs.

  • subType: business domain or feature name
  • action: operation being logged (optional)

func RegisterRPCTag added in v0.0.4

func RegisterRPCTag(subType, action string) *Tag

RegisterRPCTag registers or retrieves a Tag intended for RPC logs, covering external/internal dependency interactions.

  • subType: protocol or target system (e.g., http, grpc, redis)
  • action: RPC phase (e.g., send, retry, fail)

func RegisterTag added in v0.0.4

func RegisterTag(tag string) *Tag

RegisterTag retrieves or creates a Tag by name. If the tag is not yet registered, a new Tag is created and initialized.

This function must be called during initialization. It panics if invoked after the logging system has been refreshed (i.e., when global.refreshed is already set).

Normally, higher-level helpers such as RegisterAppTag, RegisterBizTag, or RegisterRPCTag should be used to enforce semantic consistency.

type TextEncoder

type TextEncoder struct {
	// contains filtered or unexported fields
}

TextEncoder encodes fields as "key=value" pairs separated by a delimiter. For nested objects and arrays, it delegates to the embedded JSONEncoder.

func NewTextEncoder

func NewTextEncoder(out Writer, separator string) *TextEncoder

NewTextEncoder creates a new TextEncoder, using the specified separator.

func (*TextEncoder) AppendArrayBegin

func (enc *TextEncoder) AppendArrayBegin()

AppendArrayBegin signals the start of a JSON array. Increments the depth and delegates to the JSON encoder.

func (*TextEncoder) AppendArrayEnd

func (enc *TextEncoder) AppendArrayEnd()

AppendArrayEnd signals the end of a JSON array. Decrements the depth and resets the JSON encoder if back to top level.

func (*TextEncoder) AppendBool

func (enc *TextEncoder) AppendBool(v bool)

AppendBool appends a boolean value, using JSON encoder if nested.

func (*TextEncoder) AppendEncoderBegin

func (enc *TextEncoder) AppendEncoderBegin()

AppendEncoderBegin writes the start of an encoder section.

func (*TextEncoder) AppendEncoderEnd

func (enc *TextEncoder) AppendEncoderEnd()

AppendEncoderEnd writes the end of an encoder section.

func (*TextEncoder) AppendFloat64

func (enc *TextEncoder) AppendFloat64(v float64)

AppendFloat64 appends a float64 value, using JSON encoder if nested.

func (*TextEncoder) AppendInt64

func (enc *TextEncoder) AppendInt64(v int64)

AppendInt64 appends an int64 value, using JSON encoder if nested.

func (*TextEncoder) AppendKey

func (enc *TextEncoder) AppendKey(key string)

AppendKey appends a key for a key-value pair. If inside a JSON structure, the key is handled by the JSON encoder. Otherwise, it's written directly with proper separator handling.

func (*TextEncoder) AppendObjectBegin

func (enc *TextEncoder) AppendObjectBegin()

AppendObjectBegin signals the start of a JSON object. Increments the depth and delegates to the JSON encoder.

func (*TextEncoder) AppendObjectEnd

func (enc *TextEncoder) AppendObjectEnd()

AppendObjectEnd signals the end of a JSON object. Decrements the depth and resets the JSON encoder if back to top level.

func (*TextEncoder) AppendReflect

func (enc *TextEncoder) AppendReflect(v any)

AppendReflect uses reflection to marshal any value as JSON. If nested, delegates to JSON encoder.

func (*TextEncoder) AppendString

func (enc *TextEncoder) AppendString(v string)

AppendString appends a string value, using JSON encoder if nested.

func (*TextEncoder) AppendUint64

func (enc *TextEncoder) AppendUint64(v uint64)

AppendUint64 appends a uint64 value, using JSON encoder if nested.

type TextLayout

type TextLayout struct {
	BaseLayout
}

TextLayout encodes a log event as a human-readable text line.

func (*TextLayout) EncodeTo added in v0.1.0

func (c *TextLayout) EncodeTo(e *Event, w Writer)

EncodeTo writes the log event to the provided writer in plain-text format.

type UintType

type UintType interface {
	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

UintType is the type of uint, uint8, uint16, uint32, uint64.

type ValueType

type ValueType int

ValueType represents the underlying type stored in a Field. The Type determines how Num and Any should be interpreted.

type Writer added in v0.1.0

type Writer interface {
	io.Writer
	io.ByteWriter
	io.StringWriter
}

Writer defines the interface for writing raw data.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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