v0.1.0 Release
This commit is contained in:
@ -11,11 +11,11 @@ The `compat` package provides adapters that allow the lixenwraith/log logger to
|
||||
|
||||
### Features
|
||||
|
||||
- ✅ Full interface compatibility
|
||||
- ✅ Preserves structured logging
|
||||
- ✅ Configurable behavior
|
||||
- ✅ Shared logger instances
|
||||
- ✅ Optional field extraction
|
||||
- Full interface compatibility
|
||||
- Preserves structured logging
|
||||
- Configurable behavior
|
||||
- Shared logger instances
|
||||
- Optional field extraction
|
||||
|
||||
## gnet Adapter
|
||||
|
||||
@ -188,6 +188,7 @@ logger := log.NewLogger()
|
||||
cfg := log.DefaultConfig()
|
||||
cfg.Level = log.LevelDebug
|
||||
logger.ApplyConfig(cfg)
|
||||
logger.Start()
|
||||
defer logger.Shutdown()
|
||||
|
||||
// Create builder with existing logger
|
||||
@ -195,7 +196,10 @@ builder := compat.NewBuilder().WithLogger(logger)
|
||||
|
||||
// Build adapters
|
||||
gnetAdapter, _ := builder.BuildGnet()
|
||||
if err != nil { return err }
|
||||
|
||||
fasthttpAdapter, _ := builder.BuildFastHTTP()
|
||||
if err != nil { return err }
|
||||
```
|
||||
|
||||
### Creating New Logger
|
||||
@ -210,6 +214,7 @@ builder := compat.NewBuilder().WithConfig(cfg)
|
||||
|
||||
// Option 2: Default config (created on first build)
|
||||
builder := compat.NewBuilder()
|
||||
if err != nil { return err }
|
||||
|
||||
// Build adapters
|
||||
gnetAdapter, _ := builder.BuildGnet()
|
||||
@ -261,63 +266,6 @@ adapter.Infof("Connected to server")
|
||||
// → {"msg": "Connected to server"}
|
||||
```
|
||||
|
||||
## Example Configuration
|
||||
|
||||
### High-Performance Setup
|
||||
|
||||
```go
|
||||
builder := compat.NewBuilder().
|
||||
WithOptions(
|
||||
"directory=/var/log/highperf",
|
||||
"format=json",
|
||||
"buffer_size=8192", // Large buffer
|
||||
"flush_interval_ms=1000", // Batch writes
|
||||
"enable_periodic_sync=false", // Reduce I/O
|
||||
"heartbeat_level=1", // Monitor drops
|
||||
)
|
||||
```
|
||||
|
||||
### Development Setup
|
||||
|
||||
```go
|
||||
builder := compat.NewBuilder().
|
||||
WithOptions(
|
||||
"directory=./log",
|
||||
"format=txt", // Human-readable
|
||||
"level=-4", // Debug level
|
||||
"trace_depth=3", // Include traces
|
||||
"enable_console=true", // Console output
|
||||
"flush_interval_ms=50", // Quick feedback
|
||||
)
|
||||
```
|
||||
|
||||
### Container Setup
|
||||
|
||||
```go
|
||||
builder := compat.NewBuilder().
|
||||
WithOptions(
|
||||
"enable_file=false", // No files
|
||||
"enable_console=true", // Console only
|
||||
"format=json", // For aggregators
|
||||
"level=0", // Info and above
|
||||
)
|
||||
```
|
||||
|
||||
### Helper Functions
|
||||
|
||||
Configure servers with adapters:
|
||||
|
||||
```go
|
||||
// Simple integration
|
||||
logger := log.NewLogger()
|
||||
|
||||
builder := compat.NewBuilder().WithLogger(logger)
|
||||
gnetAdapter, _ := builder.BuildGnet()
|
||||
|
||||
gnet.Run(handler, "tcp://127.0.0.1:9000",
|
||||
gnet.WithLogger(gnetAdapter))
|
||||
```
|
||||
|
||||
### Integration Examples
|
||||
|
||||
#### Microservice with Both Frameworks
|
||||
@ -330,41 +278,40 @@ type Service struct {
|
||||
}
|
||||
|
||||
func NewService() (*Service, error) {
|
||||
builder := compat.NewBuilder().
|
||||
WithOptions(
|
||||
"directory=/var/log/service",
|
||||
"format=json",
|
||||
"heartbeat_level=2",
|
||||
)
|
||||
|
||||
gnet, fasthttp, err := builder.Build()
|
||||
if err != nil {
|
||||
// Create and configure logger
|
||||
logger := log.NewLogger()
|
||||
cfg := log.DefaultConfig()
|
||||
cfg.Directory = "/var/log/service"
|
||||
cfg.Format = "json"
|
||||
cfg.HeartbeatLevel = 2
|
||||
if err := logger.ApplyConfig(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Service{
|
||||
gnetAdapter: gnet,
|
||||
fasthttpAdapter: fasthttp,
|
||||
logger: builder.GetLogger(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) StartTCPServer() error {
|
||||
return gnet.Run(handler, "tcp://0.0.0.0:9000",
|
||||
gnet.WithLogger(s.gnetAdapter),
|
||||
)
|
||||
}
|
||||
|
||||
func (s *Service) StartHTTPServer() error {
|
||||
server := &fasthttp.Server{
|
||||
Handler: s.handleHTTP,
|
||||
Logger: s.fasthttpAdapter,
|
||||
if err := logger.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return server.ListenAndServe(":8080")
|
||||
}
|
||||
|
||||
func (s *Service) Shutdown() error {
|
||||
return s.logger.Shutdown(5 * time.Second)
|
||||
// Create builder with the logger
|
||||
builder := compat.NewBuilder().WithLogger(logger)
|
||||
|
||||
// Build adapters
|
||||
gnetAdapter, err := builder.BuildGnet()
|
||||
if err != nil {
|
||||
logger.Shutdown()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fasthttpAdapter, err := builder.BuildFastHTTP()
|
||||
if err != nil {
|
||||
logger.Shutdown()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Service{
|
||||
gnetAdapter: gnetAdapter,
|
||||
fasthttpAdapter: fasthttpAdapter,
|
||||
logger: logger,
|
||||
}, nil
|
||||
}
|
||||
```
|
||||
|
||||
@ -405,5 +352,4 @@ func requestLogger(adapter *compat.FastHTTPAdapter) fasthttp.RequestHandler {
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← Heartbeat Monitoring](heartbeat-monitoring.md) | [← Back to README](../README.md)
|
||||
@ -388,5 +388,4 @@ func (s *Service) Shutdown() error {
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← Configuration Builder](config-builder.md) | [← Back to README](../README.md) | [Logging Guide →](logging-guide.md)
|
||||
90
doc/builder.md
Normal file
90
doc/builder.md
Normal file
@ -0,0 +1,90 @@
|
||||
# Builder Pattern Guide
|
||||
|
||||
The Builder provides a fluent API for constructing and initializing logger instances with compile-time safety and deferred validation.
|
||||
|
||||
## Creating a Builder
|
||||
|
||||
NewBuilder creates a new builder for constructing a logger instance.
|
||||
```go
|
||||
func NewBuilder() *Builder
|
||||
```
|
||||
```go
|
||||
builder := log.NewBuilder()
|
||||
```
|
||||
|
||||
## Builder Methods
|
||||
|
||||
All builder methods return `*Builder` for chaining. Errors are accumulated and returned by `Build()`.
|
||||
|
||||
### Common Methods
|
||||
|
||||
| Method | Parameters | Description |
|
||||
|--------|------------|-------------|
|
||||
| `Level(level int64)` | `level`: Numeric log level | Sets log level (-4 to 8) |
|
||||
| `LevelString(level string)` | `level`: Named level | Sets level by name ("debug", "info", etc.) |
|
||||
| `Name(name string)` | `name`: Base filename | Sets log file base name |
|
||||
| `Directory(dir string)` | `dir`: Path | Sets log directory |
|
||||
| `Format(format string)` | `format`: Output format | Sets format ("txt", "json", "raw") |
|
||||
| `Extension(ext string)` | `ext`: File extension | Sets log file extension |
|
||||
| `BufferSize(size int64)` | `size`: Buffer size | Sets channel buffer size |
|
||||
| `MaxSizeKB(size int64)` | `size`: Size in KB | Sets max file size in KB |
|
||||
| `MaxSizeMB(size int64)` | `size`: Size in MB | Sets max file size in MB |
|
||||
| `MaxTotalSizeKB(size int64)` | `size`: Size in KB | Sets max total log directory size in KB |
|
||||
| `MaxTotalSizeMB(size int64)` | `size`: Size in MB | Sets max total log directory size in MB |
|
||||
| `MinDiskFreeKB(size int64)` | `size`: Size in KB | Sets minimum required free disk space in KB |
|
||||
| `MinDiskFreeMB(size int64)` | `size`: Size in MB | Sets minimum required free disk space in MB |
|
||||
| `EnableConsole(enable bool)` | `enable`: Boolean | Enables console output |
|
||||
| `EnableFile(enable bool)` | `enable`: Boolean | Enables file output |
|
||||
| `ConsoleTarget(target string)` | `target`: "stdout"/"stderr" | Sets console output target |
|
||||
| `ShowTimestamp(show bool)` | `show`: Boolean | Controls timestamp display |
|
||||
| `ShowLevel(show bool)` | `show`: Boolean | Controls log level display |
|
||||
| `TimestampFormat(format string)` | `format`: Time format | Sets timestamp format (Go time format) |
|
||||
| `HeartbeatLevel(level int64)` | `level`: 0-3 | Sets monitoring level (0=off) |
|
||||
| `HeartbeatIntervalS(interval int64)` | `interval`: Seconds | Sets heartbeat interval |
|
||||
| `FlushIntervalMs(interval int64)` | `interval`: Milliseconds | Sets buffer flush interval |
|
||||
| `TraceDepth(depth int64)` | `depth`: 0-10 | Sets default function trace depth |
|
||||
| `DiskCheckIntervalMs(interval int64)` | `interval`: Milliseconds | Sets disk check interval |
|
||||
| `EnableAdaptiveInterval(enable bool)` | `enable`: Boolean | Enables adaptive disk check intervals |
|
||||
| `MinCheckIntervalMs(interval int64)` | `interval`: Milliseconds | Sets minimum adaptive interval |
|
||||
| `MaxCheckIntervalMs(interval int64)` | `interval`: Milliseconds | Sets maximum adaptive interval |
|
||||
| `EnablePeriodicSync(enable bool)` | `enable`: Boolean | Enables periodic disk sync |
|
||||
| `RetentionPeriodHrs(hours float64)` | `hours`: Hours | Sets log retention period |
|
||||
| `RetentionCheckMins(mins float64)` | `mins`: Minutes | Sets retention check interval |
|
||||
| `InternalErrorsToStderr(enable bool)` | `enable`: Boolean | Send internal errors to stderr |
|
||||
|
||||
## Build
|
||||
```go
|
||||
func (b *Builder) Build() (*Logger, error)
|
||||
```
|
||||
|
||||
Creates and initializes a logger instance with the configured settings.
|
||||
Returns accumulated errors if any builder operations failed.
|
||||
```go
|
||||
logger, err := builder.Build()
|
||||
if err != nil {
|
||||
// Handle validation or initialization errors
|
||||
}
|
||||
defer logger.Shutdown()
|
||||
```
|
||||
|
||||
## Usage Pattern
|
||||
```go
|
||||
// Single-step logger creation and initialization
|
||||
logger, err := log.NewBuilder().
|
||||
Directory("/var/log/app").
|
||||
Format("json").
|
||||
LevelString("debug").
|
||||
Build()
|
||||
|
||||
if err != nil { return err }
|
||||
defer logger.Shutdown()
|
||||
|
||||
// Start the logger
|
||||
err = logger.Start()
|
||||
if err != nil { return err }
|
||||
|
||||
logger.Info("Application started")
|
||||
```
|
||||
|
||||
---
|
||||
[← Configuration](configuration.md) | [← Back to README](../README.md) | [API Reference →](api-reference.md)
|
||||
@ -1,71 +0,0 @@
|
||||
# Builder Pattern Guide
|
||||
|
||||
The ConfigBuilder provides a fluent API for constructing logger configurations with compile-time safety and deferred validation.
|
||||
|
||||
## Creating a Builder
|
||||
|
||||
NewConfigBuilder creates a new configuration builder initialized with default values.
|
||||
|
||||
```go
|
||||
func NewConfigBuilder() *ConfigBuilder
|
||||
```
|
||||
|
||||
```go
|
||||
builder := log.NewConfigBuilder()
|
||||
```
|
||||
|
||||
## Builder Methods
|
||||
|
||||
All builder methods return `*ConfigBuilder` for chaining. Errors are accumulated and returned by `Build()`.
|
||||
|
||||
### Common Methods
|
||||
|
||||
| Method | Parameters | Description |
|
||||
|-------------------------------|----------------------------|--------------------------------------------|
|
||||
| `Level(level int64)` | `level`: Numeric log level | Sets log level (-4 to 8) |
|
||||
| `LevelString(level string)` | `level`: Named level | Sets level by name ("debug", "info", etc.) |
|
||||
| `Directory(dir string)` | `dir`: Path | Sets log directory |
|
||||
| `Format(format string)` | `format`: Output format | Sets format ("txt", "json", "raw") |
|
||||
| `BufferSize(size int64)` | `size`: Buffer size | Sets channel buffer size |
|
||||
| `MaxSizeKB(size int64)` | `size`: Size in MB | Sets max file size |
|
||||
| `EnableConsole(enable bool)` | `enable`: Boolean | Enables console output |
|
||||
| `EnableFile(enable bool)` | `enable`: Boolean | Enable file output |
|
||||
| `HeartbeatLevel(level int64)` | `level`: 0-3 | Sets monitoring level |
|
||||
|
||||
## Build
|
||||
|
||||
```go
|
||||
func (b *ConfigBuilder) Build() (*Config, error)
|
||||
```
|
||||
|
||||
Validates builder configuration and returns logger config.
|
||||
Returns accumulated errors if any builder operations failed.
|
||||
|
||||
```go
|
||||
cfg, err := builder.Build()
|
||||
if err != nil {
|
||||
// Handle validation or conversion errors
|
||||
}
|
||||
```
|
||||
|
||||
## Usage pattern
|
||||
|
||||
```go
|
||||
logger := log.NewLogger()
|
||||
|
||||
cfg, err := log.NewConfigBuilder().
|
||||
Directory("/var/log/app").
|
||||
Format("json").
|
||||
LevelString("debug").
|
||||
Build()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = logger.ApplyConfig(cfg)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← Configuration](configuration.md) | [← Back to README](../README.md) | [API Reference →](api-reference.md)
|
||||
@ -102,5 +102,4 @@ logger.Info("info txt log record written to /var/log/myapp.txt")
|
||||
| `heartbeat_interval_s` | `int64` | Heartbeat interval (seconds) | `60` |
|
||||
|
||||
---
|
||||
|
||||
[← Getting Started](getting-started.md) | [← Back to README](../README.md) | [Configuration Builder →](config-builder.md)
|
||||
@ -24,18 +24,32 @@ The logger follows an instance-based design. You create logger instances and cal
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/lixenwraith/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create a new logger instance with default configuration
|
||||
// Writes to both console (stdout) and file ./log/log.log
|
||||
logger := log.NewLogger()
|
||||
// Create a new logger instance with default configuration
|
||||
logger := log.NewLogger()
|
||||
|
||||
// Apply configuration
|
||||
err := logger.ApplyConfigString("directory=/var/log/myapp")
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to apply logger config: %w", err))
|
||||
}
|
||||
defer logger.Shutdown()
|
||||
|
||||
|
||||
// Start the logger (required before logging)
|
||||
if err = logger.Start(); err != nil {
|
||||
panic(fmt.Errorf("failed to start logger: %w", err))
|
||||
}
|
||||
|
||||
// Start logging!
|
||||
logger.Info("Application started")
|
||||
logger.Debug("Debug mode enabled", "verbose", true)
|
||||
logger.Warn("Warning message", "threshold", 0.95)
|
||||
logger.Error("Error occurred", "code", 500)
|
||||
}
|
||||
```
|
||||
|
||||
@ -64,6 +78,8 @@ func NewService() (*Service, error) {
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("logger init failed: %w", err)
|
||||
}
|
||||
|
||||
logger.Start()
|
||||
|
||||
return &Service{
|
||||
logger: logger,
|
||||
@ -101,5 +117,4 @@ func loggingMiddleware(logger *log.Logger) func(http.Handler) http.Handler {
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← Back to README](../README.md) | [Configuration →](configuration.md)
|
||||
@ -165,5 +165,4 @@ With `format=txt`, heartbeats are human-readable:
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← Disk Management](disk-management.md) | [← Back to README](../README.md) | [Compatibility Adapters →](compatibility-adapters.md)
|
||||
513
doc/llm-guide_lixenwraith_log.md
Normal file
513
doc/llm-guide_lixenwraith_log.md
Normal file
@ -0,0 +1,513 @@
|
||||
# lixenwraith/log LLM Usage Guide
|
||||
|
||||
This guide details the `lixenwraith/log` package, a high-performance, buffered, rotating file logger for Go with built-in disk management, operational monitoring, and framework compatibility adapters.
|
||||
|
||||
## Quick Start: Recommended Usage
|
||||
|
||||
The recommended pattern uses the **Builder** with type-safe configuration. This provides compile-time safety and eliminates runtime errors.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/lixenwraith/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 1. Use the builder pattern for configuration (recommended).
|
||||
logger, err := log.NewBuilder().
|
||||
Directory("/var/log/myapp"). // Log directory path
|
||||
LevelString("info"). // Minimum log level
|
||||
Format("json"). // Output format
|
||||
BufferSize(2048). // Channel buffer size
|
||||
MaxSizeMB(10). // Max file size before rotation
|
||||
HeartbeatLevel(1). // Enable operational monitoring
|
||||
HeartbeatIntervalS(300). // Every 5 minutes
|
||||
Build() // Build the logger instance
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("logger build failed: %w", err))
|
||||
}
|
||||
defer logger.Shutdown(5 * time.Second)
|
||||
|
||||
// 2. Start the logger (required before logging).
|
||||
if err := logger.Start(); err != nil {
|
||||
panic(fmt.Errorf("logger start failed: %w", err))
|
||||
}
|
||||
|
||||
// 3. Begin logging with structured key-value pairs.
|
||||
logger.Info("Application started", "version", "1.0.0", "pid", os.Getpid())
|
||||
logger.Debug("Debug information", "user_id", 12345)
|
||||
logger.Warn("High memory usage", "used_mb", 1800, "limit_mb", 2048)
|
||||
logger.Error("Connection failed", "host", "db.example.com", "error", err)
|
||||
}
|
||||
```
|
||||
|
||||
## Alternative Initialization Methods
|
||||
|
||||
### Using ApplyConfigString (Quick Configuration)
|
||||
|
||||
```go
|
||||
logger := log.NewLogger()
|
||||
err := logger.ApplyConfigString(
|
||||
"directory=/var/log/app",
|
||||
"format=json",
|
||||
"level=debug",
|
||||
"max_size_kb=5000",
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config failed: %w", err)
|
||||
}
|
||||
defer logger.Shutdown()
|
||||
logger.Start()
|
||||
```
|
||||
|
||||
### Using ApplyConfig (Full Control)
|
||||
|
||||
```go
|
||||
logger := log.NewLogger()
|
||||
cfg := log.DefaultConfig()
|
||||
cfg.Directory = "/var/log/app"
|
||||
cfg.Format = "json"
|
||||
cfg.Level = log.LevelDebug
|
||||
cfg.MaxSizeKB = 5000
|
||||
cfg.HeartbeatLevel = 2 // Process + disk stats
|
||||
err := logger.ApplyConfig(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config failed: %w", err)
|
||||
}
|
||||
defer logger.Shutdown()
|
||||
logger.Start()
|
||||
```
|
||||
|
||||
## Builder Pattern
|
||||
|
||||
The `Builder` is the primary way to construct a `Logger` instance with compile-time safety.
|
||||
|
||||
```go
|
||||
// NewBuilder creates a new logger builder.
|
||||
func NewBuilder() *Builder
|
||||
// Build finalizes configuration and creates the logger.
|
||||
func (b *Builder) Build() (*Logger, error)
|
||||
```
|
||||
|
||||
### Builder Methods
|
||||
|
||||
All builder methods return `*Builder` for chaining.
|
||||
|
||||
**Basic Configuration:**
|
||||
- `Level(level int64)`: Set numeric log level (-4 to 8)
|
||||
- `LevelString(level string)`: Set level by name ("debug", "info", "warn", "error")
|
||||
- `Directory(dir string)`: Set log directory path
|
||||
- `Name(name string)`: Set base filename (default: "log")
|
||||
- `Format(format string)`: Set format ("txt", "json", "raw")
|
||||
- `Extension(ext string)`: Set file extension (default: ".log")
|
||||
|
||||
**Buffer and Performance:**
|
||||
- `BufferSize(size int64)`: Channel buffer size (default: 1024)
|
||||
- `FlushIntervalMs(ms int64)`: Buffer flush interval (default: 100ms)
|
||||
- `TraceDepth(depth int64)`: Default function trace depth 0-10 (default: 0)
|
||||
|
||||
**File Management:**
|
||||
- `MaxSizeKB(size int64)` / `MaxSizeMB(size int64)`: Max file size before rotation
|
||||
- `MaxTotalSizeKB(size int64)` / `MaxTotalSizeMB(size int64)`: Max total directory size
|
||||
- `MinDiskFreeKB(size int64)` / `MinDiskFreeMB(size int64)`: Required free disk space
|
||||
- `RetentionPeriodHrs(hours float64)`: Hours to keep logs (0=disabled)
|
||||
- `RetentionCheckMins(mins float64)`: Retention check interval
|
||||
|
||||
**Output Control:**
|
||||
- `EnableConsole(enable bool)`: Enable stdout/stderr output
|
||||
- `EnableFile(enable bool)`: Enable file output
|
||||
- `ConsoleTarget(target string)`: "stdout", "stderr", or "split"
|
||||
|
||||
**Formatting:**
|
||||
- `ShowTimestamp(show bool)`: Add timestamps
|
||||
- `ShowLevel(show bool)`: Add level labels
|
||||
- `TimestampFormat(format string)`: Go time format string
|
||||
|
||||
**Monitoring:**
|
||||
- `HeartbeatLevel(level int64)`: 0=off, 1=proc, 2=+disk, 3=+sys
|
||||
- `HeartbeatIntervalS(seconds int64)`: Heartbeat interval
|
||||
|
||||
**Disk Monitoring:**
|
||||
- `DiskCheckIntervalMs(ms int64)`: Base disk check interval
|
||||
- `EnableAdaptiveInterval(enable bool)`: Adjust interval based on load
|
||||
- `MinCheckIntervalMs(ms int64)`: Minimum adaptive interval
|
||||
- `MaxCheckIntervalMs(ms int64)`: Maximum adaptive interval
|
||||
- `EnablePeriodicSync(enable bool)`: Periodic disk sync
|
||||
|
||||
**Error Handling:**
|
||||
- `InternalErrorsToStderr(enable bool)`: Send internal errors to stderr
|
||||
|
||||
## API Reference
|
||||
|
||||
### Logger Creation
|
||||
|
||||
```go
|
||||
func NewLogger() *Logger
|
||||
```
|
||||
Creates a new uninitialized logger with default configuration.
|
||||
|
||||
### Configuration Methods
|
||||
|
||||
```go
|
||||
func (l *Logger) ApplyConfig(cfg *Config) error
|
||||
func (l *Logger) ApplyConfigString(overrides ...string) error
|
||||
func (l *Logger) GetConfig() *Config
|
||||
```
|
||||
|
||||
### Lifecycle Methods
|
||||
|
||||
```go
|
||||
func (l *Logger) Start() error // Start log processing
|
||||
func (l *Logger) Stop(timeout ...time.Duration) error // Stop (can restart)
|
||||
func (l *Logger) Shutdown(timeout ...time.Duration) error // Terminal shutdown
|
||||
func (l *Logger) Flush(timeout time.Duration) error // Force buffer flush
|
||||
```
|
||||
|
||||
### Standard Logging Methods
|
||||
|
||||
```go
|
||||
func (l *Logger) Debug(args ...any) // Level -4
|
||||
func (l *Logger) Info(args ...any) // Level 0
|
||||
func (l *Logger) Warn(args ...any) // Level 4
|
||||
func (l *Logger) Error(args ...any) // Level 8
|
||||
```
|
||||
|
||||
### Trace Logging Methods
|
||||
|
||||
Include function call traces (depth 0-10):
|
||||
|
||||
```go
|
||||
func (l *Logger) DebugTrace(depth int, args ...any)
|
||||
func (l *Logger) InfoTrace(depth int, args ...any)
|
||||
func (l *Logger) WarnTrace(depth int, args ...any)
|
||||
func (l *Logger) ErrorTrace(depth int, args ...any)
|
||||
```
|
||||
|
||||
### Special Logging Methods
|
||||
|
||||
```go
|
||||
func (l *Logger) LogStructured(level int64, message string, fields map[string]any)
|
||||
func (l *Logger) Write(args ...any) // Raw output, no formatting
|
||||
func (l *Logger) Log(args ...any) // Timestamp only, no level
|
||||
func (l *Logger) Message(args ...any) // No timestamp or level
|
||||
func (l *Logger) LogTrace(depth int, args ...any) // Timestamp + trace, no level
|
||||
```
|
||||
|
||||
## Constants and Levels
|
||||
|
||||
### Standard Log Levels
|
||||
|
||||
```go
|
||||
const (
|
||||
LevelDebug int64 = -4 // Verbose debugging
|
||||
LevelInfo int64 = 0 // Informational messages
|
||||
LevelWarn int64 = 4 // Warning conditions
|
||||
LevelError int64 = 8 // Error conditions
|
||||
)
|
||||
```
|
||||
|
||||
### Heartbeat Monitoring Levels
|
||||
|
||||
Special levels that bypass filtering:
|
||||
|
||||
```go
|
||||
const (
|
||||
LevelProc int64 = 12 // Process statistics
|
||||
LevelDisk int64 = 16 // Disk usage statistics
|
||||
LevelSys int64 = 20 // System statistics
|
||||
)
|
||||
```
|
||||
|
||||
### Level Helper
|
||||
|
||||
```go
|
||||
func Level(levelStr string) (int64, error)
|
||||
```
|
||||
Converts level string to numeric constant: "debug", "info", "warn", "error", "proc", "disk", "sys".
|
||||
|
||||
## Configuration Structure
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
// Output Settings
|
||||
EnableConsole bool // Enable stdout/stderr output
|
||||
ConsoleTarget string // "stdout", "stderr", or "split"
|
||||
EnableFile bool // Enable file output
|
||||
|
||||
// Basic Settings
|
||||
Level int64 // Minimum log level
|
||||
Name string // Base filename (default: "log")
|
||||
Directory string // Log directory path
|
||||
Format string // "txt", "json", or "raw"
|
||||
Extension string // File extension (default: ".log")
|
||||
|
||||
// Formatting
|
||||
ShowTimestamp bool // Add timestamps
|
||||
ShowLevel bool // Add level labels
|
||||
TimestampFormat string // Go time format
|
||||
|
||||
// Buffer and Performance
|
||||
BufferSize int64 // Channel buffer size
|
||||
FlushIntervalMs int64 // Buffer flush interval
|
||||
TraceDepth int64 // Default trace depth (0-10)
|
||||
|
||||
// File Management
|
||||
MaxSizeKB int64 // Max file size (KB)
|
||||
MaxTotalSizeKB int64 // Max total directory size (KB)
|
||||
MinDiskFreeKB int64 // Required free disk space (KB)
|
||||
RetentionPeriodHrs float64 // Hours to keep logs
|
||||
RetentionCheckMins float64 // Retention check interval
|
||||
|
||||
// Disk Monitoring
|
||||
DiskCheckIntervalMs int64 // Base check interval
|
||||
EnableAdaptiveInterval bool // Adjust based on load
|
||||
MinCheckIntervalMs int64 // Minimum interval
|
||||
MaxCheckIntervalMs int64 // Maximum interval
|
||||
EnablePeriodicSync bool // Periodic disk sync
|
||||
|
||||
// Heartbeat
|
||||
HeartbeatLevel int64 // 0=off, 1=proc, 2=+disk, 3=+sys
|
||||
HeartbeatIntervalS int64 // Heartbeat interval
|
||||
|
||||
// Error Handling
|
||||
InternalErrorsToStderr bool // Write internal errors to stderr
|
||||
}
|
||||
```
|
||||
|
||||
### Default Configuration
|
||||
|
||||
```go
|
||||
func DefaultConfig() *Config
|
||||
```
|
||||
|
||||
Returns default configuration with sensible values:
|
||||
- Console output enabled to stdout
|
||||
- File output enabled
|
||||
- Info level logging
|
||||
- 1MB max file size
|
||||
- 5MB max total size
|
||||
- 100ms flush interval
|
||||
|
||||
## Output Formats
|
||||
|
||||
### Text Format (default)
|
||||
|
||||
Human-readable format with optional timestamps and levels:
|
||||
```
|
||||
2024-01-15T10:30:00.123456Z INFO Application started version="1.0.0" pid=1234
|
||||
2024-01-15T10:30:01.456789Z ERROR Connection failed host="db.example.com" error="timeout"
|
||||
```
|
||||
|
||||
### JSON Format
|
||||
|
||||
Structured JSON output for log aggregation:
|
||||
```json
|
||||
{"time":"2024-01-15T10:30:00.123456Z","level":"INFO","fields":["Application started","version","1.0.0","pid",1234]}
|
||||
{"time":"2024-01-15T10:30:01.456789Z","level":"ERROR","fields":["Connection failed","host","db.example.com","error","timeout"]}
|
||||
```
|
||||
|
||||
### Raw Format
|
||||
|
||||
Minimal format without timestamps or levels:
|
||||
```
|
||||
Application started version="1.0.0" pid=1234
|
||||
Connection failed host="db.example.com" error="timeout"
|
||||
```
|
||||
|
||||
## Framework Adapters (compat package)
|
||||
|
||||
### gnet v2 Adapter
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/lixenwraith/log"
|
||||
"github.com/lixenwraith/log/compat"
|
||||
"github.com/panjf2000/gnet/v2"
|
||||
)
|
||||
|
||||
// Create adapter
|
||||
adapter := compat.NewGnetAdapter(logger)
|
||||
|
||||
// Use with gnet
|
||||
gnet.Run(handler, "tcp://127.0.0.1:9000", gnet.WithLogger(adapter))
|
||||
```
|
||||
|
||||
### fasthttp Adapter
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/lixenwraith/log"
|
||||
"github.com/lixenwraith/log/compat"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
// Create adapter
|
||||
adapter := compat.NewFastHTTPAdapter(logger)
|
||||
|
||||
// Use with fasthttp
|
||||
server := &fasthttp.Server{
|
||||
Handler: requestHandler,
|
||||
Logger: adapter,
|
||||
}
|
||||
```
|
||||
|
||||
### Adapter Builder Pattern
|
||||
|
||||
```go
|
||||
// Share logger across adapters
|
||||
builder := compat.NewBuilder().WithLogger(logger)
|
||||
|
||||
gnetAdapter, err := builder.BuildGnet()
|
||||
fasthttpAdapter, err := builder.BuildFastHTTP()
|
||||
|
||||
// Or create structured adapters
|
||||
structuredGnet, err := builder.BuildStructuredGnet()
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Service with Shared Logger
|
||||
|
||||
```go
|
||||
type Service struct {
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
func NewService() (*Service, error) {
|
||||
logger, err := log.NewBuilder().
|
||||
Directory("/var/log/service").
|
||||
Format("json").
|
||||
BufferSize(2048).
|
||||
HeartbeatLevel(2).
|
||||
Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := logger.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Service{logger: logger}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Close() error {
|
||||
return s.logger.Shutdown(5 * time.Second)
|
||||
}
|
||||
|
||||
func (s *Service) ProcessRequest(id string) {
|
||||
s.logger.Info("Processing", "request_id", id)
|
||||
// ... process ...
|
||||
s.logger.Info("Completed", "request_id", id)
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP Middleware
|
||||
|
||||
```go
|
||||
func loggingMiddleware(logger *log.Logger) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
wrapped := &responseWriter{ResponseWriter: w, status: 200}
|
||||
|
||||
next.ServeHTTP(wrapped, r)
|
||||
|
||||
logger.Info("HTTP request",
|
||||
"method", r.Method,
|
||||
"path", r.URL.Path,
|
||||
"status", wrapped.status,
|
||||
"duration_ms", time.Since(start).Milliseconds(),
|
||||
"remote_addr", r.RemoteAddr,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Hot Reconfiguration
|
||||
|
||||
```go
|
||||
// Initial configuration
|
||||
logger.ApplyConfigString("level=info")
|
||||
|
||||
// Debugging reconfiguration
|
||||
logger.ApplyConfigString(
|
||||
"level=debug",
|
||||
"heartbeat_level=3",
|
||||
"heartbeat_interval_s=60",
|
||||
)
|
||||
|
||||
// Revert to normal
|
||||
logger.ApplyConfigString(
|
||||
"level=info",
|
||||
"heartbeat_level=1",
|
||||
"heartbeat_interval_s=300",
|
||||
)
|
||||
```
|
||||
|
||||
### Graceful Shutdown
|
||||
|
||||
```go
|
||||
// Setup signal handling
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
|
||||
|
||||
// Shutdown sequence
|
||||
<-sigChan
|
||||
logger.Info("Shutdown initiated")
|
||||
|
||||
// Flush pending logs with timeout
|
||||
if err := logger.Shutdown(5 * time.Second); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Logger shutdown error: %v\n", err)
|
||||
}
|
||||
```
|
||||
|
||||
## Thread Safety
|
||||
|
||||
All public methods are thread-safe. The logger uses:
|
||||
- Atomic operations for state management
|
||||
- Channels for log record passing
|
||||
- No locks in the critical logging path
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
- **Zero-allocation logging path**: Uses pre-allocated buffers
|
||||
- **Lock-free async design**: Non-blocking sends to buffered channel
|
||||
- **Adaptive disk checks**: Adjusts I/O based on load
|
||||
- **Batch writes**: Flushes buffer periodically, not per-record
|
||||
- **Drop tracking**: Counts dropped logs when buffer full
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### From standard log package
|
||||
|
||||
```go
|
||||
// Before: standard log
|
||||
log.Printf("User login: id=%d name=%s", id, name)
|
||||
|
||||
// After: lixenwraith/log
|
||||
logger.Info("User login", "id", id, "name", name)
|
||||
```
|
||||
|
||||
### From other structured loggers
|
||||
|
||||
```go
|
||||
// Before: zap
|
||||
zap.Info("User login",
|
||||
zap.Int("id", id),
|
||||
zap.String("name", name))
|
||||
|
||||
// After: lixenwraith/log
|
||||
logger.Info("User login", "id", id, "name", name)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Builder pattern** for configuration - compile-time safety
|
||||
2. **Use structured logging** - consistent key-value pairs
|
||||
3. **Use appropriate levels** - filter noise in logs
|
||||
@ -131,11 +131,11 @@ func logWithContext(ctx context.Context, logger *log.Logger, level string, msg s
|
||||
Default format for development and debugging:
|
||||
|
||||
```
|
||||
2024-01-15T10:30:45.123456789Z INFO User login user_id=42 email="user@example.com" ip="192.168.1.100"
|
||||
2024-01-15T10:30:45.123456789Z INFO User login user_id=42 email=user@example.com ip=192.168.1.100
|
||||
2024-01-15T10:30:45.234567890Z WARN Rate limit approaching user_id=42 requests=95 limit=100
|
||||
```
|
||||
|
||||
Note: The txt format does not add quotes around string values containing spaces. This ensures predictability for simple, space-delimited parsing tools. For logs where maintaining the integrity of such values is critical, `json` format is recommended.
|
||||
Note: The txt format adds quotes around non-string values (errors, stringers, complex types) when they contain spaces. Plain string arguments are not quoted. Control characters in strings are sanitized to hex representation. For logs requiring exact preservation of all values, `json` format is recommended.
|
||||
|
||||
Configuration:
|
||||
```go
|
||||
@ -336,5 +336,4 @@ func (m *MetricsCollector) logMetrics() {
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← API Reference](api-reference.md) | [← Back to README](../README.md) | [Disk Management →](disk-management.md)
|
||||
@ -10,13 +10,13 @@ Log files are automatically rotated when they reach the configured size limit:
|
||||
|
||||
```go
|
||||
logger.ApplyConfigString(
|
||||
"max_size_mb=100", // Rotate at 100MB
|
||||
"max_size_kb=100", // Rotate at 100MB
|
||||
)
|
||||
```
|
||||
|
||||
### Rotation Behavior
|
||||
|
||||
1. **Size Check**: Before each write, the logger checks if the file would exceed `max_size_mb`
|
||||
1. **Size Check**: Before each write, the logger checks if the file would exceed `max_size_kb`
|
||||
2. **New File Creation**: Creates a new file with timestamp: `appname_240115_103045_123456789.log`
|
||||
3. **Seamless Transition**: No logs are lost during rotation
|
||||
4. **Old File Closure**: Previous file is properly closed and synced
|
||||
@ -44,8 +44,8 @@ The logger enforces two types of space limits:
|
||||
|
||||
```go
|
||||
logger.ApplyConfigString(
|
||||
"max_total_size_mb=1000", // Total log directory size
|
||||
"min_disk_free_mb=5000", // Minimum free disk space
|
||||
"max_total_size_kb=1000", // Total log directory size
|
||||
"min_disk_free_kb=5000", // Minimum free disk space
|
||||
)
|
||||
```
|
||||
|
||||
@ -62,23 +62,23 @@ When limits are exceeded, the logger:
|
||||
```go
|
||||
// Conservative: Strict limits
|
||||
logger.ApplyConfigString(
|
||||
"max_size_mb=50", // 50MB files
|
||||
"max_total_size_mb=500", // 500MB total
|
||||
"min_disk_free_mb=1000", // 1GB free required
|
||||
"max_size_kb=500", // 500KB files
|
||||
"max_total_size_kb=5000", // 5MB total
|
||||
"min_disk_free_kb=1000000", // 1GB free required
|
||||
)
|
||||
|
||||
// Generous: Large files, external archival
|
||||
logger.ApplyConfigString(
|
||||
"max_size_mb=1000", // 1GB files
|
||||
"max_total_size_mb=0", // No total limit
|
||||
"min_disk_free_mb=100", // 100MB free required
|
||||
"max_size_kb=100000", // 100MB files
|
||||
"max_total_size_kb=0", // No total limit
|
||||
"min_disk_free_kb=10000", // 10MB free required
|
||||
)
|
||||
|
||||
// Balanced: Production defaults
|
||||
logger.ApplyConfigString(
|
||||
"max_size_mb=100", // 100MB files
|
||||
"max_total_size_mb=5000", // 5GB total
|
||||
"min_disk_free_mb=500", // 500MB free required
|
||||
"max_size_kb=100000", // 100MB files
|
||||
"max_total_size_kb=5000000", // 5GB total
|
||||
"min_disk_free_kb=500000", // 500MB free required
|
||||
)
|
||||
```
|
||||
|
||||
@ -102,21 +102,21 @@ logger.ApplyConfigString(
|
||||
logger.ApplyConfigString(
|
||||
"retention_period_hrs=720", // 30 days
|
||||
"retention_check_mins=60", // Check hourly
|
||||
"max_size_mb=1000", // 1GB daily files
|
||||
"max_size_kb=1000000", // 1GB daily files
|
||||
)
|
||||
|
||||
// High-frequency logs, keep 24 hours
|
||||
logger.ApplyConfigString(
|
||||
"retention_period_hrs=24", // 1 day
|
||||
"retention_check_mins=15", // Check every 15 min
|
||||
"max_size_mb=100", // 100MB files
|
||||
"max_size_kb=100000", // 100MB files
|
||||
)
|
||||
|
||||
// Compliance: Keep 90 days
|
||||
logger.ApplyConfigString(
|
||||
"retention_period_hrs=2160", // 90 days
|
||||
"retention_check_mins=360", // Check every 6 hours
|
||||
"max_total_size_mb=100000", // 100GB total
|
||||
"max_total_size_kb=100000000", // 100GB total
|
||||
)
|
||||
```
|
||||
|
||||
@ -161,7 +161,7 @@ logger.ApplyConfigString(
|
||||
|
||||
Output:
|
||||
```
|
||||
2024-01-15T10:30:00Z DISK type="disk" sequence=1 rotated_files=5 deleted_files=2 total_log_size_mb="487.32" log_file_count=8 current_file_size_mb="23.45" disk_status_ok=true disk_free_mb="5234.67"
|
||||
2024-01-15T10:30:00Z DISK type="disk" sequence=1 rotated_files=5 deleted_files=2 total_log_size_kb="487.32" log_file_count=8 current_file_size_kb="23.45" disk_status_ok=true disk_free_kb="5234.67"
|
||||
```
|
||||
|
||||
## Manual Recovery
|
||||
@ -183,5 +183,4 @@ df -h /var/log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← Logging Guide](logging-guide.md) | [← Back to README](../README.md) | [Heartbeat Monitoring →](heartbeat-monitoring.md)
|
||||
Reference in New Issue
Block a user