clog

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2026 License: MIT Imports: 12 Imported by: 0

README

clog

Go Reference

clog 是 Genesis 的 L0 日志组件,基于 Go 标准库 log/slog 构建。它的目标不是替代日志平台,而是为 Genesis 各组件提供统一、克制、可组合的结构化日志接口,解决命名空间分层、Context 字段提取、运行时调级和统一错误字段输出等工程问题。

组件定位

  • 提供稳定的结构化日志接口,避免上层组件直接耦合 slog
  • 支持 WithWithNamespace 派生,方便按服务、模块、子模块组织日志
  • 支持从 context.Context 自动提取业务字段与 OpenTelemetry Trace 字段
  • 支持 JSON / console 两种输出格式,以及运行时动态调整级别
  • 当输出到文件时,显式暴露 Close(),遵循 Genesis 的资源所有权原则

clog 不负责日志采集、检索、告警、轮转和异步批处理。这些能力属于日志平台或应用层。

快速开始

logger, err := clog.New(
    clog.NewProdDefaultConfig("genesis"),
    clog.WithNamespace("user-service", "api"),
    clog.WithTraceContext(),
    clog.WithContextField("request_id", "request_id"),
)
if err != nil {
    return err
}
defer logger.Close()

logger.Info("request started",
    clog.String("path", "/v1/users"),
    clog.String("method", "GET"),
)

核心能力

能力 说明
结构化字段 Field 直接复用 slog.Attr,减少字段适配成本
命名空间 WithNamespace("service", "api") 生成 namespace=service.api
Context 提取 通过 WithContextFieldWithTraceContext 自动注入上下文字段
动态级别 SetLevel() 基于 slog.LevelVar,运行时生效
错误结构 统一输出 error={...},便于检索、索引和统计
文件输出 Output 为文件路径时,调用方需要执行 Close() 释放句柄

推荐使用方式

生产环境
  • 使用 json 格式,输出到 stdout
  • 打开 AddSource,便于排障
  • 配合 WithTraceContext() 关联 trace
  • 组件内使用 WithNamespace() 派生,不要手写 namespace 字段
开发环境
  • 使用 NewDevDefaultConfig(...)
  • 使用 console 格式和颜色输出
  • 保留源码位置,方便快速定位
错误日志
  • 大多数场景使用 Error(err)
  • 需要错误分类时使用 ErrorWithCode(err, code)
  • 只有在定位复杂问题时再使用带堆栈的错误字段
  • Fatal 只记录 FATAL 级别日志,不会退出进程;进程生命周期由应用层控制

资源释放

Output 为文件路径时,clog 会持有底层文件句柄:

logger, _ := clog.New(&clog.Config{
    Level:  "info",
    Format: "json",
    Output: "/var/log/app.log",
})
defer logger.Close()

stdoutstderrDiscard() 返回的 logger,Close() 是 no-op。

相关文档

Documentation

Overview

Package clog 为 Genesis 提供统一的结构化日志接口。 它基于 slog,支持命名空间管理、Context 字段提取和运行时级别调整。

特性:

  • 抽象接口,不暴露底层实现(slog)
  • 支持层级命名空间,对于子模块 order,可使用 logger.WithNamespace("order")
  • 基于标准库 slog,额外支持可选的 OpenTelemetry Trace 上下文字段提取
  • 采用函数式选项模式,符合 Genesis 标准
  • Field 直接映射到 slog.Attr,减少字段适配成本
  • 支持统一的 error 结构化字段输出

基本使用:

logger, _ := clog.New(&clog.Config{
    Level:  "info",
    Format: "console",
    Output: "stdout",
})
defer logger.Close()
logger.Info("Hello, World!", clog.String("key", "value"))

使用函数式选项:

logger, _ := clog.New(&clog.Config{Level: "info"},
    clog.WithNamespace("my-service", "api"),
    clog.WithContextField("trace_id", "trace_id"),
    clog.WithContextField("user_id", "user_id"),
    clog.WithContextField("request_id", "request_id"),
)
defer logger.Close()

带 Context 的日志:

ctx := context.WithValue(context.Background(), "trace-id", "abc123")
logger.InfoContext(ctx, "Request processed")

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Level       string `json:"level" yaml:"level"`             // debug|info|warn|error|fatal
	Format      string `json:"format" yaml:"format"`           // json|console
	Output      string `json:"output" yaml:"output"`           // stdout|stderr|<file path>
	EnableColor bool   `json:"enableColor" yaml:"enableColor"` // 仅在 console 格式下有效,开发环境可启用彩色输出
	AddSource   bool   `json:"addSource" yaml:"addSource"`     // 是否添加调用源信息
	SourceRoot  string `json:"sourceRoot" yaml:"sourceRoot"`   // 用于裁剪文件路径,推荐设置为你的项目根目录,获取相对路径
}

Config 日志配置结构

当 Output 为文件路径时,Logger 会持有对应文件句柄, 调用方应在不再使用时执行 logger.Close() 释放资源。

func NewDevDefaultConfig

func NewDevDefaultConfig(sourceRoot string) *Config

NewDevDefaultConfig 创建开发环境的默认日志配置 参数 sourceRoot 推荐设置为你的项目根目录,例如 genesis,以获得更简洁的调用源信息。

func NewProdDefaultConfig

func NewProdDefaultConfig(sourceRoot string) *Config

NewProdDefaultConfig 创建生产环境的默认日志配置 参数 sourceRoot 推荐设置为你的项目根目录,例如 genesis,以获得更简洁的调用源信息。

type ContextField

type ContextField struct {
	Key       any    // Context 中存储的键
	FieldName string // 日志中的字段名
}

ContextField 定义从 Context 中提取字段的规则

type Field

type Field = slog.Attr

Field 是 slog.Attr 的类型别名,减少字段适配开销。

func Any

func Any(k string, v any) Field

Any 创建任意类型字段

func Bool

func Bool(k string, v bool) Field

Bool 创建布尔字段

func Duration

func Duration(k string, v time.Duration) Field

Duration 创建时间长度字段

func Error

func Error(err error) Field

Error 将错误简化为仅包含错误消息

这是轻量级的错误字段,输出统一的 error={msg="..."} 结构, 适用于大多数业务场景。

func ErrorWithCode

func ErrorWithCode(err error, code string) Field

ErrorWithCode 包含错误代码的错误字段

添加业务错误码,适用于需要错误分类的场景。 使用 slog.Group 产生嵌套结构:error={msg="invalid email", code="ERR_INVALID_INPUT"}

边界行为:

  • err == nil 且 code == "":返回空字段(不记录)
  • err == nil 且 code != "":仅记录 error={code="..."},适用于纯错误码场景
  • err != nil 且 code == "":等同于 Error(err),仅记录 error={msg="..."}
  • err != nil 且 code != "":同时记录 msg 和 code

func ErrorWithCodeStack

func ErrorWithCodeStack(err error, code string) Field

ErrorWithCodeStack 包含错误消息、错误码和堆栈信息的字段

最完整的错误字段,包含消息、类型、堆栈和错误码。 仅在需要最详细调试信息时使用,如系统严重错误。 使用 slog.Group 产生嵌套结构:error={msg="...", type="...", code="...", stack="..."}

边界行为:

  • err == nil 且 code == "":返回空字段(不记录)
  • err == nil 且 code != "":仅记录 error={code="..."}
  • err != nil 且 code == "":等同于 ErrorWithStack(err),包含 msg、type 和 stack
  • err != nil 且 code != "":完整记录 msg、type、code 和 stack

func ErrorWithStack

func ErrorWithStack(err error) Field

ErrorWithStack 包含错误消息和堆栈信息的字段

适用于需要调试的场景,包含完整的堆栈信息。 注意:生产环境中谨慎使用,可能产生过多日志。 使用 slog.Group 产生嵌套结构:error={msg="file not found", type="*os.PathError", stack="..."}

func Float64

func Float64(k string, v float64) Field

Float64 创建浮点数字段

func Group

func Group(k string, fields ...any) Field

Group 创建嵌套字段组

func Int

func Int(k string, v int) Field

Int 创建整数字段

func Int64

func Int64(k string, v int64) Field

Int64 创建64位整数字段

func String

func String(k, v string) Field

String 创建字符串字段

func Time

func Time(k string, v time.Time) Field

Time 创建时间字段

func Uint64

func Uint64(k string, v uint64) Field

Uint64 创建64位无符号整数字段

type Level

type Level int

Level 日志级别类型

支持5个级别,按严重程度递增:

DebugLevel: 调试信息,通常只在开发环境使用
InfoLevel:  一般信息,记录正常的业务流程
WarnLevel:  警告信息,表示潜在问题
ErrorLevel: 错误信息,表示程序出错但可恢复
FatalLevel: 致命错误,需要人工介入或由应用层决定是否终止进程

级别数值越小优先级越高,DebugLevel 最低。

const (
	DebugLevel Level = -4 // 调试级别
	InfoLevel  Level = 0  // 信息级别
	WarnLevel  Level = 4  // 警告级别
	ErrorLevel Level = 8  // 错误级别
	FatalLevel Level = 12 // 致命级别
)

func ParseLevel

func ParseLevel(s string) (Level, error)

ParseLevel 将字符串解析为 Level

支持的字符串(不区分大小写):

"debug", "info", "warn", "error", "fatal"

如果无法解析,会返回 InfoLevel 和错误信息。

func (Level) String

func (l Level) String() string

String 返回 Level 的字符串表示

type Logger

type Logger interface {
	// 基础日志级别方法
	Debug(msg string, fields ...Field)
	Info(msg string, fields ...Field)
	Warn(msg string, fields ...Field)
	Error(msg string, fields ...Field)

	// Fatal 记录 FATAL 级别日志。
	//
	// Fatal 只负责记录日志,不会退出进程,进程生命周期由调用方自行控制。
	Fatal(msg string, fields ...Field)

	// 带 Context 的日志级别方法,用于自动提取 Context 字段
	DebugContext(ctx context.Context, msg string, fields ...Field)
	InfoContext(ctx context.Context, msg string, fields ...Field)
	WarnContext(ctx context.Context, msg string, fields ...Field)
	ErrorContext(ctx context.Context, msg string, fields ...Field)

	// FatalContext 记录带 Context 的 FATAL 级别日志。
	//
	// FatalContext 只负责记录日志,不会退出进程,进程生命周期由调用方自行控制。
	FatalContext(ctx context.Context, msg string, fields ...Field)

	// With 创建一个带有预设字段的子 Logger
	With(fields ...Field) Logger

	// WithNamespace 创建一个扩展命名空间的子 Logger
	WithNamespace(parts ...string) Logger

	// SetLevel 动态调整日志级别
	SetLevel(level Level) error

	// Flush 强制同步所有缓冲区的日志
	Flush()

	// Close 释放 Logger 持有的资源。
	//
	// 当 Output 配置为文件路径时,调用方应在不再使用 Logger 后执行 Close。
	// 对 stdout、stderr 和 Discard Logger,Close 是 no-op。
	Close() error
}

Logger 日志接口,提供结构化日志记录功能

func Discard

func Discard() Logger

Discard 创建一个静默的 Logger 实例

返回的 Logger 实现了 Logger 接口,但所有方法体都是空操作。

func New

func New(config *Config, opts ...Option) (Logger, error)

New 创建一个新的 Logger 实例

config - 日志配置,如果为 nil 会使用默认配置 opts - 函数式选项列表,用于命名空间、Context 字段等配置

返回的 Logger 可能持有底层文件句柄;当 Output 为文件路径时, 调用方应在使用完成后执行 logger.Close() 释放资源。

type Option

type Option func(*options)

Option 函数式选项,用于配置 Logger 实例

func WithContextField

func WithContextField(key any, fieldName string) Option

WithContextField 添加自定义的 Context 字段提取规则

可以从 Context 中提取任意字段并添加到日志中。 推荐常用字段:trace_id、user_id、request_id 如果开启了 OpenTelemetry TraceID 提取,则无需手动添加 trace_id 字段。

func WithNamespace

func WithNamespace(parts ...string) Option

WithNamespace 设置日志命名空间,支持多级命名空间

命名空间会以 "." 连接,作为日志中的 namespace 字段。

func WithTraceContext

func WithTraceContext() Option

WithTraceContext 开启 OpenTelemetry TraceID 自动提取

启用后,会自动从 Context 中提取 OTel 的 TraceID 和 SpanID。 该能力依赖 OpenTelemetry trace 包。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL