Kart Logger

高性能、统一接口的 Go 日志库,支持智能 OTLP 配置、多源配置管理,以及跨框架的统一日志记录。
✨ 核心特性
- 🚀 双引擎架构: 同时支持 Zap (高性能) 和 Slog (标准库),统一接口,透明切换
- 📊 字段标准化: 确保不同引擎输出完全一致的日志格式和字段名
- 🔧 智能 OTLP 配置: 基于端点自动启用,消除冗余配置,支持多种后端
- ⚙️ 多源配置管理: 环境变量、配置文件、API 配置的智能冲突处理
- 🔄 动态配置重载: 文件监控、信号处理、API 触发的运行时配置更新
- 🌐 框架集成: 开箱即用的 Gin、Echo、GORM、Kratos 等框架适配
- 🎯 三种调用风格: 支持简单参数、Printf 格式化、结构化键值对三种日志方式
- 📈 性能优化: Zap 引擎支持零分配高性能日志记录
- 🔍 可观测性: 完整的分布式追踪、上下文传递和 OpenTelemetry 集成
🚀 快速开始
安装
go get github.com/kart-io/logger
最简示例
package main
import "github.com/kart-io/logger"
func main() {
// 使用默认配置 (Slog 引擎, INFO 级别, JSON 格式)
logger.Info("Hello, World!")
// 结构化日志记录
logger.Infow("用户登录成功",
"user_id", "12345",
"ip", "192.168.1.100",
"duration", "200ms")
}
自定义配置
package main
import (
"github.com/kart-io/logger"
"github.com/kart-io/logger/option"
)
func main() {
// 创建高性能 Zap 日志器
opt := &option.LogOption{
Engine: "zap", // 使用 Zap 引擎
Level: "debug", // 调试级别
Format: "json", // JSON 格式
OutputPaths: []string{
"stdout", // 控制台输出
"/var/log/app.log", // 文件输出
},
// 自动启用 OTLP (智能配置)
OTLPEndpoint: "http://localhost:4317",
}
// 添加初始字段(会自动包含在每个日志条目中)
opt.WithInitialFields(map[string]interface{}{
"service.name": "my-service",
"service.version": "v1.0.0",
"environment": "production",
}).AddInitialField("instance_id", "web-001")
coreLogger, err := logger.New(opt)
if err != nil {
panic(err)
}
// 三种调用风格(所有日志都会包含上面设置的初始字段)
coreLogger.Info("简单消息")
coreLogger.Infof("格式化消息: %s", "hello")
coreLogger.Infow("结构化消息", "key", "value")
}
📊 三种调用风格
1. 简单参数风格
logger.Debug("调试消息", "额外信息")
logger.Info("信息消息")
logger.Warn("警告消息")
logger.Error("错误消息")
2. Printf 格式化风格
logger.Debugf("用户 %s 执行 %s 操作", userName, action)
logger.Infof("处理了 %d 个请求,耗时 %v", count, duration)
logger.Errorf("连接 %s:%d 失败: %v", host, port, err)
3. 结构化风格 (推荐)
logger.Debugw("API 请求开始",
"method", "POST",
"path", "/api/users",
"user_id", userID)
logger.Infow("数据库查询完成",
"table", "users",
"duration", duration.Milliseconds(),
"rows", count)
logger.Errorw("支付处理失败",
"order_id", orderID,
"error", err.Error(),
"amount", 99.99)
🏷️ 初始字段管理 (InitialFields)
InitialFields 是一个强大的功能,允许你在创建日志器时设置一组字段,这些字段会自动包含在每个日志条目中,无需重复添加。
基础用法
import "github.com/kart-io/logger/option"
// 创建配置并添加初始字段
opt := option.DefaultLogOption()
// 方法1: 批量添加字段
opt.WithInitialFields(map[string]interface{}{
"service.name": "user-api",
"service.version": "v2.1.0",
"environment": "production",
})
// 方法2: 逐个添加字段(支持链式调用)
opt.AddInitialField("datacenter", "us-west-2").
AddInitialField("instance_id", "web-003").
AddInitialField("team", "platform")
// 方法3: 混合使用
opt.WithInitialFields(map[string]interface{}{
"project": "e-commerce",
"component": "payment",
}).AddInitialField("build_id", "build-12345")
logger, err := logger.New(opt)
自动包含示例
// 设置初始字段
opt := option.DefaultLogOption()
opt.WithInitialFields(map[string]interface{}{
"service.name": "payment-service",
"version": "v1.0.0",
"region": "us-east-1",
})
logger, _ := logger.New(opt)
// 所有日志都会自动包含初始字段
logger.Info("服务启动")
// 输出: {"time":"...", "level":"info", "msg":"服务启动", "service.name":"payment-service", "version":"v1.0.0", "region":"us-east-1", ...}
logger.Infow("处理支付请求",
"order_id", "ord-123",
"amount", 99.99)
// 输出: {"time":"...", "level":"info", "msg":"处理支付请求", "service.name":"payment-service", "version":"v1.0.0", "region":"us-east-1", "order_id":"ord-123", "amount":99.99, ...}
字段优先级
InitialFields 具有明确的优先级规则:
opt := option.DefaultLogOption()
opt.WithInitialFields(map[string]interface{}{
"service.name": "original-service",
"environment": "production",
})
logger, _ := logger.New(opt)
// With() 方法的字段可以覆盖 InitialFields
childLogger := logger.With("service.name", "child-service")
// 当前日志调用的字段具有最高优先级
childLogger.Infow("测试优先级",
"service.name", "current-call-service",
"additional", "data")
// 最终优先级: 当前调用 > With() 方法 > InitialFields
// 输出中 service.name 将是 "current-call-service"
实用场景
1. 微服务标识
opt.WithInitialFields(map[string]interface{}{
"service.name": "user-service",
"service.version": "v1.2.3",
"service.instance": os.Getenv("HOSTNAME"),
})
2. 部署环境信息
opt.WithInitialFields(map[string]interface{}{
"environment": "production",
"datacenter": "us-west-2",
"cluster": "production-cluster",
"namespace": "default",
})
3. 构建和版本信息
opt.WithInitialFields(map[string]interface{}{
"build_date": "2023-12-01T10:30:00Z",
"git_commit": "abc123def456",
"git_branch": "main",
"build_number": "1234",
})
获取已配置字段
// 获取所有初始字段(返回副本,安全访问)
fields := opt.GetInitialFields()
for key, value := range fields {
fmt.Printf("%s: %v\n", key, value)
}
⚠️ 注意事项
- OTLP 兼容: InitialFields 会自动传递给 OTLP 导出器,确保分布式追踪中的服务标识正确
- 内存效率: 字段在日志器创建时设置,不会在每次日志调用时复制
- 类型安全: 支持任意类型的值,会在输出时自动序列化
- 不可变性:
GetInitialFields() 返回副本,防止意外修改
🏗️ 项目架构
包结构图
github.com/kart-io/logger/
├── core/ # 核心接口定义 (Logger, Level)
├── engines/ # 双引擎实现
│ ├── slog/ # Go 标准库 slog 引擎
│ └── zap/ # Uber Zap 高性能引擎
├── factory/ # 工厂模式,动态创建日志器
├── option/ # 配置选项和验证
├── fields/ # 字段标准化系统
├── otlp/ # OpenTelemetry 集成
├── reload/ # 动态配置重载
├── integrations/ # 框架集成适配器
│ ├── gorm/ # GORM ORM 集成
│ └── kratos/ # Kratos 微服务框架集成
├── errors/ # 错误处理和恢复
└── example/ # 12+ 完整使用示例
系统设计图
graph TB
%% 用户层
subgraph "用户接口层"
APP[应用程序]
CLI[命令行工具]
WEB[Web框架]
end
%% 核心层
subgraph "核心接口层"
CORE[core.Logger 统一接口]
LEVEL[core.Level 日志级别]
end
%% 配置层
subgraph "配置管理层"
OPT[option.LogOption 配置结构]
VALID[配置验证和智能默认值]
RELOAD[reload.ConfigReloader 动态重载]
end
%% 工厂层
subgraph "工厂层"
FACTORY[factory.LoggerFactory]
CREATE[动态引擎创建]
end
%% 引擎层
subgraph "双引擎实现层"
SLOG[engines/slog 标准库引擎]
ZAP[engines/zap 高性能引擎]
end
%% 标准化层
subgraph "字段标准化层"
FIELDS[fields.StandardEncoder]
UNIFIED[统一字段格式]
end
%% 集成层
subgraph "框架集成层"
GORM[integrations/gorm]
KRATOS[integrations/kratos]
MIDDLEWARE[Web中间件]
end
%% 输出层
subgraph "输出处理层"
CONSOLE[控制台输出]
FILE[文件输出]
OTLP[OTLP导出器]
end
%% 可观测性后端
subgraph "可观测性后端"
JAEGER[Jaeger]
VICTORIA[VictoriaLogs]
OTEL[OpenTelemetry Collector]
end
%% 连接关系
APP --> CORE
CLI --> OPT
WEB --> MIDDLEWARE
CORE --> FACTORY
OPT --> VALID
VALID --> FACTORY
RELOAD --> FACTORY
FACTORY --> CREATE
CREATE --> SLOG
CREATE --> ZAP
SLOG --> FIELDS
ZAP --> FIELDS
FIELDS --> UNIFIED
UNIFIED --> CONSOLE
UNIFIED --> FILE
UNIFIED --> OTLP
GORM --> CORE
KRATOS --> CORE
MIDDLEWARE --> CORE
OTLP --> JAEGER
OTLP --> VICTORIA
OTLP --> OTEL
%% 样式
classDef userLayer fill:#e1f5fe
classDef coreLayer fill:#f3e5f5
classDef configLayer fill:#e8f5e8
classDef factoryLayer fill:#fff3e0
classDef engineLayer fill:#fce4ec
classDef integrationLayer fill:#e0f2f1
classDef outputLayer fill:#f1f8e9
classDef backendLayer fill:#e3f2fd
class APP,CLI,WEB userLayer
class CORE,LEVEL coreLayer
class OPT,VALID,RELOAD configLayer
class FACTORY,CREATE factoryLayer
class SLOG,ZAP,FIELDS,UNIFIED engineLayer
class GORM,KRATOS,MIDDLEWARE integrationLayer
class CONSOLE,FILE,OTLP outputLayer
class JAEGER,VICTORIA,OTEL backendLayer
配置优先级流程图
graph TD
START([配置加载开始])
%% 配置源
ENV[环境变量]
API[HTTP API]
CENTER[配置中心]
FILE[配置文件]
DEFAULT[系统默认值]
%% 处理逻辑
MERGE[配置合并处理器]
CONFLICT[冲突解决算法]
OTLP_AUTO[OTLP智能检测]
VALIDATE[配置验证]
%% 结果
FINAL[最终配置]
LOGGER[日志器实例]
START --> ENV
START --> API
START --> CENTER
START --> FILE
START --> DEFAULT
ENV --> MERGE
API --> MERGE
CENTER --> MERGE
FILE --> MERGE
DEFAULT --> MERGE
MERGE --> CONFLICT
CONFLICT --> OTLP_AUTO
OTLP_AUTO --> VALIDATE
VALIDATE --> FINAL
FINAL --> LOGGER
%% 优先级标注
ENV -.->|优先级: 1| MERGE
API -.->|优先级: 2| MERGE
CENTER -.->|优先级: 3| MERGE
FILE -.->|优先级: 4| MERGE
DEFAULT -.->|优先级: 5| MERGE
%% 样式
classDef highPriority fill:#ffcdd2
classDef mediumPriority fill:#fff9c4
classDef lowPriority fill:#e8f5e8
classDef processNode fill:#e1f5fe
classDef resultNode fill:#f3e5f5
class ENV highPriority
class API,CENTER mediumPriority
class FILE,DEFAULT lowPriority
class MERGE,CONFLICT,OTLP_AUTO,VALIDATE processNode
class FINAL,LOGGER resultNode
🎯 核心概念
双引擎架构设计
graph LR
subgraph "用户代码"
USER[logger.Info/Infof/Infow]
end
subgraph "统一接口层"
INTERFACE[core.Logger Interface]
end
subgraph "引擎选择"
FACTORY[factory.LoggerFactory]
end
subgraph "双引擎实现"
SLOG_ENGINE[engines/slog]
ZAP_ENGINE[engines/zap]
end
subgraph "字段标准化"
ENCODER[fields.StandardEncoder]
end
subgraph "统一输出"
OUTPUT[相同的JSON/Console格式]
end
USER --> INTERFACE
INTERFACE --> FACTORY
FACTORY --> SLOG_ENGINE
FACTORY --> ZAP_ENGINE
SLOG_ENGINE --> ENCODER
ZAP_ENGINE --> ENCODER
ENCODER --> OUTPUT
classDef userCode fill:#e1f5fe
classDef interface fill:#f3e5f5
classDef factory fill:#fff3e0
classDef engine fill:#fce4ec
classDef output fill:#e8f5e8
class USER userCode
class INTERFACE interface
class FACTORY factory
class SLOG_ENGINE,ZAP_ENGINE engine
class ENCODER,OUTPUT output
| 引擎 |
适用场景 |
性能 |
特点 |
| Slog |
通用应用,标准化 |
标准 |
Go 1.21+ 标准库,兼容性好 |
| Zap |
高性能场景 |
极高 |
零分配,生产环境首选 |
关键优势: 相同的代码,不同的引擎,完全一致的输出格式!
字段标准化
确保不同引擎输出完全一致的字段名和格式:
// Slog 和 Zap 引擎输出完全相同
{
"timestamp": "2023-12-01T10:30:00.123456789Z",
"level": "info",
"message": "用户登录成功",
"caller": "main.go:42",
"user_id": "12345",
"trace_id": "abc123def456"
}
智能 OTLP 配置
无需繁琐的 enabled: true 配置,有端点即自动启用:
# 最简配置,自动启用 OTLP
otlp-endpoint: "http://localhost:4317"
# 高级配置
otlp:
endpoint: "https://jaeger.company.com:4317"
protocol: "grpc"
timeout: "15s"
headers:
Authorization: "Bearer token123"
🛠️ 高级功能
动态配置重载
import "github.com/kart-io/logger/reload"
// 文件监控 + 信号处理 + API 触发
reloadConfig := &reload.ReloadConfig{
ConfigFile: "logger.yaml",
Triggers: reload.TriggerAll,
Signals: []os.Signal{syscall.SIGUSR1},
}
reloader, _ := reload.NewConfigReloader(reloadConfig, initialConfig, factory)
reloader.Start()
// 现在支持:
// 1. 修改 logger.yaml 文件自动重载
// 2. kill -USR1 <pid> 信号重载
// 3. HTTP API 调用重载
Web 框架集成
// Gin 集成
import "github.com/kart-io/logger/integrations"
router := gin.Default()
logger, _ := logger.NewWithDefaults()
router.Use(integrations.GinMiddleware(logger))
// Echo 集成
e := echo.New()
e.Use(integrations.EchoMiddleware(logger))
// GORM 集成
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
Logger: integrations.NewGormLogger(logger),
})
上下文和追踪
// 创建带上下文的日志器
ctx := context.WithValue(context.Background(), "request_id", "req-12345")
contextLogger := logger.WithCtx(ctx,
"service", "user-api",
"version", "v1.2.3")
// 分布式追踪
contextLogger.Infow("处理用户请求",
"trace_id", "abc123def456",
"span_id", "span789xyz",
"user_id", userID,
"operation", "get_profile")
// 创建子日志器
userLogger := logger.With(
"user_id", userID,
"session_id", sessionID)
// 所有后续日志都包含这些字段
userLogger.Info("用户进入页面")
userLogger.Warn("权限检查失败")
📖 使用示例
项目包含 13+ 个完整的使用示例,每个示例都是独立的 Go 模块:
运行示例
# 综合功能演示
cd example/comprehensive && go run main.go
# InitialFields 使用演示
cd example/initial_fields && go run main.go
# Web 框架集成
cd example/echo && go run main.go # http://localhost:8081
cd example/gin && go run main.go # http://localhost:8080
# OTLP 集成测试
cd example/otlp && go run main.go
# 性能基准测试
cd example/performance && go run main.go
🔧 配置选项
基本配置
engine: "zap" # 引擎选择: "zap" | "slog"
level: "info" # 日志级别: "debug" | "info" | "warn" | "error" | "fatal"
format: "json" # 输出格式: "json" | "console"
output-paths: ["stdout"] # 输出路径: 控制台、文件路径
development: false # 开发模式 (影响格式和堆栈跟踪)
OTLP 配置
# 扁平化配置 (常用)
otlp-endpoint: "http://localhost:4317"
# 嵌套配置 (高级)
otlp:
enabled: true # 明确启用/禁用
endpoint: "http://jaeger:4317" # OTLP 收集器端点
protocol: "grpc" # 协议: "grpc" | "http"
timeout: "10s" # 连接超时
headers: # 自定义请求头
Authorization: "Bearer token"
X-Tenant-ID: "tenant-123"
环境变量
export LOG_ENGINE="zap"
export LOG_LEVEL="debug"
export LOG_FORMAT="json"
export LOG_OTLP_ENDPOINT="http://localhost:4317"
export LOG_DEVELOPMENT="true"
🚦 OTLP 后端支持
Jaeger
# docker-compose.yml
services:
jaeger:
image: jaegertracing/all-in-one:latest
ports:
- "16686:16686" # Web UI
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
VictoriaLogs
services:
victorialogs:
image: victoriametrics/victoria-logs:latest
ports:
- "9428:9428" # HTTP API
- "4317:4317" # OTLP gRPC
OpenTelemetry Collector
# otel-collector.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
exporters:
logging:
jaeger:
endpoint: jaeger:14250
tls:
insecure: true
service:
pipelines:
logs:
receivers: [otlp]
exporters: [logging, jaeger]
🎛️ 命令行集成
import (
"github.com/spf13/pflag"
"github.com/kart-io/logger/option"
)
func main() {
opt := option.DefaultLogOption()
// 自动添加所有日志配置标志
fs := pflag.NewFlagSet("myapp", pflag.ExitOnError)
opt.AddFlags(fs)
fs.Parse(os.Args[1:])
logger, _ := logger.New(opt)
}
# 命令行使用
./myapp --engine=zap \
--level=debug \
--format=console \
--otlp-endpoint=http://localhost:4317 \
--development
🏭 生产环境配置
高性能配置
opt := &option.LogOption{
Engine: "zap", // 高性能引擎
Level: "info", // 生产级别
Format: "json", // 结构化输出
OutputPaths: []string{"/var/log/app.log"}, // 文件输出
Development: false, // 生产模式
// OTLP 配置
OTLPEndpoint: os.Getenv("OTLP_ENDPOINT"),
OTLP: &option.OTLPOption{
Protocol: "grpc",
Timeout: 30 * time.Second,
Headers: map[string]string{
"Authorization": "Bearer " + os.Getenv("OTLP_TOKEN"),
},
},
}
多环境配置
func createLogger(env string) (core.Logger, error) {
var opt *option.LogOption
switch env {
case "production":
opt = &option.LogOption{
Engine: "zap",
Level: "info",
Format: "json",
OutputPaths: []string{"/var/log/app.log"},
OTLPEndpoint: "https://otlp.company.com:4317",
}
case "development":
opt = &option.LogOption{
Engine: "slog",
Level: "debug",
Format: "console",
OutputPaths: []string{"stdout"},
Development: true,
}
case "test":
opt = &option.LogOption{
Engine: "slog",
Level: "error",
OutputPaths: []string{"stderr"},
}
}
return logger.New(opt)
}
📊 性能基准
基于内置的 performance example:
cd example/performance && go run main.go
典型结果 (M1 Pro, 8 cores):
| 引擎 |
操作 |
速度 |
分配 |
| Zap |
结构化日志 |
~2M ops/sec |
0 allocs/op |
| Zap |
格式化日志 |
~1M ops/sec |
1 alloc/op |
| Slog |
结构化日志 |
~800K ops/sec |
3 allocs/op |
| Slog |
格式化日志 |
~600K ops/sec |
4 allocs/op |
🧪 测试
# 运行所有测试
go test ./...
# 运行基准测试
go test -bench=. ./...
# 查看覆盖率
go test -cover ./...
# 生成覆盖率报告
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
📚 文档
每个包都有详细的中文文档:
🤝 贡献
我们欢迎各种形式的贡献!
- Fork 本项目
- 创建功能分支 (
git checkout -b feature/AmazingFeature)
- 提交更改 (
git commit -m 'Add some AmazingFeature')
- 推送到分支 (
git push origin feature/AmazingFeature)
- 创建 Pull Request
开发指南
# 克隆项目
git clone https://github.com/kart-io/logger.git
cd logger
# 安装依赖
go mod tidy
# 运行测试
go test ./...
# 运行示例
cd example/comprehensive && go run main.go
🐛 问题反馈
如果您遇到问题或有建议,请:
- 查看 Issues
- 查看 文档 和各包的 README
- 运行相关 示例
- 提交新的 Issue
📄 许可证
本项目采用 Apache 2.0 许可证。
🙏 致谢
⭐ 如果这个项目对您有帮助,请给个 Star! ⭐