增强的 slog 包,支持调用者跳过功能,可在 Go 日志辅助函数中实现准确的源位置报告。
🎯 调用者跳过支持: 提供类似 zap.AddCallerSkip 的 WithCallerSkip 功能
📍 准确的源位置: 在嵌套的辅助函数中保持正确的调用者信息
🔗 1:1 API 兼容: 完全兼容 slog.Logger 接口
🍬 SugaredLogger 支持: 包含类似 zap.SugaredLogger 的平铺参数日志记录
⚡ 全域变量: 即用型 LOG 和 SUG 全域日志器
go get github.com/yylego/slogxpackage main
import (
"github.com/yylego/slogx"
)
func main() {
// 使用全局 LOG 进行结构化日志记录
slogx.LOG.Info("application started", "version", "1.0.0", "mode", "production")
// 使用全局 SUG 进行平铺参数日志记录
slogx.SUG.Info("client", "alice", "logged in")
// SUG 的 Infoln 在参数之间添加空格
slogx.SUG.Infoln("Processing", "item", 123, "of", 456)
// Debug 级别日志记录结构化数据
slogx.LOG.Debug("database query", "table", "clients", "duration", "45ms")
// Warning 级别使用平铺参数
slogx.SUG.Warn("high", "memory", "usage", 85, "%")
}⬆️ 源码: 源码
package main
import (
"log/slog"
"os"
"github.com/yylego/slogx"
)
// logHelper 演示辅助函数中的栈帧跳过
func logHelper(instance *slogx.Logger, message string) {
// 跳过 1 帧以显示 logHelper 调用点而不是此函数
instance.Skip(1).Info(message, "from", "assist function")
}
// nestedLogHelper 演示多级栈帧跳过
func nestedLogHelper(instance *slogx.Logger, operation string) {
// 跳过 2 帧以显示原始调用点
instance.Skip(2).Info("nested operation", "op", operation)
}
func main() {
// 创建带有 JSON handler 的自定义 slog 日志实例
jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
Level: slog.LevelDebug,
})
baseLogger := slog.New(jsonHandler)
// 使用 slogx 包装以启用栈帧跳过支持
instance := slogx.New(baseLogger)
// 在辅助函数中使用,保持正确的源位置
logHelper(instance, "message from main")
// 不使用 skip 的直接日志记录显示当前位置
instance.Info("direct message", "level", "info")
// 使用 WithCallerSkip 作为 Skip 的替代方法
instance.WithCallerSkip(1).Warn("warning from main", "skip", 1)
// 与其他 slog 方法链式调用
instance.With("request_id", "12345").
WithGroup("app").
Info("chained logging", "status", "success")
// 演示带有多级 skip 的嵌套辅助函数
func() {
nestedLogHelper(instance, "cleanup")
}()
}⬆️ 源码: 源码
package main
import (
"context"
"log/slog"
"os"
"github.com/yylego/slogx"
)
// processData 演示在业务逻辑中使用 SugaredLogger
func processData(sugar *slogx.SugaredLogger, itemID int) {
sugar.Info("Start", "processing", "item", itemID)
sugar.Infoln("Completed", "item", itemID, "status", "success")
}
// contextLogger 演示上下文感知的日志记录
func contextLogger(sugar *slogx.SugaredLogger, ctx context.Context) {
sugar.InfoContext(ctx, "Processing", "with", "context", "data")
sugar.InfolnContext(ctx, "Status", "check", "complete")
}
func main() {
// 创建使用文本输出的自定义 handler
textHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
AddSource: false,
Level: slog.LevelInfo,
})
baseLogger := slog.New(textHandler)
// 创建 Log Instance 并转换为 SugaredLogger
instance := slogx.New(baseLogger)
sugar := instance.Sugar()
// Sprint 风格的连接,不添加额外空格
sugar.Info("Processing", "item", 123, "of", 456)
// 输出: "Processingitem123of456"
// Sprintln 风格在每个参数之间添加空格
sugar.Infoln("Processing", "item", 123, "of", 456)
// 输出: "Processing item 123 of 456"
// Warning 带有数字数据
sugar.Warn("Memory", "usage", 85.5, "%", "threshold", 80)
// 在业务逻辑函数中使用
processData(sugar, 42)
// 上下文感知的日志记录
ctx := context.Background()
contextLogger(sugar, ctx)
// 从全局 LOG 创建 SugaredLogger
globalSugar := slogx.LOG.Sugar()
globalSugar.Infoln("Using", "worldwide", "LOG", "instance")
// 结合不同的日志风格
globalSugar.Info("Event", 1, "Type", "startup")
globalSugar.Infoln("Event", 2, "Type", "ready")
}⬆️ 源码: 源码
带有调用者跳过支持的 slog.Logger 轻量级包装器:
// 创建新的 Logger 包装器
logger := slogx.New(slogLogger)
// 跳过额外的栈帧
logger.Skip(1).Info("消息")
logger.WithCallerSkip(2).Error("错误消息")
// 支持所有 slog.Logger 方法
logger.Info(msg, args...)
logger.Debug(msg, args...)
logger.Warn(msg, args...)
logger.Error(msg, args...)
logger.InfoContext(ctx, msg, args...)
logger.With(args...)
logger.WithGroup(name)提供类似 zap.SugaredLogger 的平铺参数日志记录:
// 创建 SugaredLogger
sugar := slogx.NewSugaredLogger(logger)
// 或从 Logger 创建
sugar := logger.Sugar()
// Sprint 风格的连接
sugar.Info("用户", 123, "操作") // "用户123 操作"
sugar.Debug("1", 2, 3, 4, "5", 6) // "12 3 456"
// Sprintln 风格带空格
sugar.Infoln("用户", 123, "操作") // "用户 123 操作"
sugar.Debugln("1", 2, 3, 4, "5", 6) // "1 2 3 4 5 6"
// Context 方法
sugar.InfoContext(ctx, args...)
sugar.InfolnContext(ctx, args...)// LOG - 结构化日志的全域 Logger
slogx.LOG.Info("消息", "键", "值")
// SUG - 平铺参数的全域 SugaredLogger
slogx.SUG.Info("多个", "参数", 123)
// SetLog - 使用自定义 slog 实例配置全域日志器
customLogger := slog.New(customHandler)
slogx.SetLog(customLogger)
// NewDefault - 创建带默认 JSON 配置的 Logger
logger := slogx.NewDefault()func serviceMethod() {
// 将显示 serviceMethod 作为源
logWithContext("操作", "数据")
}
func logWithContext(op string, data string) {
// 跳过 1 以显示 serviceMethod 而不是 logWithContext
slogx.LOG.Skip(1).Info("处理中", "操作", op, "数据", data)
}logger := slogx.New(slogLogger)
.WithGroup("app")
.With("request_id", "123")
.Skip(1)
logger.Info("链式日志器就绪")ctx := context.Background()
if slogx.LOG.Enabled(ctx, slog.LevelDebug) {
slogx.LOG.Debug("调试模式已启用")
}MIT 许可证 - 详见 LICENSE。
非常欢迎贡献代码!报告 BUG、建议功能、贡献代码:
- 🐛 问题报告? 在 GitHub 上提交问题并附上重现步骤
- 💡 新颖思路? 创建 issue 讨论
- 📖 文档疑惑? 报告问题,帮助我们完善文档
- 🚀 需要功能? 分享使用场景,帮助理解需求
- ⚡ 性能瓶颈? 报告慢操作,协助解决性能问题
- 🔧 配置困扰? 询问复杂设置的相关问题
- 📢 追踪进展? 关注仓库以获取新版本和功能
- 🌟 成功案例? 分享这个包如何改善工作流程
- 💬 反馈意见? 欢迎提出建议和意见
新代码贡献,请遵循此流程:
- Fork:在 GitHub 上 Fork 仓库(使用网页界面)
- 克隆:克隆 Fork 的项目(
git clone https://github.com/yourname/repo-name.git) - 导航:进入克隆的项目(
cd repo-name) - 分支:创建功能分支(
git checkout -b feature/xxx) - 编码:实现您的更改并编写全面的测试
- 测试:(Golang 项目)确保测试通过(
go test ./...)并遵守 Go 代码风格约定 - 文档:面向用户的更改需要更新文档
- 暂存:暂存更改(
git add .) - 提交:提交更改(
git commit -m "Add feature xxx")确保向后兼容的代码 - 推送:推送到分支(
git push origin feature/xxx) - PR:在 GitHub 上打开 Merge Request(在 GitHub 网页上)并提供详细描述
请确保测试通过并包含相关的文档更新。
非常欢迎通过提交 Merge Request 和报告问题来贡献此项目。
项目支持:
- ⭐ 给予星标如果项目对您有帮助
- 🤝 分享项目给团队成员和(golang)编程朋友
- 📝 撰写博客关于开发工具和工作流程 - 我们提供写作支持
- 🌟 加入生态 - 致力于支持开源和(golang)开发场景
祝你用这个包编程愉快! 🎉🎉🎉