|
|
@@ -11,17 +11,145 @@ import (
|
|
|
|
|
|
type nanoLogger struct{}
|
|
|
|
|
|
+// Println 实现标准日志接口的 Println 方法,用于记录信息级别的微服务日志
|
|
|
+//
|
|
|
+// 该方法提供了智能的日志级别检查和性能优化:
|
|
|
+// 1. 首先检查 Info 级别的日志是否启用,避免不必要的字符串格式化开销
|
|
|
+// 2. 如果 Info 级别已启用,才执行字符串格式化和日志记录操作
|
|
|
+//
|
|
|
+// 参数:
|
|
|
+//
|
|
|
+// v - 可变参数,支持任意类型的日志内容
|
|
|
+//
|
|
|
+// 功能特性:
|
|
|
+// - 性能优化:先检查日志级别,避免不必要的字符串格式化
|
|
|
+// - 调用栈调整:跳过1层调用栈,准确定位日志调用位置
|
|
|
+// - 自动格式化:使用 fmt.Sprint 自动格式化各种类型参数
|
|
|
+// - 级别控制:遵循配置的日志级别,支持动态启用/禁用
|
|
|
+//
|
|
|
+// 使用示例:
|
|
|
+//
|
|
|
+// logger := logx.NanoLogger()
|
|
|
+// logger.Println("微服务启动完成")
|
|
|
+// logger.Println("用户ID:", userID, "操作:", "登录")
|
|
|
+// logger.Println("请求参数:", req, "响应:", resp)
|
|
|
+//
|
|
|
+// 性能优化说明:
|
|
|
+// - e.Enabled() 检查可以避免在日志级别禁用时执行昂贵的字符串格式化
|
|
|
+// - 这种设计特别适合高频调用的微服务日志场景
|
|
|
+// - 在生产环境中,当 Info 级别被禁用时,此方法几乎无性能开销
|
|
|
+//
|
|
|
+// 调用栈调整:
|
|
|
+// - CallerSkipFrame(1) 跳过当前方法本身的调用栈帧
|
|
|
+// - 确保日志显示的是调用 Println 的代码位置,而不是此方法内部
|
|
|
func (nanoLogger) Println(v ...interface{}) {
|
|
|
+ // 获取 Info 级别的日志事件,并检查该级别是否启用
|
|
|
+ // 这种设计避免在日志级别禁用时执行不必要的字符串格式化操作
|
|
|
if e := nanoWriter.Info(); e.Enabled() {
|
|
|
+ // 跳过当前方法本身的调用栈帧(CallerSkipFrame(1))
|
|
|
+ // 确保日志显示的调用位置是实际业务代码的位置
|
|
|
+ // 使用 fmt.Sprint 自动格式化所有参数为字符串
|
|
|
e.CallerSkipFrame(1).Msg(fmt.Sprint(v...))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Fatal 实现标准日志接口的 Fatal 方法,用于记录致命错误并终止程序
|
|
|
+//
|
|
|
+// 该方法用于处理无法恢复的严重错误,记录错误信息后会立即终止应用程序。
|
|
|
+// 在微服务架构中,Fatal 日志通常表示服务遇到了不可恢复的致命问题。
|
|
|
+//
|
|
|
+// 参数:
|
|
|
+//
|
|
|
+// v - 可变参数,支持任意类型的致命错误信息
|
|
|
+//
|
|
|
+// 功能特性:
|
|
|
+// - 立即终止:记录日志后立即调用 os.Exit(1) 终止程序
|
|
|
+// - 自动格式化:使用 fmt.Sprint 自动格式化各种类型参数
|
|
|
+// - 致命级别:使用 Fatal 级别记录,便于监控系统识别
|
|
|
+// - 微服务适配:专为微服务环境优化的致命错误处理
|
|
|
+//
|
|
|
+// 使用示例:
|
|
|
+//
|
|
|
+// logger := logx.NanoLogger()
|
|
|
+//
|
|
|
+// // 数据库连接失败,无法继续运行
|
|
|
+// if err := connectDatabase(); err != nil {
|
|
|
+// logger.Fatal("数据库连接失败:", err)
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 关键配置缺失,服务无法启动
|
|
|
+// if config.APIKey == "" {
|
|
|
+// logger.Fatal("API密钥配置缺失,服务无法启动")
|
|
|
+// }
|
|
|
+//
|
|
|
+// 注意事项:
|
|
|
+// - Fatal 方法会立即终止程序,请谨慎使用
|
|
|
+// - 仅在遇到不可恢复的致命错误时使用
|
|
|
+// - 确保在调用 Fatal 前已经记录了足够的错误上下文信息
|
|
|
+// - 微服务环境中,监控系统应该对 Fatal 日志进行告警
|
|
|
+//
|
|
|
+// 与 Panic 的区别:
|
|
|
+// - Fatal: 记录日志后立即终止程序(os.Exit(1))
|
|
|
+// - Panic: 抛出异常,可以被 recover 捕获和处理
|
|
|
func (nanoLogger) Fatal(v ...interface{}) {
|
|
|
+ // 使用 Fatal 级别的日志事件记录致命错误信息
|
|
|
+ // Fatal 级别会自动调用 os.Exit(1) 终止应用程序
|
|
|
+ // 使用 fmt.Sprint 自动格式化所有参数为字符串
|
|
|
nanoWriter.Fatal().Msg(fmt.Sprint(v...))
|
|
|
}
|
|
|
|
|
|
+// Fatalf 实现标准日志接口的 Fatalf 方法,用于格式化记录致命错误并终止程序
|
|
|
+//
|
|
|
+// 该方法与 Fatal 方法类似,但支持格式化字符串,便于记录结构化的致命错误信息。
|
|
|
+// 在微服务架构中,Fatalf 用于记录包含具体错误代码、状态等详细信息的致命错误。
|
|
|
+//
|
|
|
+// 参数:
|
|
|
+//
|
|
|
+// format - 格式化字符串模板,支持标准 fmt 包占位符
|
|
|
+// v - 可变参数,用于填充格式化字符串的占位符
|
|
|
+//
|
|
|
+// 功能特性:
|
|
|
+// - 立即终止:记录日志后立即调用 os.Exit(1) 终止程序
|
|
|
+// - 格式化支持:支持使用格式化字符串模板记录结构化错误信息
|
|
|
+// - 致命级别:使用 Fatal 级别记录,便于监控系统识别
|
|
|
+// - 微服务适配:专为微服务环境优化的格式化致命错误处理
|
|
|
+//
|
|
|
+// 使用示例:
|
|
|
+//
|
|
|
+// logger := logx.NanoLogger()
|
|
|
+//
|
|
|
+// // 数据库连接失败,包含具体错误代码
|
|
|
+// if err := connectDatabase(); err != nil {
|
|
|
+// logger.Fatalf("数据库连接失败,错误码: %d, 错误信息: %s", err.Code, err.Message)
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 配置验证失败,包含具体配置项
|
|
|
+// if !validateConfig(config) {
|
|
|
+// logger.Fatalf("配置验证失败,缺失配置项: %s,当前环境: %s", missingKey, env)
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 服务端口被占用
|
|
|
+// if err := startServer(port); err != nil {
|
|
|
+// logger.Fatalf("服务启动失败,端口 %d 已被占用,错误: %v", port, err)
|
|
|
+// }
|
|
|
+//
|
|
|
+// 格式化占位符支持:
|
|
|
+// - %s: 字符串
|
|
|
+// - %d: 整数
|
|
|
+// - %f: 浮点数
|
|
|
+// - %v: 默认格式
|
|
|
+// - %+v: 详细格式(包含结构体字段名)
|
|
|
+// - 其他标准 fmt 包支持的占位符
|
|
|
+//
|
|
|
+// 注意事项:
|
|
|
+// - Fatalf 方法会立即终止程序,请谨慎使用
|
|
|
+// - 仅在遇到不可恢复的致命错误时使用
|
|
|
+// - 格式化字符串可以包含具体的错误代码、状态等详细信息
|
|
|
+// - 微服务环境中,监控系统应该对 Fatalf 日志进行告警和分析
|
|
|
func (nanoLogger) Fatalf(format string, v ...interface{}) {
|
|
|
+ // 使用 Fatal 级别的日志事件记录格式化致命错误信息
|
|
|
+ // Fatal 级别会自动调用 os.Exit(1) 终止应用程序
|
|
|
+ // 使用 Msgf 方法支持格式化字符串模板
|
|
|
nanoWriter.Fatal().Msgf(format, v...)
|
|
|
}
|
|
|
|
|
|
@@ -30,17 +158,56 @@ var (
|
|
|
nanoWriter *zerolog.Logger
|
|
|
)
|
|
|
|
|
|
-// InitNanoWriter
|
|
|
+// InitNanoWriter 初始化微服务专用的日志写入器
|
|
|
//
|
|
|
-// e.g.
|
|
|
+// 该函数创建一个专门用于微服务架构的日志器实例,配置了适合分布式系统日志的格式。
|
|
|
+// Nano 日志器特别优化了调用栈信息,便于在微服务环境中追踪跨服务调用链。
|
|
|
+//
|
|
|
+// 参数:
|
|
|
+//
|
|
|
+// writer - 微服务日志输出目标,通常是文件写入器或控制台
|
|
|
+//
|
|
|
+// 功能特性:
|
|
|
+// - 专门为微服务架构优化的日志格式
|
|
|
+// - 使用控制台格式输出,便于阅读分布式系统日志
|
|
|
+// - 禁用颜色输出,适合文件持久化存储
|
|
|
+// - 包含时间戳和精确的调用者信息
|
|
|
+// - 跳过多层调用栈(CallerWithSkipFrameCount(3)),准确定位业务代码位置
|
|
|
+// - 实现单例模式,全局共享微服务日志器
|
|
|
+//
|
|
|
+// 使用示例:
|
|
|
+//
|
|
|
+// // 创建微服务日志文件写入器(推荐启用异步写入)
|
|
|
+// nanoWriter := logx.DefaultWriter("nano.log", true)
|
|
|
+//
|
|
|
+// // 初始化微服务日志器
|
|
|
+// logx.InitNanoWriter(nanoWriter)
|
|
|
+//
|
|
|
+// // 获取微服务日志器接口
|
|
|
+// logger := logx.NanoLogger()
|
|
|
//
|
|
|
-// logx.InitNanoWriter(logx.DefaultWriter("nano.log", true))
|
|
|
+// 注意事项:
|
|
|
+// - 微服务日志通常需要包含完整的调用链信息,便于分布式追踪
|
|
|
+// - CallerWithSkipFrameCount(3) 确保跳过框架内部调用,准确定位业务代码
|
|
|
+// - 建议在生产环境中启用异步写入以提高微服务性能
|
|
|
+// - 需要先调用 logx.InitDefault() 或设置 loggingLocationName 以确保时区正确
|
|
|
func InitNanoWriter(writer io.Writer) {
|
|
|
+ // 创建配置完善的 zerolog 微服务日志器:
|
|
|
+ // - ConsoleWriter: 使用控制台格式,便于阅读分布式系统日志
|
|
|
+ // - Out: writer: 指定微服务日志的输出目标
|
|
|
+ // - NoColor: true: 禁用颜色输出,适合文件记录
|
|
|
+ // - FormatTimestamp: 使用自定义时区格式化日志时间
|
|
|
+ // - With().Timestamp(): 自动记录日志时间戳
|
|
|
+ // - With().Caller(): 包含基础调用者信息
|
|
|
+ // - With().CallerWithSkipFrameCount(3): 跳过3层调用栈,准确定位业务代码位置
|
|
|
l := zerolog.New(zerolog.ConsoleWriter{
|
|
|
- Out: writer, NoColor: true,
|
|
|
- FormatTimestamp: tool.ZerologFormatTimestamp(loggingLocationName),
|
|
|
+ Out: writer, // 微服务日志输出目标
|
|
|
+ NoColor: true, // 禁用颜色(适合文件记录)
|
|
|
+ FormatTimestamp: tool.ZerologFormatTimestamp(loggingLocationName), // 自定义时区时间戳
|
|
|
}).With().Timestamp().Caller().CallerWithSkipFrameCount(3).Logger()
|
|
|
- // 存储单例
|
|
|
+
|
|
|
+ // 存储单例实例,供全局微服务日志记录使用
|
|
|
+ // 后续通过 nanoLogger 结构体的方法使用这个预配置的日志器
|
|
|
nanoWriter = &l
|
|
|
}
|
|
|
|
|
|
@@ -48,15 +215,61 @@ func InitNanoWriter(writer io.Writer) {
|
|
|
//
|
|
|
// e.g.
|
|
|
//
|
|
|
+// # NanoLogger 返回微服务专用的日志器接口
|
|
|
+//
|
|
|
+// 该函数实现了智能的微服务日志器初始化机制:
|
|
|
+// 1. 如果已经通过 InitNanoWriter() 初始化了专用微服务日志器,则直接返回 nanoLogger 实例
|
|
|
+// 2. 如果没有初始化,则自动创建一个临时的控制台输出日志器作为回退方案
|
|
|
+//
|
|
|
+// 返回值:
|
|
|
+//
|
|
|
+// nanoLogger - 实现了标准日志接口的微服务日志器
|
|
|
+//
|
|
|
+// 主要用途:
|
|
|
+// 1. 为微服务框架提供兼容的日志器接口
|
|
|
+// 2. 确保即使没有显式初始化,微服务也能正常使用日志功能
|
|
|
+// 3. 支持分布式系统中的日志记录和追踪
|
|
|
+//
|
|
|
+// 使用示例:
|
|
|
+//
|
|
|
+// // 配置微服务框架使用自定义日志器
|
|
|
// nano.WithLogger(logx.NanoLogger())
|
|
|
+//
|
|
|
+// 功能特性:
|
|
|
+// - 懒加载初始化:首次调用时自动创建日志器实例
|
|
|
+// - 智能回退:无专用配置时使用控制台输出作为回退
|
|
|
+// - 颜色支持:启用颜色输出便于控制台调试
|
|
|
+// - 精确调用栈:跳过3层调用栈,准确定位业务代码
|
|
|
+// - 线程安全:单例模式确保全局一致性
|
|
|
+//
|
|
|
+// 智能初始化逻辑:
|
|
|
+// - 检查 nanoWriter 单例是否已初始化
|
|
|
+// - 如果未初始化,创建临时控制台日志器并存储为单例
|
|
|
+// - 返回 nanoLogger 结构体实例,该结构体实现了标准日志接口
|
|
|
+//
|
|
|
+// 最佳实践:
|
|
|
+// - 生产环境建议先调用 InitNanoWriter() 初始化专用文件日志器
|
|
|
+// - 开发环境可以使用自动回退的控制台日志器进行调试
|
|
|
+// - 微服务环境中确保所有服务使用相同的日志配置
|
|
|
func NanoLogger() nanoLogger {
|
|
|
+ // 检查微服务日志器单例是否已经初始化
|
|
|
+ // 如果未初始化,执行懒加载初始化流程
|
|
|
if nanoWriter == nil {
|
|
|
+ // 创建临时的控制台微服务日志器作为回退方案
|
|
|
+ // 这种设计确保即使没有显式初始化,微服务框架也能正常使用日志功能
|
|
|
l := zerolog.New(zerolog.ConsoleWriter{
|
|
|
- Out: os.Stdout, NoColor: false,
|
|
|
- FormatTimestamp: tool.ZerologFormatTimestamp(loggingLocationName),
|
|
|
+ Out: os.Stdout, // 输出到标准输出
|
|
|
+ NoColor: false, // 启用颜色输出(便于控制台调试)
|
|
|
+ FormatTimestamp: tool.ZerologFormatTimestamp(loggingLocationName), // 自定义时区时间戳
|
|
|
}).With().Timestamp().Caller().CallerWithSkipFrameCount(3).Logger()
|
|
|
- // 存储单例
|
|
|
+
|
|
|
+ // 存储单例实例,供后续调用使用
|
|
|
+ // 确保整个应用程序中使用同一个微服务日志器实例
|
|
|
nanoWriter = &l
|
|
|
}
|
|
|
+
|
|
|
+ // 返回 nanoLogger 结构体实例
|
|
|
+ // nanoLogger 实现了标准日志接口(Println、Fatal、Fatalf)
|
|
|
+ // 微服务框架可以通过这个接口记录日志
|
|
|
return nanoLogger{}
|
|
|
}
|