Skip to content

全局 Logger

DD 提供一个进程级的全局 Logger,所有包级便捷函数dd.Info()dd.Errorf() 等)都委托给它。这是最简单的使用方式——零配置即可开始记录日志。

两种使用模式对比

模式代码示例适用场景
全局 Loggerdd.Info("hello")脚本、小型项目、快速原型
实例 Loggerlogger, _ := dd.New(cfg); logger.Info("hello")需要自定义配置、多 Logger 实例、依赖注入

全局 Logger 本质上就是一个由 sync.Once 保护的单例 *Logger,首次调用时自动创建。

包级便捷函数

所有标准日志方法都有对应的包级版本,直接操作全局 Logger:

go
package main

import "github.com/cybergodev/dd"

func main() {
    // 基础日志
    dd.Debug("调试信息")
    dd.Info("服务启动")
    dd.Warn("内存使用率偏高")
    dd.Error("请求失败")
    // dd.Fatal("致命错误")  // ⚠️ 会调用 os.Exit(1)

    // 格式化
    dd.Infof("用户 %s 已登录", username)

    // 结构化日志
    dd.InfoWith("请求处理完成",
        dd.String("method", "GET"),
        dd.Int("status", 200),
    )

    // 字段链式传递
    dd.WithFields(dd.String("service", "api")).
        Info("服务就绪")

    // 级别控制
    dd.SetLevel(dd.LevelDebug)
    if dd.IsDebugEnabled() {
        dd.Debug("debug 已启用")
    }
}

全部包级函数

基础(Debug/Info/Warn/Error/Fatal)、格式化(Debugf/Infof/...)、结构化(DebugWith/InfoWith/...)、通用级别(Log/Logf/LogWith)、字段链(WithFields/WithField)、级别查询(IsLevelEnabled/IsDebugEnabled/...)、采样(SetSampling/GetSampling)、输出管理(AddWriter/RemoveWriter/WriterCount)、生命周期(Flush)。

全局 Logger 初始化

Default():懒初始化

dd.Default() 返回全局 Logger,首次调用时用 DefaultConfig() 自动创建:

go
// 首次调用 → 自动创建(sync.Once 保证线程安全)
logger := dd.Default()
logger.Info("hello") // 等价于 dd.Info("hello")

InitDefault():自定义配置

在程序启动时用自定义配置初始化全局 Logger:

go
package main

import (
    "log"

    "github.com/cybergodev/dd"
)

func main() {
    cfg := dd.DefaultConfig()
    cfg.Level = dd.LevelDebug
    cfg.Format = dd.FormatJSON

    if err := dd.InitDefault(cfg); err != nil {
        log.Fatalf("初始化日志失败: %v", err)
    }

    // 此后所有包级函数使用上述配置
    dd.Info("全局 Logger 已初始化")
}

InitDefault 会替换旧实例

如果全局 Logger 已存在(如已被 Default() 自动创建),InitDefault()关闭旧实例并替换为新实例。旧实例的关闭在后台 goroutine 中延迟执行(100ms),以等待进行中的写操作完成。

SetDefault():直接替换

用已创建的 Logger 实例替换全局 Logger:

go
logger, _ := dd.New(dd.DevelopmentConfig())
dd.SetDefault(logger)

// 此后包级函数使用新 Logger
dd.Info("使用自定义 Logger")

错误处理

全局 Logger 初始化失败时会自动降级为 stderr 输出(不会 panic)。通过以下函数检测初始化状态:

go
logger := dd.Default()

if err := dd.DefaultInitError(); err != nil {
    // Logger 运行在降级模式(输出到 stderr)
    log.Printf("警告:全局 Logger 初始化失败: %v", err)
}

// 或者一次性获取 Logger 和错误
logger, err := dd.DefaultWithErr()
if err != nil {
    log.Printf("降级模式: %v", err)
}

与实例 Logger 的配合

全局 Logger 和实例 Logger 可以共存。常见模式是在 main 中初始化全局 Logger,同时在需要 DI 的地方使用接口:

go
// main.go
func main() {
    cfg := dd.DefaultConfig()
    cfg.Format = dd.FormatJSON
    _ = dd.InitDefault(cfg)
    defer dd.Flush()
}

// service.go — 使用接口实现可测试性
type Service struct {
    logger dd.LogProvider // 接口,可 mock
}

func NewService(logger dd.LogProvider) *Service {
    return &Service{logger: logger}
}

// 使用全局 Logger 创建 Service
svc := NewService(dd.Default())

依赖注入推荐接口

dd.LogProvider 是最完整的日志接口,适合依赖注入。更精简的接口:dd.CoreLogger(仅日志方法)、dd.LevelLogger(+ 级别管理)、dd.ConfigurableLogger(+ 配置与生命周期)。详见 接口定义

下一步