e1.4.4 Fix module path and dependency issues, compatibility package added.

This commit is contained in:
2025-07-08 22:13:11 -04:00
parent 7ce7158841
commit ccbe65bf40
22 changed files with 776 additions and 29 deletions

View File

@ -1,7 +1,7 @@
# Log
A high-performance, buffered, rotating file logger for Go applications, configured via
the [LixenWraith/config](https://github.com/LixenWraith/config) package or simple overrides. Designed for
the [lixenwraith/config](https://github.com/lixenwraith/config) package or simple overrides. Designed for
production-grade reliability with features like disk management, log retention, and lock-free asynchronous processing
using atomic operations and channels.
@ -14,7 +14,7 @@ using atomic operations and channels.
- **Lock-free Asynchronous Logging:** Non-blocking log operations with minimal application impact. Logs are sent via a
buffered channel, processed by a dedicated background goroutine. Uses atomic operations for state management, avoiding
mutexes in the hot path.
- **External Configuration:** Fully configured using `github.com/LixenWraith/config`, supporting both TOML files and CLI
- **External Configuration:** Fully configured using `github.com/lixenwraith/config`, supporting both TOML files and CLI
overrides with centralized management. Also supports simple initialization with defaults and string overrides via
`InitWithDefaults`.
- **Automatic File Rotation:** Seamlessly rotates log files when they reach configurable size limits (`max_size_mb`),
@ -47,8 +47,8 @@ using atomic operations and channels.
## Installation
```bash
go get github.com/LixenWraith/log
go get github.com/LixenWraith/config
go get github.com/lixenwraith/log
go get github.com/lixenwraith/config
```
## Basic Usage
@ -59,7 +59,7 @@ This example shows minimal initialization using defaults with a single override,
package main
import (
"github.com/LixenWraith/log"
"github.com/lixenwraith/log"
)
func main() {
@ -287,7 +287,7 @@ err := logger.InitWithDefaults(
condition is resolved.
- **Configuration Dependencies:**
For full configuration management (TOML file loading, CLI overrides, etc.), the `github.com/LixenWraith/config` package is required when using the `Init` method. For simpler initialization without this external dependency, use `InitWithDefaults`.
For full configuration management (TOML file loading, CLI overrides, etc.), the `github.com/lixenwraith/config` package is required when using the `Init` method. For simpler initialization without this external dependency, use `InitWithDefaults`.
- **Retention Accuracy:** Log retention relies on file modification times, which could potentially be affected by
external file system operations.

188
compat/README.md Normal file
View File

@ -0,0 +1,188 @@
# Compatibility Adapters for lixenwraith/log
This package provides compatibility adapters to use the `github.com/lixenwraith/log` logger with popular Go networking frameworks:
- **gnet v2**: High-performance event-driven networking framework
- **fasthttp**: Fast HTTP implementation
## Features
- ✅ Full interface compatibility with both frameworks
- ✅ Preserves structured logging capabilities
- ✅ Configurable fatal behavior for gnet
- ✅ Automatic log level detection for fasthttp
- ✅ Optional structured field extraction from printf formats
- ✅ Thread-safe and high-performance
- ✅ Shared logger instance for multiple adapters
## Installation
```bash
go get github.com/lixenwraith/log
```
## Quick Start
### Basic Usage with gnet
```go
import (
"github.com/lixenwraith/log"
"github.com/lixenwraith/log/compat"
"github.com/panjf2000/gnet/v2"
)
// Create and configure logger
logger := log.NewLogger()
logger.InitWithDefaults("directory=/var/log/gnet", "level=-4")
defer logger.Shutdown()
// Create gnet adapter
adapter := compat.NewGnetAdapter(logger)
// Use with gnet
gnet.Run(eventHandler, "tcp://127.0.0.1:9000", gnet.WithLogger(adapter))
```
### Basic Usage with fasthttp
```go
import (
"github.com/lixenwraith/log"
"github.com/lixenwraith/log/compat"
"github.com/valyala/fasthttp"
)
// Create and configure logger
logger := log.NewLogger()
logger.InitWithDefaults("directory=/var/log/fasthttp")
defer logger.Shutdown()
// Create fasthttp adapter
adapter := compat.NewFastHTTPAdapter(logger)
// Use with fasthttp
server := &fasthttp.Server{
Handler: requestHandler,
Logger: adapter,
}
server.ListenAndServe(":8080")
```
### Using the Builder Pattern
```go
// Create adapters with shared configuration
builder := compat.NewBuilder().
WithOptions(
"directory=/var/log/app",
"level=0",
"format=json",
"max_size_mb=100",
)
gnetAdapter, fasthttpAdapter, err := builder.Build()
if err != nil {
panic(err)
}
defer builder.GetLogger().Shutdown()
```
## Advanced Features
### Structured Field Extraction
The structured adapters can extract key-value pairs from printf-style format strings:
```go
// Use structured adapter
adapter := compat.NewStructuredGnetAdapter(logger)
// These calls will extract structured fields:
adapter.Infof("client=%s port=%d", "192.168.1.1", 8080)
// Logs: {"client": "192.168.1.1", "port": 8080, "source": "gnet"}
adapter.Errorf("user: %s, action: %s, error: %s", "john", "login", "invalid password")
// Logs: {"user": "john", "action": "login", "error": "invalid password", "source": "gnet"}
```
### Custom Fatal Handling
```go
adapter := compat.NewGnetAdapter(logger,
compat.WithFatalHandler(func(msg string) {
// Custom cleanup
saveState()
notifyAdmin(msg)
os.Exit(1)
}),
)
```
### Custom Level Detection for fasthttp
```go
adapter := compat.NewFastHTTPAdapter(logger,
compat.WithDefaultLevel(log.LevelInfo),
compat.WithLevelDetector(func(msg string) int64 {
if strings.Contains(msg, "CRITICAL") {
return log.LevelError
}
return 0 // Use default detection
}),
)
```
## Configuration Examples
### High-Performance Configuration
```go
builder := compat.NewBuilder().
WithOptions(
"directory=/var/log/highperf",
"level=0", // Info and above
"format=json", // Structured logs
"buffer_size=4096", // Large buffer
"flush_interval_ms=1000", // Less frequent flushes
"enable_periodic_sync=false", // Disable periodic sync
)
```
### Development Configuration
```go
builder := compat.NewBuilder().
WithOptions(
"directory=./logs",
"level=-4", // Debug level
"format=txt", // Human-readable
"show_timestamp=true",
"show_level=true",
"trace_depth=3", // Include call traces
"flush_interval_ms=100", // Frequent flushes
)
```
### Production Configuration with Monitoring
```go
builder := compat.NewBuilder().
WithOptions(
"directory=/var/log/prod",
"level=0",
"format=json",
"max_size_mb=1000", // 1GB files
"max_total_size_mb=10000", // 10GB total
"retention_period_hrs=168", // 7 days
"heartbeat_level=2", // Process + disk heartbeats
"heartbeat_interval_s=300", // 5 minutes
)
```
## Performance Considerations
1. **Printf Overhead**: The adapters must format printf-style strings, adding minimal overhead
2. **Structured Extraction**: The structured adapters use regex matching, which adds ~1-2μs per call
3. **Level Detection**: FastHTTP adapter's level detection adds <100ns for simple string checks
4. **Buffering**: The underlying logger's buffering minimizes I/O impact

72
compat/builder.go Normal file
View File

@ -0,0 +1,72 @@
// FILE: compat/builder.go
package compat
import (
"github.com/lixenwraith/log"
"github.com/panjf2000/gnet/v2"
"github.com/valyala/fasthttp"
)
// Builder provides a convenient way to create configured loggers for both frameworks
type Builder struct {
logger *log.Logger
options []string // InitWithDefaults options
}
// NewBuilder creates a new adapter builder
func NewBuilder() *Builder {
return &Builder{
logger: log.NewLogger(),
}
}
// WithOptions adds configuration options for the underlying logger
func (b *Builder) WithOptions(opts ...string) *Builder {
b.options = append(b.options, opts...)
return b
}
// Build initializes the logger and returns adapters for both frameworks
func (b *Builder) Build() (*GnetAdapter, *FastHTTPAdapter, error) {
// Initialize the logger
if err := b.logger.InitWithDefaults(b.options...); err != nil {
return nil, nil, err
}
// Create adapters
gnetAdapter := NewGnetAdapter(b.logger)
fasthttpAdapter := NewFastHTTPAdapter(b.logger)
return gnetAdapter, fasthttpAdapter, nil
}
// BuildStructured initializes the logger and returns structured adapters
func (b *Builder) BuildStructured() (*StructuredGnetAdapter, *FastHTTPAdapter, error) {
// Initialize the logger
if err := b.logger.InitWithDefaults(b.options...); err != nil {
return nil, nil, err
}
// Create adapters
gnetAdapter := NewStructuredGnetAdapter(b.logger)
fasthttpAdapter := NewFastHTTPAdapter(b.logger)
return gnetAdapter, fasthttpAdapter, nil
}
// GetLogger returns the underlying logger for direct access
func (b *Builder) GetLogger() *log.Logger {
return b.logger
}
// Example usage functions
// ConfigureGnetServer configures a gnet server with the logger
func ConfigureGnetServer(adapter *GnetAdapter, opts ...gnet.Option) []gnet.Option {
return append(opts, gnet.WithLogger(adapter))
}
// ConfigureFastHTTPServer configures a fasthttp server with the logger
func ConfigureFastHTTPServer(adapter *FastHTTPAdapter, server *fasthttp.Server) {
server.Logger = adapter
}

103
compat/fasthttp.go Normal file
View File

@ -0,0 +1,103 @@
// FILE: compat/fasthttp.go
package compat
import (
"fmt"
"strings"
"github.com/lixenwraith/log"
)
// FastHTTPAdapter wraps lixenwraith/log.Logger to implement fasthttp's Logger interface
type FastHTTPAdapter struct {
logger *log.Logger
defaultLevel int64
levelDetector func(string) int64 // Function to detect log level from message
}
// NewFastHTTPAdapter creates a new fasthttp-compatible logger adapter
func NewFastHTTPAdapter(logger *log.Logger, opts ...FastHTTPOption) *FastHTTPAdapter {
adapter := &FastHTTPAdapter{
logger: logger,
defaultLevel: log.LevelInfo,
levelDetector: DetectLogLevel, // Default level detection
}
for _, opt := range opts {
opt(adapter)
}
return adapter
}
// FastHTTPOption allows customizing adapter behavior
type FastHTTPOption func(*FastHTTPAdapter)
// WithDefaultLevel sets the default log level for Printf calls
func WithDefaultLevel(level int64) FastHTTPOption {
return func(a *FastHTTPAdapter) {
a.defaultLevel = level
}
}
// WithLevelDetector sets a custom function to detect log level from message content
func WithLevelDetector(detector func(string) int64) FastHTTPOption {
return func(a *FastHTTPAdapter) {
a.levelDetector = detector
}
}
// Printf implements fasthttp's Logger interface
func (a *FastHTTPAdapter) Printf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
// Detect log level from message content
level := a.defaultLevel
if a.levelDetector != nil {
detected := a.levelDetector(msg)
if detected != 0 {
level = detected
}
}
// Log with appropriate level
switch level {
case log.LevelDebug:
a.logger.Debug("msg", msg, "source", "fasthttp")
case log.LevelWarn:
a.logger.Warn("msg", msg, "source", "fasthttp")
case log.LevelError:
a.logger.Error("msg", msg, "source", "fasthttp")
default:
a.logger.Info("msg", msg, "source", "fasthttp")
}
}
// DetectLogLevel attempts to detect log level from message content
func DetectLogLevel(msg string) int64 {
msgLower := strings.ToLower(msg)
// Check for error indicators
if strings.Contains(msgLower, "error") ||
strings.Contains(msgLower, "failed") ||
strings.Contains(msgLower, "fatal") ||
strings.Contains(msgLower, "panic") {
return log.LevelError
}
// Check for warning indicators
if strings.Contains(msgLower, "warn") ||
strings.Contains(msgLower, "warning") ||
strings.Contains(msgLower, "deprecated") {
return log.LevelWarn
}
// Check for debug indicators
if strings.Contains(msgLower, "debug") ||
strings.Contains(msgLower, "trace") {
return log.LevelDebug
}
// Default to info level
return log.LevelInfo
}

79
compat/gnet.go Normal file
View File

@ -0,0 +1,79 @@
// FILE: compat/gnet.go
package compat
import (
"fmt"
"os"
"time"
"github.com/lixenwraith/log"
)
// GnetAdapter wraps lixenwraith/log.Logger to implement gnet's logging.Logger interface
type GnetAdapter struct {
logger *log.Logger
fatalHandler func(msg string) // Customizable fatal behavior
}
// NewGnetAdapter creates a new gnet-compatible logger adapter
func NewGnetAdapter(logger *log.Logger, opts ...GnetOption) *GnetAdapter {
adapter := &GnetAdapter{
logger: logger,
fatalHandler: func(msg string) {
os.Exit(1) // Default behavior matches gnet expectations
},
}
for _, opt := range opts {
opt(adapter)
}
return adapter
}
// GnetOption allows customizing adapter behavior
type GnetOption func(*GnetAdapter)
// WithFatalHandler sets a custom fatal handler
func WithFatalHandler(handler func(string)) GnetOption {
return func(a *GnetAdapter) {
a.fatalHandler = handler
}
}
// Debugf logs at debug level with printf-style formatting
func (a *GnetAdapter) Debugf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
a.logger.Debug("msg", msg, "source", "gnet")
}
// Infof logs at info level with printf-style formatting
func (a *GnetAdapter) Infof(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
a.logger.Info("msg", msg, "source", "gnet")
}
// Warnf logs at warn level with printf-style formatting
func (a *GnetAdapter) Warnf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
a.logger.Warn("msg", msg, "source", "gnet")
}
// Errorf logs at error level with printf-style formatting
func (a *GnetAdapter) Errorf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
a.logger.Error("msg", msg, "source", "gnet")
}
// Fatalf logs at error level and triggers fatal handler
func (a *GnetAdapter) Fatalf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
a.logger.Error("msg", msg, "source", "gnet", "fatal", true)
// Ensure log is flushed before exit
_ = a.logger.Flush(100 * time.Millisecond)
if a.fatalHandler != nil {
a.fatalHandler(msg)
}
}

131
compat/structured.go Normal file
View File

@ -0,0 +1,131 @@
// FILE: compat/structured.go
package compat
import (
"fmt"
"regexp"
"strings"
"github.com/lixenwraith/log"
)
// parseFormat attempts to extract structured fields from printf-style format strings
// This is useful for preserving structured logging semantics
func parseFormat(format string, args []interface{}) []interface{} {
// Pattern to detect common structured patterns like "key=%v" or "key: %v"
keyValuePattern := regexp.MustCompile(`(\w+)\s*[:=]\s*%[vsdqxXeEfFgGpbcU]`)
matches := keyValuePattern.FindAllStringSubmatchIndex(format, -1)
if len(matches) == 0 || len(matches) > len(args) {
// Fallback to simple message if pattern doesn't match
return []interface{}{"msg", fmt.Sprintf(format, args...)}
}
// Build structured fields
fields := make([]interface{}, 0, len(matches)*2+2)
lastEnd := 0
argIndex := 0
for _, match := range matches {
// Add any text before this match as part of the message
if match[0] > lastEnd {
prefix := format[lastEnd:match[0]]
if strings.TrimSpace(prefix) != "" {
if len(fields) == 0 {
fields = append(fields, "msg", strings.TrimSpace(prefix))
}
}
}
// Extract key name
keyStart := match[2]
keyEnd := match[3]
key := format[keyStart:keyEnd]
// Get corresponding value
if argIndex < len(args) {
fields = append(fields, key, args[argIndex])
argIndex++
}
lastEnd = match[1]
}
// Handle remaining format string and args
if lastEnd < len(format) {
remainingFormat := format[lastEnd:]
remainingArgs := args[argIndex:]
if len(remainingArgs) > 0 {
remaining := fmt.Sprintf(remainingFormat, remainingArgs...)
if strings.TrimSpace(remaining) != "" {
if len(fields) == 0 {
fields = append(fields, "msg", strings.TrimSpace(remaining))
} else {
// Append to existing message
for i := 0; i < len(fields); i += 2 {
if fields[i] == "msg" {
fields[i+1] = fmt.Sprintf("%v %s", fields[i+1], strings.TrimSpace(remaining))
break
}
}
}
}
}
}
return fields
}
// StructuredGnetAdapter provides enhanced structured logging for gnet
type StructuredGnetAdapter struct {
*GnetAdapter
extractFields bool
}
// NewStructuredGnetAdapter creates a gnet adapter with structured field extraction
func NewStructuredGnetAdapter(logger *log.Logger, opts ...GnetOption) *StructuredGnetAdapter {
return &StructuredGnetAdapter{
GnetAdapter: NewGnetAdapter(logger, opts...),
extractFields: true,
}
}
// Debugf logs with structured field extraction
func (a *StructuredGnetAdapter) Debugf(format string, args ...interface{}) {
if a.extractFields {
fields := parseFormat(format, args)
a.logger.Debug(append(fields, "source", "gnet")...)
} else {
a.GnetAdapter.Debugf(format, args...)
}
}
// Infof logs with structured field extraction
func (a *StructuredGnetAdapter) Infof(format string, args ...interface{}) {
if a.extractFields {
fields := parseFormat(format, args)
a.logger.Info(append(fields, "source", "gnet")...)
} else {
a.GnetAdapter.Infof(format, args...)
}
}
// Warnf logs with structured field extraction
func (a *StructuredGnetAdapter) Warnf(format string, args ...interface{}) {
if a.extractFields {
fields := parseFormat(format, args)
a.logger.Warn(append(fields, "source", "gnet")...)
} else {
a.GnetAdapter.Warnf(format, args...)
}
}
// Errorf logs with structured field extraction
func (a *StructuredGnetAdapter) Errorf(format string, args ...interface{}) {
if a.extractFields {
fields := parseFormat(format, args)
a.logger.Error(append(fields, "source", "gnet")...)
} else {
a.GnetAdapter.Errorf(format, args...)
}
}

View File

@ -1,4 +1,4 @@
// --- File: config.go ---
// FILE: config.go
package log
import (

75
example/fasthttp/main.go Normal file
View File

@ -0,0 +1,75 @@
// FILE: examples/fasthttp/main.go
package main
import (
"fmt"
"strings"
"time"
"github.com/lixenwraith/log"
"github.com/lixenwraith/log/compat"
"github.com/valyala/fasthttp"
)
func main() {
// Create and configure logger
logger := log.NewLogger()
err := logger.InitWithDefaults(
"directory=/var/log/fasthttp",
"level=0",
"format=txt",
"buffer_size=2048",
)
if err != nil {
panic(err)
}
defer logger.Shutdown()
// Create fasthttp adapter with custom level detection
fasthttpAdapter := compat.NewFastHTTPAdapter(
logger,
compat.WithDefaultLevel(log.LevelInfo),
compat.WithLevelDetector(customLevelDetector),
)
// Configure fasthttp server
server := &fasthttp.Server{
Handler: requestHandler,
Logger: fasthttpAdapter,
// Other server settings
Name: "MyServer",
Concurrency: fasthttp.DefaultConcurrency,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
TCPKeepalive: true,
ReduceMemoryUsage: true,
}
// Start server
fmt.Println("Starting server on :8080")
if err := server.ListenAndServe(":8080"); err != nil {
panic(err)
}
}
func requestHandler(ctx *fasthttp.RequestCtx) {
ctx.SetContentType("text/plain")
fmt.Fprintf(ctx, "Hello, world! Path: %s\n", ctx.Path())
}
func customLevelDetector(msg string) int64 {
// Custom logic to detect log levels
// Can inspect specific fasthttp message patterns
if strings.Contains(msg, "connection cannot be served") {
return log.LevelWarn
}
if strings.Contains(msg, "error when serving connection") {
return log.LevelError
}
// Use default detection
return compat.detectLogLevel(msg)
}

47
example/gnet/main.go Normal file
View File

@ -0,0 +1,47 @@
// FILE: example/gnet/main.go
package main
import (
"github.com/lixenwraith/log"
"github.com/lixenwraith/log/compat"
"github.com/panjf2000/gnet/v2"
)
// Example gnet event handler
type echoServer struct {
gnet.BuiltinEventEngine
}
func (es *echoServer) OnTraffic(c gnet.Conn) gnet.Action {
buf, _ := c.Next(-1)
c.Write(buf)
return gnet.None
}
func main() {
// Method 1: Simple adapter
logger := log.NewLogger()
err := logger.InitWithDefaults(
"directory=/var/log/gnet",
"level=-4", // Debug level
"format=json",
)
if err != nil {
panic(err)
}
defer logger.Shutdown()
gnetAdapter := compat.NewGnetAdapter(logger)
// Configure gnet server with the logger
err = gnet.Run(
&echoServer{},
"tcp://127.0.0.1:9000",
gnet.WithMulticore(true),
gnet.WithLogger(gnetAdapter),
gnet.WithReusePort(true),
)
if err != nil {
panic(err)
}
}

View File

@ -1,3 +1,4 @@
// FILE: example/heartbeat/main.go
package main
import (
@ -5,7 +6,7 @@ import (
"os"
"time"
"github.com/LixenWraith/log"
"github.com/lixenwraith/log"
)
func main() {

View File

@ -1,3 +1,4 @@
// FILE: example/reconfig/main.go
package main
import (
@ -5,7 +6,7 @@ import (
"sync/atomic"
"time"
"github.com/LixenWraith/log"
"github.com/lixenwraith/log"
)
// Simulate rapid reconfiguration

View File

@ -1,3 +1,4 @@
// FILE: example/simple/main.go
package main
import (
@ -6,8 +7,8 @@ import (
"sync"
"time"
"github.com/LixenWraith/config"
"github.com/LixenWraith/log"
"github.com/lixenwraith/config"
"github.com/lixenwraith/log"
)
const configFile = "simple_config.toml"
@ -51,7 +52,7 @@ func main() {
// Load config from file (and potentially CLI args - none provided here)
// The log package will register its keys during Init
_, err = cfg.Load(configFile, nil) // os.Args[1:] could be used here
err = cfg.Load(configFile, nil) // os.Args[1:] could be used here
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to load config: %v. Using defaults.\n", err)
// Proceeding, log.Init will use registered defaults

View File

@ -1,3 +1,4 @@
// FILE: example/stress/main.go
package main
import (
@ -11,8 +12,8 @@ import (
"syscall"
"time"
"github.com/LixenWraith/config"
"github.com/LixenWraith/log"
"github.com/lixenwraith/config"
"github.com/lixenwraith/log"
)
const (
@ -121,7 +122,7 @@ func main() {
// defer os.RemoveAll(logsDir) // Remove to keep the log directory
cfg := config.New()
_, err = cfg.Load(configFile, nil)
err = cfg.Load(configFile, nil)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to load config: %v.\n", err)
os.Exit(1)

View File

@ -1,4 +1,4 @@
// --- File: format.go ---
// FILE: format.go
package log
import (

19
go.mod
View File

@ -1,10 +1,23 @@
module github.com/LixenWraith/log
module github.com/lixenwraith/log
go 1.24.2
go 1.24.4
require github.com/LixenWraith/config v0.0.0-20250426061518-532233ac282c
require (
github.com/lixenwraith/config v0.0.0-20250701170607-8515fa0543b6
github.com/panjf2000/gnet/v2 v2.9.1
github.com/valyala/fasthttp v1.63.0
)
require (
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/panjf2000/ants/v2 v2.11.3 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
)

38
go.sum
View File

@ -1,6 +1,40 @@
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/LixenWraith/config v0.0.0-20250426061518-532233ac282c h1:3JcYZVGF+OOfm72eOE2LLFHU9ERYSKs76jJOxpB/4FQ=
github.com/LixenWraith/config v0.0.0-20250426061518-532233ac282c/go.mod h1:3cBfqRthYrMGIkea2GXyMVPNxVWSYt2FkeWG1Zyv2Ow=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/lixenwraith/config v0.0.0-20250701170607-8515fa0543b6 h1:qE4SpAJWFaLkdRyE0FjTPBBRYE7LOvcmRCB5p86W73Q=
github.com/lixenwraith/config v0.0.0-20250701170607-8515fa0543b6/go.mod h1:4wPJ3HnLrYrtUwTinngCsBgtdIXsnxkLa7q4KAIbwY8=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg=
github.com/panjf2000/ants/v2 v2.11.3/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek=
github.com/panjf2000/gnet/v2 v2.9.1 h1:bKewICy/0xnQ9PMzNaswpe/Ah14w1TrRk91LHTcbIlA=
github.com/panjf2000/gnet/v2 v2.9.1/go.mod h1:WQTxDWYuQ/hz3eccH0FN32IVuvZ19HewEWx0l62fx7E=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.63.0 h1:DisIL8OjB7ul2d7cBaMRcKTQDYnrGy56R4FCiuDP0Ns=
github.com/valyala/fasthttp v1.63.0/go.mod h1:REc4IeW+cAEyLrRPa5A81MIjvz0QE1laoTX2EaPHKJM=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,4 +1,4 @@
// --- File: interface.go ---
// FILE: interface.go
package log
import (

View File

@ -1,4 +1,4 @@
// --- File: logger.go ---
// FILE: logger.go
package log
import (
@ -9,7 +9,7 @@ import (
"sync"
"time"
"github.com/LixenWraith/config"
"github.com/lixenwraith/config"
)
// Logger is the core struct that encapsulates all logger functionality

View File

@ -1,4 +1,4 @@
// --- File: processor.go ---
// FILE: processor.go
package log
import (

View File

@ -1,4 +1,4 @@
// --- File: state.go ---
// FILE: state.go
package log
import (
@ -9,7 +9,7 @@ import (
"sync/atomic"
"time"
"github.com/LixenWraith/config"
"github.com/lixenwraith/config"
)
// State encapsulates the runtime state of the logger

View File

@ -1,3 +1,4 @@
// FILE: storage.go
package log
import (

View File

@ -1,4 +1,4 @@
// --- File: utility.go ---
// FILE: utility.go
package log
import (