logger

package
v0.25.3 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2026 License: MIT Imports: 11 Imported by: 0

README

UniRTM Logger

Enhanced zerolog-based logging system for UniRTM with rotating file writers, structured logging, and automatic stack trace capture.

Features

  • Multiple Log Levels: Trace, Debug, Info, Warn, Error, Fatal, Panic
  • Rotating File Writers: Automatic log rotation for both operation and error logs
    • Max size: 500MB per file
    • Max backups: 10 files
    • Max age: 30 days
    • Automatic compression of rotated files
  • Structured Logging: Support for context fields and key-value pairs
  • Stack Trace Capture: Automatic stack trace capture for error-level logs
  • Console Output: Color-coded log levels for better readability
  • Dual Output: Logs written to both files and console (stdout/stderr)

Configuration

Log Files
  • unirtm.log: All operation logs (Trace, Debug, Info, Warn, Error, Fatal, Panic)
  • error.log: Error-level logs only (Error, Fatal, Panic) with stack traces
Rotation Settings
MaxSize:    500  // megabytes
MaxBackups: 10   // number of old log files to retain
MaxAge:     30   // days
Compress:   true // compress rotated files

Usage

Initialization
import "github.com/snowdreamtech/unirtm/internal/pkg/logger"

// Initialize with default paths (unirtm.log and error.log)
opWriter, errWriter := logger.InitUniRTMLogger("", "")

// Initialize with custom paths
opWriter, errWriter := logger.InitUniRTMLogger("/var/log/unirtm/unirtm.log", "/var/log/unirtm/error.log")
Basic Logging
// Simple log messages
logger.Trace("trace message")
logger.Debug("debug message")
logger.Info("info message")
logger.Warn("warning message")
logger.Error("error message")  // Automatically captures stack trace
logger.Fatal("fatal message")  // Logs and exits
logger.Panic("panic message")  // Logs and panics
Structured Logging with Context
// Log with context fields
logger.Info("Tool installed", map[string]interface{}{
    "tool":    "node",
    "version": "20.0.0",
    "path":    "/usr/local/bin/node",
})

logger.Error("Installation failed", map[string]interface{}{
    "tool":    "python",
    "version": "3.11.0",
    "reason":  "checksum mismatch",
})
Logging Errors with Error Objects
err := errors.New("network timeout")

// Log error with message
logger.ErrorWithErr(err, "Failed to download artifact")

// Log error with context fields
logger.ErrorWithErr(err, "Download failed", map[string]interface{}{
    "url":     "https://example.com/artifact.tar.gz",
    "retries": 5,
    "timeout": "30s",
})
Creating Loggers with Context
// Create a logger with context fields
contextLogger := logger.WithContext(map[string]interface{}{
    "request_id": "req-123456",
    "user_id":    "user-789",
    "operation":  "install",
})

// All logs from this logger will include the context fields
contextLogger.Info().Msg("Starting installation")
contextLogger.Debug().Msg("Downloading artifact")
contextLogger.Info().Msg("Installation completed")
Creating Loggers with Variadic Fields
// Create a logger with key-value pairs
fieldsLogger := logger.WithFields(
    "tool", "go",
    "version", "1.21.0",
    "backend", "github",
)

// All logs from this logger will include these fields
fieldsLogger.Info().Msg("Tool resolved")
fieldsLogger.Debug().Msg("Downloading from GitHub")
fieldsLogger.Info().Msg("Installation successful")
Using the Global Logger Directly
// Access the global logger for advanced usage
logger.Logger.Info().
    Str("tool", "node").
    Str("version", "20.0.0").
    Int("size_mb", 45).
    Msg("Download completed")

logger.Logger.Error().
    Err(err).
    Str("operation", "install").
    Msg("Operation failed")

Integration with Error Handling

The logger integrates seamlessly with the UniRTM error handling system:

import (
    "github.com/snowdreamtech/unirtm/internal/pkg/errors"
    "github.com/snowdreamtech/unirtm/internal/pkg/logger"
)

// Create a categorized error
err := errors.NewUserError("invalid version specification", nil)

// Log the error with its category
logger.ErrorWithErr(err, "Configuration validation failed", map[string]interface{}{
    "category": errors.GetCategory(err).String(),
    "file":     ".unirtm.toml",
})

Log Output Format

Console Output (Human-Readable)
2026-05-06T13:00:00+08:00 INF logger.go:456 > Tool installed tool=node version=20.0.0 path=/usr/local/bin/node
2026-05-06T13:00:01+08:00 ERR logger.go:477 > Installation failed tool=python version=3.11.0 reason="checksum mismatch" stack_trace="goroutine 1 [running]:\n..."
File Output (JSON)
{
  "level": "info",
  "time": "2026-05-06T13:00:00+08:00",
  "caller": "/path/to/file.go:123",
  "message": "Tool installed",
  "tool": "node",
  "version": "20.0.0",
  "path": "/usr/local/bin/node"
}

{
  "level": "error",
  "time": "2026-05-06T13:00:01+08:00",
  "caller": "/path/to/file.go:456",
  "message": "Installation failed",
  "tool": "python",
  "version": "3.11.0",
  "reason": "checksum mismatch",
  "stack_trace": "goroutine 1 [running]:\n..."
}

Requirements Validation

This implementation satisfies the following UniRTM requirements:

  • Requirement 7.1: Multiple log levels (Trace, Debug, Info, Warn, Error, Fatal, Panic)
  • Requirement 7.2: Rotating file writers for unirtm.log (max 500MB, 10 backups, 30 days retention)
  • Requirement 7.3: Rotating file writers for error.log (max 500MB, 10 backups, 30 days retention)
  • Requirement 7.4: Structured logging with context fields
  • Requirement 7.5: Timestamps, log levels, and structured context in all log entries
  • Requirement 7.7: Stack trace capture for errors
  • Requirement 7.8: Integration with audit logging system (via structured fields)

Testing

Run the test suite:

go test -v ./internal/pkg/logger/...

Run specific tests:

go test -v -run TestInitUniRTMLogger ./internal/pkg/logger/...
go test -v -run TestLogLevels ./internal/pkg/logger/...
go test -v -run TestErrorWithErr ./internal/pkg/logger/...

Performance Considerations

  • Buffered I/O: Lumberjack uses buffered I/O for efficient file writes
  • Lazy File Creation: Log files are created only when first written to
  • Compression: Rotated log files are automatically compressed to save disk space
  • Minimal Overhead: Zerolog is one of the fastest structured logging libraries for Go
  • Stack Trace Caching: Stack traces are captured only for error-level logs

Best Practices

  1. Initialize Early: Call InitUniRTMLogger() at application startup
  2. Use Structured Logging: Always include relevant context fields
  3. Avoid Sensitive Data: Never log passwords, tokens, or PII
  4. Use Appropriate Levels:
    • Trace: Very detailed debugging information
    • Debug: Debugging information
    • Info: General informational messages
    • Warn: Warning messages for potentially harmful situations
    • Error: Error messages for failures that don't stop the application
    • Fatal: Critical errors that cause application exit
    • Panic: Critical errors that cause panic
  5. Context Propagation: Use WithContext() or WithFields() to create loggers with persistent context
  6. Error Wrapping: Use ErrorWithErr() to log errors with their full context

Migration from Existing Logger

The enhanced logger maintains backward compatibility with the existing InitLogger() function for Gin integration. New code should use InitUniRTMLogger() for full UniRTM functionality.

// Old (Gin-specific)
errorWriter, ginWriter := logger.InitLogger("error.log", "gin.log")

// New (UniRTM-specific)
opWriter, errWriter := logger.InitUniRTMLogger("unirtm.log", "error.log")

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// Logger is the global logger with a human-friendly console writer by default.
	Logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger()

	// NoColor disables the colorized output.
	NoColor bool
)

Functions

func Close added in v0.3.11

func Close() error

Close closes any open log files.

func Debug

func Debug(msg string, fields ...map[string]interface{})

Debug logs a message at debug level with optional context fields.

func Error

func Error(msg string, fields ...map[string]interface{})

Error logs a message at error level with optional context fields. Stack traces are automatically captured for error-level logs.

Example

ExampleError demonstrates error-level logging with automatic stack trace capture.

package main

import (
	"github.com/snowdreamtech/unirtm/internal/pkg/logger"
)

func main() {
	// Initialize logger
	logger.InitUniRTMLogger("unirtm.log", "error.log")

	// Log a simple error message (stack trace is automatically captured)
	logger.Error("Failed to connect to database")

	// Log with context fields
	logger.Error("Installation failed", map[string]interface{}{
		"tool":    "python",
		"version": "3.11.0",
		"reason":  "checksum mismatch",
	})
}

func ErrorWithErr

func ErrorWithErr(err error, msg string, fields ...map[string]interface{})

ErrorWithErr logs an error with its message and optional context fields. This is a convenience function for logging errors with automatic error field extraction.

Example

ExampleErrorWithErr demonstrates logging errors with error objects.

package main

import (
	"errors"

	"github.com/snowdreamtech/unirtm/internal/pkg/logger"
)

func main() {
	// Initialize logger
	logger.InitUniRTMLogger("unirtm.log", "error.log")

	// Create an error
	err := errors.New("network timeout")

	// Log error with message
	logger.ErrorWithErr(err, "Failed to download artifact")

	// Log error with context fields
	logger.ErrorWithErr(err, "Download failed", map[string]interface{}{
		"url":     "https://example.com/artifact.tar.gz",
		"retries": 5,
		"timeout": "30s",
	})
}

func Fatal

func Fatal(msg string, fields ...map[string]interface{})

Fatal logs a message at fatal level with optional context fields and exits. Stack traces are automatically captured for fatal-level logs.

func FatalWithErr

func FatalWithErr(err error, msg string, fields ...map[string]interface{})

FatalWithErr logs an error with its message and optional context fields, then exits.

func Info

func Info(msg string, fields ...map[string]interface{})

Info logs a message at info level with optional context fields.

Example

ExampleInfo demonstrates basic info-level logging.

package main

import (
	"github.com/snowdreamtech/unirtm/internal/pkg/logger"
)

func main() {
	// Initialize logger
	logger.InitUniRTMLogger("unirtm.log", "error.log")

	// Log a simple info message
	logger.Info("Application started successfully")

	// Log with context fields
	logger.Info("Tool installed", map[string]interface{}{
		"tool":    "node",
		"version": "20.0.0",
		"path":    "/usr/local/bin/node",
	})
}

func InitLogger

func InitLogger(errorLogPath, ginLogPath string) (errorWriter io.Writer, ginWriter io.Writer)

InitLogger initializes the logger with the specified error and gin log paths. It returns the error and gin writers.

Parameters:

  • errorLogPath: The path to the error log file.
  • ginLogPath: The path to the gin log file.

Returns:

  • errorWriter: The error writer.
  • ginWriter: The gin writer.

func InitUniRTMLogger

func InitUniRTMLogger(operationLogPath, errorLogPath string) (operationWriter io.Writer, errorWriter io.Writer)

InitUniRTMLogger initializes the logger for UniRTM with rotating file writers for both operation logs (unirtm.log) and error logs (error.log).

This function configures:

  • Rotating file writer for unirtm.log (operations, max 500MB, 10 backups, 30 days retention)
  • Rotating file writer for error.log (errors only, max 500MB, 10 backups, 30 days retention)
  • Console output with color-coded log levels
  • Structured logging with context fields
  • Stack trace capture for errors

Parameters:

  • operationLogPath: The path to the operation log file (default: "unirtm.log")
  • errorLogPath: The path to the error log file (default: "error.log")

Returns:

  • operationWriter: The operation log writer
  • errorWriter: The error log writer
Example

ExampleInitUniRTMLogger demonstrates how to initialize the UniRTM logger with rotating file writers for operation and error logs.

package main

import (
	"fmt"

	"github.com/snowdreamtech/unirtm/internal/pkg/logger"
)

func main() {
	// Initialize logger with custom paths
	opWriter, errWriter := logger.InitUniRTMLogger("unirtm.log", "error.log")

	fmt.Printf("Operation writer: %v\n", opWriter != nil)
	fmt.Printf("Error writer: %v\n", errWriter != nil)

}
Output:
Operation writer: true
Error writer: true

func Log deprecated

func Log(level zerolog.Level, v ...interface{})

Log logs a message at the specified log level. The log message is formatted with the current time, log level, and the provided arguments. The log output is written to the default writer of the gin framework.

Parameters:

  • level: The log level as a string (e.g., "INF", "ERR").

TraceLevel: "TRC", DebugLevel: "DBG", InfoLevel: "INF", WarnLevel: "WRN", ErrorLevel: "ERR", FatalLevel: "FTL", PanicLevel: "PNC",

  • v: Variadic arguments to be included in the log message.

Deprecated: Use Zerolog instead.

func Logf deprecated

func Logf(level zerolog.Level, format string, v ...interface{})

Logf logs a formatted message at the specified log level. The log message includes a timestamp, the log level, and the formatted message.

Parameters:

  • level: The log level (e.g., "INF", "ERR").

TraceLevel: "TRC", DebugLevel: "DBG", InfoLevel: "INF", WarnLevel: "WRN", ErrorLevel: "ERR", FatalLevel: "FTL", PanicLevel: "PNC",

  • format: The format string for the log message.
  • v: The values to be formatted according to the format string.

Deprecated: Use Zerolog instead.

func Panic

func Panic(msg string, fields ...map[string]interface{})

Panic logs a message at panic level with optional context fields and panics. Stack traces are automatically captured for panic-level logs.

func Trace

func Trace(msg string, fields ...map[string]interface{})

Trace logs a message at trace level with optional context fields.

func Warn

func Warn(msg string, fields ...map[string]interface{})

Warn logs a message at warn level with optional context fields.

func WithContext

func WithContext(fields map[string]interface{}) *zerolog.Logger

WithContext returns a logger with the specified context fields. This enables structured logging with key-value pairs.

Example:

logger.WithContext(map[string]interface{}{
    "user_id": 123,
    "operation": "install",
    "tool": "node",
    "version": "20.0.0",
}).Info("Installing tool")
Example

ExampleWithContext demonstrates structured logging with context fields.

package main

import (
	"github.com/snowdreamtech/unirtm/internal/pkg/logger"
)

func main() {
	// Initialize logger
	logger.InitUniRTMLogger("unirtm.log", "error.log")

	// Create a logger with context
	contextLogger := logger.WithContext(map[string]interface{}{
		"request_id": "req-123456",
		"user_id":    "user-789",
		"operation":  "install",
	})

	// Use the context logger
	contextLogger.Info().Msg("Starting installation")
	contextLogger.Debug().Msg("Downloading artifact")
	contextLogger.Info().Msg("Installation completed")
}

func WithError

func WithError(err error) *zerolog.Logger

WithError returns a logger with the error field set. This is a convenience function for logging errors with context.

Example:

logger.WithError(err).Error("Failed to install tool")

func WithFields

func WithFields(keysAndValues ...interface{}) *zerolog.Logger

WithFields returns a logger with multiple fields set. This is a convenience function for structured logging.

Example:

logger.WithFields(
    "user_id", 123,
    "operation", "install",
).Info("Starting operation")
Example

ExampleWithFields demonstrates structured logging with variadic key-value pairs.

package main

import (
	"github.com/snowdreamtech/unirtm/internal/pkg/logger"
)

func main() {
	// Initialize logger
	logger.InitUniRTMLogger("unirtm.log", "error.log")

	// Create a logger with fields
	fieldsLogger := logger.WithFields(
		"tool", "go",
		"version", "1.21.0",
		"backend", "github",
	)

	// Use the fields logger
	fieldsLogger.Info().Msg("Tool resolved")
	fieldsLogger.Debug().Msg("Downloading from GitHub")
	fieldsLogger.Info().Msg("Installation successful")
}

Types

type ErrorHook

type ErrorHook struct{}

ErrorHook is a hook for logging errors.

func (ErrorHook) Run

func (h ErrorHook) Run(e *zerolog.Event, level zerolog.Level, msg string)

Run executes the ErrorHook, logging the event at the specified level with the given message. It writes the log output to the default error writer for the gin framework.

Parameters:

  • e: The zerolog event to be logged.
  • level: The logging level of the event.
  • msg: The message to be logged.

type UniRTMErrorHook

type UniRTMErrorHook struct{}

UniRTMErrorHook is a hook for logging errors in UniRTM. It captures stack traces for errors and writes them to the error log file.

func (UniRTMErrorHook) Run

func (h UniRTMErrorHook) Run(e *zerolog.Event, level zerolog.Level, msg string)

Run executes the UniRTMErrorHook, capturing stack traces for error-level logs and writing them to the error log file.

Parameters:

  • e: The zerolog event to be logged.
  • level: The logging level of the event.
  • msg: The message to be logged.

Jump to

Keyboard shortcuts

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