Go-GenAI-Stack 的完整可观测性解决方案,包含结构化日志、指标监控、分布式追踪。
| 模块 | 功能 | 依赖库 | 状态 |
|---|---|---|---|
| Logger | 结构化日志、日志轮转 | uber-go/zap, lumberjack | ✅ |
| Metrics | Prometheus 指标、系统监控 | prometheus/client_golang | ✅ |
| Tracing | 分布式追踪、链路追踪 | OpenTelemetry | ✅ |
| Health | 健康检查、依赖检查 | - | ✅ |
在 .env 文件中配置:
# ============================================
# 日志配置
# ============================================
APP_LOGGING_ENABLED=true # 是否启用结构化日志
APP_LOGGING_LEVEL=info # debug, info, warn, error
APP_LOGGING_FORMAT=json # json, console
APP_LOGGING_OUTPUT=stdout # stdout, stderr, file
APP_LOGGING_OUTPUT_PATH=./logs/app.log
APP_LOGGING_MAX_SIZE=100 # MB
APP_LOGGING_MAX_BACKUPS=3
APP_LOGGING_MAX_AGE=7 # days
APP_LOGGING_COMPRESS=true
# ============================================
# Metrics 配置
# ============================================
APP_MONITORING_METRICS_ENABLED=true # 是否启用 Prometheus Metrics
APP_MONITORING_METRICS_PATH=/metrics
APP_MONITORING_METRICS_PORT=0 # 0 表示与服务端口相同
# ============================================
# Tracing 配置
# ============================================
APP_MONITORING_TRACING_ENABLED=false # 是否启用 OpenTelemetry Tracing
APP_MONITORING_TRACING_TYPE=otlp # otlp, jaeger, stdout
APP_MONITORING_TRACING_ENDPOINT=localhost:4317
APP_MONITORING_SAMPLE_RATE=0.1 # 采样率 10%
# ============================================
# Health Check 配置
# ============================================
APP_MONITORING_HEALTH_ENABLED=true
APP_MONITORING_HEALTH_PATH=/healthcd backend
go run cmd/server/main.go- API: http://localhost:8080/api
- Metrics: http://localhost:8080/metrics
- Health: http://localhost:8080/health
- 文档: logger/README.md
- 功能: JSON/Console 格式、日志轮转、上下文注入
- 端点: 输出到 stdout/file
示例:
import "github.com/erweixin/go-genai-stack/backend/infrastructure/monitoring/logger"
logger.Info("User logged in", zap.String("user_id", userID))
logger.Error("Failed to save", zap.Error(err))- 文档: metrics/README.md
- 功能: QPS、延迟、错误率、系统指标
- 端点:
GET /metrics
示例:
import "github.com/erweixin/go-genai-stack/backend/infrastructure/monitoring/metrics"
metrics.RecordRequest("GET", "/api/tasks", 200, 0.5)查看指标:
curl http://localhost:8080/metrics- 文档: tracing/README.md
- 功能: 分布式追踪、Span 创建、上下文传播
- 后端: Jaeger、Tempo、OTLP Collector
示例:
import "github.com/erweixin/go-genai-stack/backend/infrastructure/monitoring/tracing"
ctx, span := tracing.StartSpan(ctx, "CreateTask")
defer span.End()
span.SetAttributes(attribute.String("task.title", title))- 文档: 见本文档下方
- 功能: 数据库、Redis 健康检查
- 端点:
GET /health
示例:
curl http://localhost:8080/health响应:
{
"status": "up",
"timestamp": "2025-11-24T12:00:00Z",
"uptime": "1h30m",
"version": "1.0.0",
"checks": {
"database": {
"status": "up",
"message": "ok",
"latency": "2ms"
},
"redis": {
"status": "up",
"message": "ok",
"latency": "1ms"
}
}
}// main.go
func main() {
ctx := context.Background()
cfg := config.Load()
// 1. 初始化可观测性组件
bootstrap.InitObservability(ctx, cfg)
defer bootstrap.ShutdownObservability(ctx)
// 2. 创建服务器
h := bootstrap.CreateServer(cfg)
// 3. 注册中间件(自动集成 Logger, Metrics, Tracing)
bootstrap.RegisterMiddleware(h)
// 4. 注册路由(包括 /metrics, /health)
bootstrap.RegisterRoutes(h, container)
// 5. 启动服务器
h.Spin()
}┌─────────────────────────────────────────────┐
│ Request │
└─────────────────────────────────────────────┘
│
▼
┌────────────────────────┐
│ TracingMiddleware │ ← 生成 TraceID, RequestID
│ - 创建 Span │ ← 提取/注入 Trace 上下文
└────────────────────────┘
│
▼
┌────────────────────────┐
│ LoggerMiddleware │ ← 记录请求日志
│ - 结构化日志输出 │ ← 记录 Metrics
└────────────────────────┘
│
▼
┌────────────────────────┐
│ RecoveryMiddleware │ ← 捕获 panic
└────────────────────────┘
│
▼
┌────────────────────────┐
│ Handler │ ← 业务逻辑
└────────────────────────┘
# 启用 Console 格式日志(便于阅读)
APP_LOGGING_ENABLED=true
APP_LOGGING_FORMAT=console
APP_LOGGING_OUTPUT=stdout
# 启用 Metrics(性能分析)
APP_MONITORING_METRICS_ENABLED=true
# 禁用 Tracing(避免依赖外部服务)
APP_MONITORING_TRACING_ENABLED=false# 启用 JSON 格式日志(结构化查询)
APP_LOGGING_ENABLED=true
APP_LOGGING_FORMAT=json
APP_LOGGING_OUTPUT=file
APP_LOGGING_OUTPUT_PATH=/var/log/go-genai-stack/app.log
# 启用 Metrics(监控告警)
APP_MONITORING_METRICS_ENABLED=true
# 启用 Tracing(采样 10%)
APP_MONITORING_TRACING_ENABLED=true
APP_MONITORING_TRACING_TYPE=otlp
APP_MONITORING_TRACING_ENDPOINT=jaeger:4317
APP_MONITORING_SAMPLE_RATE=0.1# prometheus.yml
scrape_configs:
- job_name: 'go-genai-stack'
scrape_interval: 15s
static_configs:
- targets: ['localhost:8080']docker run -d \
-p 9090:9090 \
-v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheusdocker run -d \
-p 3000:3000 \
grafana/grafana访问: http://localhost:3000 (admin/admin)
推荐使用:
- Go Processes: Dashboard ID 6671
- HTTP Metrics: 自定义 Dashboard
docker run -d --name jaeger \
-e COLLECTOR_OTLP_ENABLED=true \
-p 4317:4317 \
-p 16686:16686 \
jaegertracing/all-in-one:latestAPP_MONITORING_TRACING_ENABLED=true
APP_MONITORING_TRACING_TYPE=otlp
APP_MONITORING_TRACING_ENDPOINT=localhost:4317version: '3.8'
services:
# 应用
app:
build: .
ports:
- "8080:8080"
environment:
APP_MONITORING_METRICS_ENABLED: "true"
APP_MONITORING_TRACING_ENABLED: "true"
APP_MONITORING_TRACING_ENDPOINT: "jaeger:4317"
depends_on:
- prometheus
- jaeger
# Prometheus
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
# Grafana
grafana:
image: grafana/grafana
ports:
- "3000:3000"
depends_on:
- prometheus
# Jaeger
jaeger:
image: jaegertracing/all-in-one:latest
ports:
- "4317:4317"
- "16686:16686"
environment:
COLLECTOR_OTLP_ENABLED: "true"启动:
docker-compose up -d- ✅ 生产环境:使用 JSON 格式 + File 输出
- ✅ 开发环境:使用 Console 格式 + Stdout 输出
- ✅ 上下文字段:使用
With()创建带上下文的 Logger - ✅ 性能关键路径:使用结构化字段,避免格式化字符串
- ✅ 限制标签基数:避免使用高基数标签(如用户 ID)
- ✅ 合理设置 Buckets:根据实际延迟范围调整
- ✅ 业务指标:使用
metrics.NewCounter()创建自定义指标 - ✅ 避免过度监控:只采集关键指标
- ✅ 生产环境:使用 10% 采样率(SampleRate=0.1)
- ✅ 开发环境:使用 100% 采样率或 Stdout 导出器
- ✅ 命名规范:使用
ServiceName.MethodName格式 - ✅ 关键路径:只追踪关键业务逻辑
- ✅ 默认启用:Logger, Metrics, Health
- ✅ 默认禁用:Tracing(避免强依赖外部服务)
- ✅ 环境变量:所有开关都可通过环境变量控制
- ✅ 降级策略:禁用时自动降级为简单实现
- Metrics 端点: 建议通过 Nginx 限制访问(仅允许 Prometheus)
- Health 端点: 可公开访问(不包含敏感信息)
- 日志脱敏: 避免记录密码、Token 等敏感信息
- Tracing 采样: 生产环境使用采样,避免性能影响
- 检查
APP_LOGGING_ENABLED=true - 检查日志级别(
APP_LOGGING_LEVEL) - 检查文件权限(如果使用 File 输出)
- 检查
APP_MONITORING_METRICS_ENABLED=true - 检查端口是否正确
- 访问 http://localhost:8080/metrics
- 检查
APP_MONITORING_TRACING_ENABLED=true - 检查 Jaeger/OTLP Collector 是否启动
- 检查网络连接(
TRACING_ENDPOINT) - 使用
TRACING_TYPE=stdout调试
| 依赖 | 版本 | 用途 |
|---|---|---|
go.uber.org/zap |
v1.27.1 | 结构化日志 |
gopkg.in/natefinch/lumberjack.v2 |
v2.2.1 | 日志轮转 |
github.com/prometheus/client_golang |
v1.23.2 | Prometheus 客户端 |
go.opentelemetry.io/otel |
v1.38.0 | OpenTelemetry SDK |
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc |
v1.38.0 | OTLP gRPC Exporter |
- 添加更多预定义 Grafana Dashboard
- 支持 Tempo 后端(Grafana Tempo)
- 支持日志聚合(Loki)
- 添加告警规则模板(Alertmanager)
- 支持分布式追踪采样策略(基于错误率)
如有问题,请查看:
Starter 定位: 所有可观测性功能都支持开关控制,可根据项目需求灵活启用/禁用。