A high-performance, feature-rich logging library for Go applications with multi-build tag support, async writing, and extensive customization options.
- 🚀 High Performance: Object pooling and async writing support
- 🏗️ Build Tag Support: Different behaviors for debug, release, and discard modes
- 🔄 Log Rotation: Automatic hourly log file rotation
- 🎨 Rich Formatting: Customizable log formats with color support
- 🔍 Context Tracing: Goroutine ID and trace ID tracking
- 🔌 Framework Integration: Native Zap logger integration
- ⚙️ Highly Configurable: Flexible levels, outputs, and formatting
- 🧪 Well Tested: 93.0% test coverage with 284+ test cases across all build configurations
go get github.com/lazygophers/log
package main
import (
"github.com/lazygophers/log"
)
func main() {
// Simple logging
log.Info("Hello, World!")
log.Debug("This is a debug message")
log.Warn("This is a warning")
log.Error("This is an error")
// Formatted logging
log.Infof("User %s logged in with ID %d", "john", 123)
// With custom logger
logger := log.New()
logger.SetLevel(log.InfoLevel)
logger.Info("Custom logger message")
}
package main
import (
"context"
"os"
"github.com/lazygophers/log"
)
func main() {
// Create logger with file output
logger := log.New()
// Set output to file with hourly rotation
writer := log.GetOutputWriterHourly("./logs/app.log")
logger.SetOutput(writer)
// Configure formatting
logger.SetLevel(log.DebugLevel)
logger.SetPrefixMsg("[APP] ")
logger.Caller(true) // Enable caller info
// Context logging
ctxLogger := logger.CloneToCtx()
ctxLogger.Info(context.Background(), "Context-aware logging")
// Async logging for high-throughput scenarios
asyncWriter := log.NewAsyncWriter(writer, 1000)
logger.SetOutput(asyncWriter)
defer asyncWriter.Close()
logger.Info("High-performance async logging")
}
The library supports different build modes through Go build tags:
go build
- Full logging functionality
- Debug messages enabled
- Standard performance
go build -tags debug
- Enhanced debug information
- Detailed caller information
- Performance profiling support
go build -tags release
- Optimized for production
- Debug messages disabled
- Automatic log file rotation
go build -tags discard
- Maximum performance
- All logs discarded
- Zero logging overhead
go build -tags "debug,discard" # Debug with discard
go build -tags "release,discard" # Release with discard
The library supports 7 log levels (from highest to lowest priority):
Level | Value | Description |
---|---|---|
PanicLevel |
0 | Logs and then calls panic |
FatalLevel |
1 | Logs and then calls os.Exit(1) |
ErrorLevel |
2 | Error conditions |
WarnLevel |
3 | Warning conditions |
InfoLevel |
4 | Informational messages |
DebugLevel |
5 | Debug-level messages |
TraceLevel |
6 | Most verbose logging |
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/lazygophers/log"
)
// Create a zap logger that writes to our log system
logger := log.New()
hook := log.NewZapHook(logger)
core := zapcore.NewCore(
zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
hook,
zapcore.InfoLevel,
)
zapLogger := zap.New(core)
zapLogger.Info("Message from Zap", zap.String("key", "value"))
The library comes with comprehensive testing support:
# Run all tests
make test
# Run tests with coverage for all build tags
make coverage-all
# Quick test across all build tags
make test-quick
# Generate HTML coverage reports
make coverage-html
Build Tag | Coverage | Description |
---|---|---|
Default | 93.3% | Standard build with full debugging |
Debug | 93.5% | Enhanced debug information |
Release | 93.0% | Production-optimized build |
Discard | 93.5% | Maximum performance, no-op logging |
Debug+Discard | 93.5% | Debug with discard optimization |
Release+Discard | 93.7% | Release with discard optimization |
- Total Test Functions: 284+
- Functions with 100% Coverage: 125/138 (90.6%)
- Build Tag Combinations Tested: 6/6
- Excluded from Coverage: Fatal/Panic functions (safety reasons)
logger := log.New()
// Set minimum log level
logger.SetLevel(log.InfoLevel)
// Configure output
logger.SetOutput(os.Stdout) // Single writer
logger.SetOutput(writer1, writer2, writer3) // Multiple writers
// Customize messages
logger.SetPrefixMsg("[MyApp] ")
logger.SetSuffixMsg(" [END]")
logger.AppendPrefixMsg("Extra: ")
// Configure formatting
logger.ParsingAndEscaping(false) // Disable escape sequences
logger.Caller(true) // Enable caller information
logger.SetCallerDepth(4) // Adjust caller stack depth
Automatic log rotation with configurable intervals:
// Hourly rotation
writer := log.GetOutputWriterHourly("./logs/app.log")
// The library will create files like:
// - app-2024010115.log (2024-01-01 15:00)
// - app-2024010116.log (2024-01-01 16:00)
// - app-2024010117.log (2024-01-01 17:00)
Built-in support for context-aware logging and distributed tracing:
// Set trace ID for current goroutine
log.SetTrace("trace-123-456")
// Get trace ID
traceID := log.GetTrace()
// Context-aware logging
ctx := context.Background()
ctxLogger := log.CloneToCtx()
ctxLogger.Info(ctx, "Request processed", "user_id", 123)
// Automatic goroutine ID tracking
log.Info("This log includes goroutine ID automatically")
The library is designed for high-performance applications:
- Object Pooling: Reuses log entry objects to reduce GC pressure
- Async Writing: Non-blocking log writes for high-throughput scenarios
- Level Filtering: Early filtering prevents expensive operations
- Build Tag Optimization: Compile-time optimization for different environments
# Run performance benchmarks
make benchmark
# Benchmark different build modes
make benchmark-debug
make benchmark-release
make benchmark-discard
We welcome contributions! Please see our Contributing Guide for details.
-
Fork and Clone
git clone https://github.com/your-username/log.git cd log
-
Install Dependencies
go mod tidy
-
Run Tests
make test-all
-
Submit Pull Request
- Follow our PR Template
- Ensure tests pass
- Update documentation if needed
- Go: 1.21 or higher
- Dependencies:
go.uber.org/zap
(for Zap integration)github.com/petermattis/goid
(for goroutine ID)github.com/lestrrat-go/file-rotatelogs
(for log rotation)github.com/google/uuid
(for trace IDs)
This project is licensed under the MIT License - see the LICENSE file for details.
- Zap for inspiration and integration support
- Logrus for level design patterns
- The Go community for continuous feedback and improvements
- 📖 Documentation
- 🐛 Issue Tracker
- 💬 Discussions
- 📧 Email: support@lazygophers.com
Made with ❤️ by the LazyGophers team
lazygophers/log
提供了一套优雅、直观的 API,摒弃了繁杂的配置,让您专注于业务逻辑本身。通过实现 io.Writer
和 Format
接口,您可以随心所欲地定制日志的输出目标与展现形式,无论是写入文件、发送到远程服务,还是集成到您自己的监控系统,都游刃有余。
- 多日志级别:
Trace
,Debug
,Info
,Warn
,Error
,Fatal
,Panic
- 灵活输出目标: 支持同时向多个
io.Writer
输出。 - 自定义格式: 通过实现
Format
接口,轻松定制 JSON、Logfmt 等任意格式。 - 调用栈追踪: 精准定位日志来源(文件、行号、函数名)。
- 协程安全: 所有方法均为协程安全。
- 性能导向: 清晰的性能优化路线图,致力于零内存分配。
我们始终致力于将 lazygophers/log
打造成一款高性能、功能丰富的日志库。通过最近的基准测试,我们对当前版本的性能有了清晰的认识,并制定了明确的优化路线图。
以下是当前版本与业界领先的 zap.SugaredLogger
在相同条件下的性能对比。
- CPU: Apple M3
- Go: 1.23.0
测试场景 (Benchmark) | lazygophers/log (耗时/操作) |
zap.SugaredLogger (耗时/操作) |
内存分配 (allocs/op) |
---|---|---|---|
简单日志 (Simple) | 944.6 ns/op | 207.8 ns/op | 9 allocs/op |
带5个字段 (With 5 Fields) | 1343 ns/op | 746.3 ns/op | 13 allocs/op |
格式化日志 (Infof) | 1002 ns/op | 301.4 ns/op | 9 allocs/op |
当前版本在性能上与 zap
存在一定差距,主要瓶颈在于内存分配。性能优化将是下一阶段的核心任务。
- v0.2.0 - 内存优化: 全面引入
sync.Pool
对象池技术,复用日志对象,显著减少高频日志场景下的内存分配和GC压力。 - v0.3.0 - API 优化: 引入
With
方法,支持结构化上下文日志,进一步提升字段处理效率。 - 长期 - 零分配探索: 探索在特定场景下实现零内存分配的可能性。
我们相信,通过持续的迭代和优化,lazygophers/log
将在性能上达到一流水准。欢迎您关注我们的进展,也欢迎随时提出宝贵的建议!
go get github.com/lazygophers/log
package main
import "github.com/lazygophers/log"
func main() {
// 默认级别为 Info
log.Info("Application started")
log.Debug("This is a debug message") // 这条日志不会被输出
log.SetLevel(log.DebugLevel)
log.Debug("Now, this debug message will be visible.")
log.Warnf("User %s might not have permission", "Alice")
log.Error("Failed to connect to the database")
}
您可以轻松地将日志同时输出到多个目标,例如,同时在控制台显示 INFO
级别以上的日志,并将所有日志(包括 DEBUG
)保存到文件。
package main
import (
"os"
"github.com/lazygophers/log"
)
func main() {
logFile, _ := os.Create("app.log")
defer logFile.Close()
// 同时输出到控制台和文件
log.SetOutput(os.Stdout, logFile)
log.SetLevel(log.DebugLevel)
log.Info("This message appears on both stdout and in app.log.")
log.Debug("This message only appears in app.log.")
}
通过实现 Format
接口,您可以创建自己的日志格式,比如输出结构化的 JSON。
package main
import (
"encoding/json"
"os"
"github.com/lazygophers/log"
)
// JSONFormatter 实现了 log.Format 接口
type JSONFormatter struct{}
// Format 将日志条目格式化为 JSON
func (f *JSONFormatter) Format(entry *log.Entry) []byte {
data := map[string]interface{}{
"level": entry.Level.String(),
"time": entry.Time,
"message": entry.Message,
"caller": entry.CallerName,
}
serialized, _ := json.Marshal(data)
return append(serialized, '\n')
}
func main() {
jsonLogger := log.New()
jsonLogger.SetFormatter(&JSONFormatter{})
jsonLogger.SetOutput(os.Stdout)
jsonLogger.Info("This is a JSON formatted log.")
jsonLogger.Warnf("User %s login failed.", "admin")
}
使用内置的 GetOutputWriterHourly
可以方便地实现日志文件的按小时轮转和自动清理。
package main
import (
"time"
"github.com/lazygophers/log"
)
func main() {
// 日志将写入 logs/access-YYYY-MM-DD-HH.log,并按小时分割
fileWriter := log.GetOutputWriterHourly("logs/access")
log.SetOutput(fileWriter)
log.Info("Service started, access log recording.")
}
通过 Clone()
或 New()
,您可以为应用的不同模块创建独立的 Logger
实例,它们可以拥有完全不同的配置(级别、输出、格式等),互不干扰。
package main
import (
"os"
"github.com/lazygophers/log"
)
func main() {
// 全局 logger
log.Info("Message from the global logger.")
// 为数据库模块创建一个独立的 logger
dbLogger := log.New()
dbLogger.SetPrefix("[Database]")
// 为 HTTP 模块克隆并配置一个新的 logger
httpLogger := dbLogger.Clone()
httpLogger.SetPrefix("[HTTP]")
dbLogger.Debug("Connecting to the database...")
httpLogger.Info("New request received: /api/users")
}
方法 | 描述 |
---|---|
SetLevel(level Level) |
设置日志级别。 |
SetOutput(w ...io.Writer) |
设置一个或多个输出目标。 |
SetFormatter(f Format) |
设置自定义的日志格式化器。 |
SetCallerDepth(d int) |
调整调用栈深度,用于封装场景。 |
SetPrefix(p string) |
为每条日志添加统一前缀。 |
New() *Logger |
创建一个全新的、独立的 Logger 实例。 |
Clone() *Logger |
创建一个继承当前配置的 Logger 副本。 |
Trace(v ...any)
/Tracef(format string, v ...any)
Debug(v ...any)
/Debugf(format string, v ...any)
Info(v ...any)
/Infof(format string, v ...any)
Warn(v ...any)
/Warnf(format string, v ...any)
Error(v ...any)
/Errorf(format string, v ...any)
Fatal(v ...any)
/Fatalf(format string, v ...any)
(执行后调用os.Exit(1)
)Panic(v ...any)
/Panicf(format string, v ...any)
(执行后调用panic()
)
欢迎各种形式的贡献!无论是提交 Issue、发起 Pull Request,还是改进文档,我们都非常欢迎。
- Fork 本仓库
- 创建您的特性分支 (
git checkout -b feature/your-amazing-feature
) - 提交您的更改 (
git commit -am 'Add some amazing feature'
) - 推送到分支 (
git push origin feature/your-amazing-feature
) - 创建一个 Pull Request
本项目采用 Apache 2.0 License 授权。