golang简单分级日志记录封装插件库log的使用
Golang 简单分级日志记录封装插件库 log 的使用
log
是一个基于标准 log 包的简单分级日志记录库。
特性
- 😻 分级日志记录
- 😚 简单的 API
- 🤝 兼容
fmt
包 - 👌 零依赖
- 😮💨 没有全局日志记录器
- 👏 没有复杂的结构化日志
安装
go get github.com/heartwilltell/log
分级日志
StdLog
实现了一个简单的接口:
// Logger 根据 fmt 包的标准格式说明符格式化消息,
// 并将消息写入由具体接口实现指定的写入器。
type Logger interface {
// Error 格式化并写入错误级别消息。
Error(format string, v ...any)
// Warning 格式化并写入警告级别消息。
Warning(format string, v ...any)
// Info 格式化并写入信息级别消息。
Info(format string, v ...any)
// Debug 格式化并写入调试级别消息。
Debug(format string, v ...any)
}
使用
👇 使用非常简单。只需创建一个日志记录器实例并调用任何分级方法。
logger := log.New()
logger.Info("Listen on port: %d", 8080)
设置日志级别为 debug
logger := log.New(log.WithLevel(log.DBG))
解析字符串为级别并创建 warning 级别的日志记录器
level, levelErr := log.ParseLevel("warning")
if levelErr != nil {
// 处理错误
}
logger := log.New(log.WithLevel(level))
使用不同的 io.Writer 创建日志记录器
var w bytes.Buffer
logger := log.New(log.WithWriter(w))
禁用彩色输出
logger := log.New(log.WithNoColor())
设置 UTC 时间格式
logger := log.New(log.WithUTC())
启用打印代码行号
// 短格式:
// INF: 2022/07/08 11:22:30 server.go:111: message
logger := log.New(log.WithLineNum(log.ShortFmt))
或
// 长格式:
// INF: 2022/07/08 11:22:30 /Users/heartwilltell/Go/app/server.go:111: message
logger := log.New(log.WithLineNum(log.LongFmt))
将级别标记放在日志前缀的末尾
logger := log.New(log.WithLevelAtPrefixEnd())
将产生这样的输出 👇
// 2022/07/08 11:22:30 INF: message
而不是这样 👇
// INF: 2022/07/08 11:22:30: message
创建无操作日志记录器
logger := log.NewNopLog()
💡 适用于测试或默认情况下应禁用日志记录的地方
完整示例
package main
import (
"bytes"
"github.com/heartwilltell/log"
)
func main() {
// 基本用法
logger := log.New()
logger.Info("Application started")
logger.Warning("This is a warning message")
logger.Error("Error occurred: %s", "file not found")
// 设置调试级别
debugLogger := log.New(log.WithLevel(log.DBG))
debugLogger.Debug("Debug message will be shown")
// 自定义写入器
var buf bytes.Buffer
customWriterLogger := log.New(log.WithWriter(&buf))
customWriterLogger.Info("This goes to buffer")
// 禁用颜色和UTC时间
noColorLogger := log.New(log.WithNoColor(), log.WithUTC())
noColorLogger.Info("No color and UTC time")
// 带行号的日志
lineNumLogger := log.New(log.WithLineNum(log.ShortFmt))
lineNumLogger.Info("This message includes file and line number")
}
许可证
MIT License。
更多关于golang简单分级日志记录封装插件库log的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang简单分级日志记录封装插件库log的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 分级日志记录封装库使用指南
在Go语言中实现分级日志记录可以帮助我们更好地管理和调试应用程序。下面我将介绍一个简单的分级日志记录封装库的实现和使用方法。
基础日志封装实现
首先,我们创建一个简单的日志封装库,支持不同级别的日志记录:
package log
import (
"fmt"
"io"
"os"
"sync"
"time"
)
// 日志级别类型
type Level int
const (
LevelDebug Level = iota
LevelInfo
LevelWarn
LevelError
LevelFatal
)
var levelNames = []string{
"DEBUG",
"INFO",
"WARN",
"ERROR",
"FATAL",
}
// Logger 日志记录器
type Logger struct {
mu sync.Mutex
output io.Writer
level Level
}
// NewLogger 创建新的日志记录器
func NewLogger(output io.Writer, level Level) *Logger {
return &Logger{
output: output,
level: level,
}
}
// 默认日志记录器
var defaultLogger = NewLogger(os.Stderr, LevelInfo)
// SetOutput 设置日志输出
func SetOutput(w io.Writer) {
defaultLogger.mu.Lock()
defer defaultLogger.mu.Unlock()
defaultLogger.output = w
}
// SetLevel 设置日志级别
func SetLevel(level Level) {
defaultLogger.mu.Lock()
defer defaultLogger.mu.Unlock()
defaultLogger.level = level
}
// log 内部日志记录方法
func (l *Logger) log(level Level, format string, args ...interface{}) {
if level < l.level {
return
}
now := time.Now().Format("2006-01-02 15:04:05")
msg := fmt.Sprintf(format, args...)
logEntry := fmt.Sprintf("[%s] %s %s\n", now, levelNames[level], msg)
l.mu.Lock()
defer l.mu.Unlock()
_, _ = fmt.Fprint(l.output, logEntry)
}
// 导出各级别日志方法
func Debug(format string, args ...interface{}) {
defaultLogger.log(LevelDebug, format, args...)
}
func Info(format string, args ...interface{}) {
defaultLogger.log(LevelInfo, format, args...)
}
func Warn(format string, args ...interface{}) {
defaultLogger.log(LevelWarn, format, args...)
}
func Error(format string, args ...interface{}) {
defaultLogger.log(LevelError, format, args...)
}
func Fatal(format string, args ...interface{}) {
defaultLogger.log(LevelFatal, format, args...)
os.Exit(1)
}
使用示例
下面是如何使用这个日志库的示例:
package main
import (
"os"
"./log" // 替换为你的实际包路径
)
func main() {
// 设置日志级别为Debug
log.SetLevel(log.LevelDebug)
// 设置日志输出到文件
file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatal("无法打开日志文件: %v", err)
}
defer file.Close()
log.SetOutput(file)
// 记录不同级别的日志
log.Debug("这是一条调试信息")
log.Info("应用程序启动")
log.Warn("警告: 配置项缺失, 使用默认值")
log.Error("处理请求时出错: %v", "连接超时")
// 业务逻辑
processData()
}
func processData() {
log.Debug("开始处理数据")
// 模拟处理过程
log.Info("数据处理完成")
}
高级功能扩展
如果需要更高级的功能,可以扩展上述基础实现:
- JSON格式日志:
func (l *Logger) jsonLog(level Level, format string, args ...interface{}) {
if level < l.level {
return
}
entry := map[string]interface{}{
"timestamp": time.Now().Format(time.RFC3339),
"level": levelNames[level],
"message": fmt.Sprintf(format, args...),
}
jsonData, _ := json.Marshal(entry)
l.mu.Lock()
defer l.mu.Unlock()
_, _ = fmt.Fprintln(l.output, string(jsonData))
}
- 日志轮转:
可以使用第三方库如
lumberjack
实现日志文件轮转:
import "gopkg.in/natefinch/lumberjack.v2"
func setupLogRotation() {
log.SetOutput(&lumberjack.Logger{
Filename: "app.log",
MaxSize: 100, // MB
MaxBackups: 3,
MaxAge: 28, // days
Compress: true,
})
}
- 上下文日志:
func WithFields(fields map[string]interface{}) *Entry {
return &Entry{
logger: defaultLogger,
fields: fields,
}
}
type Entry struct {
logger *Logger
fields map[string]interface{}
}
func (e *Entry) Info(format string, args ...interface{}) {
// 将fields和消息一起记录
}
最佳实践
- 在应用程序启动时配置日志级别和输出
- 生产环境使用
LevelInfo
或更高级别 - 开发环境可以使用
LevelDebug
以便调试 - 错误日志应该包含足够的上下文信息
- 避免在热路径上记录过多调试日志
这个简单的日志库已经能满足大多数基本需求,如果需要更复杂的功能,可以考虑使用成熟的日志库如zap
、logrus
或zerolog
。