【免费下载链接】litmus
Litmus helps SREs and developers practice chaos engineering in a Cloud-native way. Chaos experiments are published at the ChaosHub (https://hub.litmuschaos.io). Community notes is at https://hackmd.io/a4Zu_sH4TZGeih-xCimi3Q
项目地址:
https://gitcode.com/gh_mirrors/li/litmus
点击查看 免费下载
Litmus 是一个以云原生方式帮助 SRE 与开发者实践混沌工程的开源项目,其控制平面(ChaosCenter)中的 GraphQL 服务器在 chaoscenter/graphql/server/pkg/metrics 包中内置了一套完整的 Prometheus 指标体系。本文将以该包文档为骨架,结合仓库源码深入剖析 litmus_api_*、litmus_experiment_*、litmus_*_agents 三类共 11 个指标的定义、标签与采集链路,并给出从端点验证、Prometheus 抓取配置到 Grafana 仪表盘导入的完整实战步骤。读完本文,你将能独立为 Litmus ChaosCenter 控制平面搭建一套可观测、可告警的指标监控方案。
一、指标体系的落点:控制平面可观测性
Litmus 的混沌实验编排分为控制平面与执行平面:控制平面由 ChaosCenter 的 GraphQL 服务器、认证服务、事件追踪器与订阅器等组件构成,负责实验编排、基础设施(Infra/Agent)管理和用户交互;执行平面则在目标集群上运行混沌实验。而 pkg/metrics 包正是控制平面中负责暴露 Prometheus 指标的核心模块,它回答了三个问题:
这些指标统一通过一个独立的 HTTP 服务暴露,默认端口 8889,路径 /metrics,由 metrics.go 中定义的 11 个 Prometheus 指标向量承载。
二、指标端点与端口配置
2.1 独立指标服务器
与业务 API 不同,指标并不挂在主 GraphQL 路由上,而是由 startMetricsServer() 启动一个独立、轻量的 Gin HTTP 服务,其实现位于 server.go:
// startMetricsServer starts a separate HTTP server for Prometheus metrics
func startMetricsServer() {
metricsRouter := gin.New()
metricsRouter.Use(gin.Recovery())
metricsRouter.GET("/metrics", gin.WrapH(promhttp.Handler()))
metricsPort := utils.Config.MetricsPort
log.Infof("Metrics server running at http://localhost:%s/metrics", metricsPort)
if err := http.ListenAndServe(":"+metricsPort, metricsRouter); err != nil {
log.Fatalf("Failed to start metrics server: %v", err)
}
}
关键点:
- 端点使用 promhttp.Handler() 输出标准 Prometheus 文本格式,可直接被 Prometheus 抓取;
- 该服务器在 main() 中以 go startMetricsServer() 协程方式启动(见 server.go),与 GraphQL 主服务互不阻塞;
- 日志会打印实际监听地址,形如 Metrics server running at http://localhost:8889/metrics。
2.2 端口:METRICS_PORT 环境变量
端口由环境变量 METRICS_PORT 控制,默认值为 8889,其配置定义位于 utils/variables.go:
MetricsPort string `envconfig:"METRICS_PORT" default:"8889"`
因此你既可以通过环境变量覆盖端口(例如部署多套控制平面避免冲突时),也可以在部署清单中按需注入:
env:
– name: METRICS_PORT
value: "8889"
验证方式:启动 ChaosCenter 后,直接访问 http://localhost:8889/metrics 即可看到所有以 litmus_ 开头的指标。
三、API 指标(litmus_api_*)
这组指标描述 GraphQL 服务器的请求处理情况,均在 metrics.go 中定义:
| litmus_api_requests_total | Counter(CounterVec) | 到达 GraphQL 服务器的 API 请求总数,携带 GraphQL 操作信息 | endpoint、status、operation_name、operation_type |
| litmus_api_response_time_milliseconds | Histogram(HistogramVec) | API 请求响应耗时(毫秒),分桶从 10ms 到 5s | endpoint、operation_name、operation_type |
| litmus_api_error_requests_total | Counter(CounterVec) | 出错请求总数 | endpoint、error_type |
| litmus_api_authentication_failures_total | Counter(CounterVec) | 认证失败次数 | auth_method |
3.1 标签与取值
- endpoint:Gin 路由的完整路径,如 /query;未匹配到任何路由时记为 unmatched(见 middleware.go);
- status:HTTP 状态码字符串,如 200、500、404;
- operation_name:GraphQL 操作名,如 listExperiment、runChaosExperiment、getExperiment;匿名操作记为 anonymous,非 GraphQL 请求记为 N/A;
- operation_type:GraphQL 操作类型,取值为 query 或 mutation;
- error_type:client_error(HTTP 状态码 ≥ 400 且 < 500)或 server_error(状态码 ≥ 500);
- auth_method:认证方式,目前源码中为 bearer(见 authorization/middleware.go)。
3.2 直方图分桶
litmus_api_response_time_milliseconds 的分桶定义如下(单位毫秒):
Buckets: []float64{10, 50, 100, 200, 500, 1000, 2000, 5000},
即覆盖 10ms~5s 的响应耗时区间,配合 histogram_quantile 可计算 p50/p95/p99 等分位延迟,例如:
histogram_quantile(0.99, sum by (le) (rate(litmus_api_response_time_milliseconds_bucket[5m])))
3.3 采集链路
API 指标的写入发生在 middleware.go 的 MetricsMiddleware() 中,它是一个 Gin 中间件,通过 router.Use(metrics.MetricsMiddleware()) 挂载在全局路由上(见 server.go)。其执行流程为:
而 GraphQL 操作信息由 server.go 中的 AroundOperations 拦截器注入 context:
srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
oc := graphql.GetOperationContext(ctx)
operationType := "query"
if oc.Operation != nil && oc.Operation.Operation == "mutation" {
operationType = "mutation"
}
operationName := oc.OperationName
if operationName == "" {
operationName = "anonymous"
}
// Store operation details in context for HTTP middleware to use
ctx = context.WithValue(ctx, metrics.GraphqlOperationNameKey, operationName)
ctx = context.WithValue(ctx, metrics.GraphqlOperationTypeKey, operationType)
return next(ctx)
})
认证失败指标则由认证中间件在 JWT 令牌被吊销时递增(见 authorization/middleware.go),从而让运维者可以区分"业务出错"与"认证被拒"两类异常。
四、实验指标(litmus_experiment_*)
这组指标描述混沌实验及其运行情况,定义于 metrics.go:
| litmus_experiments_total | Gauge(GaugeVec) | 系统中的实验总数 | project_id、status、infra_id |
| litmus_experiment_runs_total | Counter(CounterVec) | 实验累计运行次数 | project_id、experiment_id、experiment_name、infra_id |
| litmus_experiment_run_duration_seconds | Histogram(HistogramVec) | 实验运行耗时(秒),分桶从 1s 到 30 分钟 | project_id、experiment_id、experiment_name、infra_id |
| litmus_experiment_status | Gauge(GaugeVec) | 实验当前运行状态:1 = 运行中,0 = 未运行 | project_id、experiment_id、experiment_name、status、infra_id |
4.1 直方图分桶
litmus_experiment_run_duration_seconds 的分桶覆盖 1 秒到 30 分钟:
Buckets: []float64{1, 5, 10, 30, 60, 120, 300, 600, 1200, 1800},
适合统计大多数混沌实验(从 pod 删除到负载注入)的时长分布。
4.2 写入时机与源码依据
-
实验创建:在 chaos_experiment/handler/handler.go 中,创建实验成功后以 ExperimentsTotal.WithLabelValues(projectID, "Active", request.InfraID).Inc() 递增实验总量(注意:该指标声明为 Gauge,但实际以 Inc() 方式使用,反映的是实验累积总量,status 标签当前取值为 Active)。
-
实验运行启动:在 chaos_experiment_run/handler/handler.go 中,实验运行记录创建成功并提交事务后:
metrics.ExperimentRunsTotal.WithLabelValues(projectID, workflow.ExperimentID, workflow.Name, workflow.InfraID).Inc()
metrics.ExperimentStatus.WithLabelValues(projectID, workflow.ExperimentID, workflow.Name, string(model.ExperimentRunStatusQueued), workflow.InfraID).Set(0)
即排队(Queued)阶段状态值为 0;随后在 cron 实验启动时(见 handler.go)将状态置为 1(Running):
metrics.ExperimentStatus.WithLabelValues(projectID, workflow.ExperimentID, workflow.Name, string(model.ExperimentRunStatusRunning), workflow.InfraID).Set(1)
metrics.ExperimentRunsTotal.WithLabelValues(projectID, workflow.ExperimentID, workflow.Name, workflow.InfraID).Inc()
- 实验完成:在 handler.go 中,当订阅者上报实验完成事件后,以 (当前时间 – 创建时间) 换算秒数观测运行时长,并将状态置 0:
duration := float64(time.Now().UnixMilli()-experimentRun.CreatedAt) / 1000.0 // Convert to seconds
metrics.ExperimentRunDuration.WithLabelValues(experiment.ProjectID, event.ExperimentID, experimentRun.ExperimentName, experiment.InfraID).Observe(duration)
metrics.ExperimentStatus.WithLabelValues(experiment.ProjectID, event.ExperimentID, experimentRun.ExperimentName, executionData.Phase, experiment.InfraID).Set(0)
因此 litmus_experiment_status 的值语义为:1 表示实验正在运行(Running),0 表示实验未在运行(Queued、Completed、Stopped、Error 等阶段);而 status 标签始终携带具体阶段字符串(如 Running、Completed、Stopped、Error),可以据此区分"正在运行"与"已完成"并分别筛选。
五、Agent(基础设施)指标(litmus_*_agents)
这组指标描述 ChaosCenter 管理的混沌 Agent(即连接各目标集群的混沌基础设施),定义于 metrics.go:
| litmus_connected_agents | Gauge(GaugeVec) | 当前已连接的混沌 Agent 数量 | project_id |
| litmus_disconnected_agents | Gauge(GaugeVec) | 当前处于断开状态的 Agent 数量 | project_id |
| litmus_total_agents | Gauge(GaugeVec) | 已注册的 Agent 总数 | project_id |
5.1 周期性刷新逻辑
这组 Gauge 不是逐事件更新的,而是由 chaos_infrastructure/service.go 中的 RecordInfraMetrics(ctx) 以 30 秒为周期从数据库查询并刷新:
ticker := time.NewTicker(30 * time.Second)
…
infras, err := in.infraOperator.GetInfras(ctx, bson.D{{"is_removed", false}})
projectCounts := make(map[string][2]int) // [connected, total]
for _, infra := range infras {
counts := projectCounts[infra.ProjectID]
counts[1]++ // total
if infra.IsActive {
counts[0]++ // connected
}
projectCounts[infra.ProjectID] = counts
}
for projectID, counts := range projectCounts {
metrics.ConnectedAgents.WithLabelValues(projectID).Set(float64(counts[0]))
metrics.DisconnectedAgents.WithLabelValues(projectID).Set(float64(counts[1] – counts[0]))
metrics.TotalAgents.WithLabelValues(projectID).Set(float64(counts[1]))
}
由此可推导出以下监控口径:
- 已连接 Agent = is_removed=false 且 IsActive=true 的基础设施数量;
- 断开 Agent = 注册总数减去已连接数(即 disconnected = total – connected);
- 该指标以 project_id 维度区分,可分别监控每个项目的 Agent 在线率,例如告警 litmus_disconnected_agents > 0。
六、快速验证与 Prometheus 采集配置
6.1 直接访问端点
在本地开发环境,可以直接验证指标输出:
curl http://localhost:8889/metrics
在 Kubernetes 部署场景中,先通过端口转发暴露指标端口:
kubectl port-forward -n litmus deployment/litmusportal-server 8889:8889
curl http://localhost:8889/metrics | grep litmus_
预期能看到类似 litmus_api_requests_total、litmus_experiment_runs_total、litmus_experiment_status 等指标及完整标签序列。
6.2 创建 Metrics Service
为了让 Prometheus(或 ServiceMonitor)能够稳定抓取指标,建议为指标端口单独创建一个 ClusterIP Service(参考 getting-started.md):
apiVersion: v1
kind: Service
metadata:
name: litmus-server-metrics
namespace: litmus
labels:
app: litmus-server-metrics
spec:
selector:
component: litmusportal-server
ports:
– name: metrics
port: 8889
targetPort: 8889
type: ClusterIP
应用:
kubectl apply -f litmus-server-metrics-service.yaml
6.3 创建 ServiceMonitor(Prometheus Operator 场景)
若使用 Prometheus Operator / kube-prometheus-stack,可创建如下 ServiceMonitor 让 Prometheus 自动发现并每 30 秒抓取一次:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: litmus-server-metrics
namespace: litmus
labels:
release: prometheus
spec:
selector:
matchLabels:
app: litmus-server-metrics
endpoints:
– port: metrics
path: /metrics
interval: 30s
应用:
kubectl apply -f litmus-server-metrics-monitor.yaml
注意:release: prometheus 标签必须与你的 Prometheus Operator 配置的标签选择器一致;如果 Helm release 名称不同,请相应修改该标签。
6.4 原生 Prometheus scrape 配置
未使用 Operator 时,也可以在 scrape_configs 中直接配置:
scrape_configs:
– job_name: 'litmus-graphql-server'
metrics_path: '/metrics'
static_configs:
– targets: ['litmus-server-metrics.litmus.svc.cluster.local:8889']
6.5 验证抓取是否成功
端口转发到 Prometheus UI 并检查目标状态:
kubectl port-forward -n monitoring svc/prometheus-kube-prometheus-prometheus 9090:9090
打开 http://localhost:9090/targets,找到 litmus-server-metrics,其状态应显示为 UP。随后可在 Prometheus 查询页面执行:
litmus_api_requests_total
确认能返回带标签的指标序列。
七、Grafana 仪表盘导入与面板清单
仓库内置了一份预构建的 Grafana 仪表盘:chaoscenter/graphql/server/grafana/litmuschaos-metrics-dashboard.json(仪表盘标题为 LitmusChaos Control Plane Observability),导入后即可开箱可视化全部指标。
7.1 导入步骤
kubectl port-forward -n monitoring deployment/prometheus-grafana 3000:3000
7.2 内置面板清单
从仪表盘 JSON 可以确认,它按三类指标组织了 19 个面板:
- API 维度:API Overview、API Request Rate、API Error Rate、API p99 Latency、Auth Failures(5m rate)、API Request Rate by Endpoint、API Response Time(p50 / p95 / p99);
- 实验维度:Experiment Runs、Total Experiment Runs、Total Experiments、Experiment Run Duration(p50)、Experiments Currently Running、Experiment Run Rate by Name & Infra、Experiment Run Duration by Name、Experiment Status Table;
- Agent 维度:Infra Agents、Total Agents、Connected Agents、Disconnected Agents。
7.3 常用 PromQL 示例
基于上述指标,可以组合出以下常用查询:
| API 请求速率 | sum(rate(litmus_api_requests_total[5m])) |
| 5 分钟错误率 | sum(rate(litmus_api_error_requests_total[5m])) |
| 认证失败速率 | sum(rate(litmus_api_authentication_failures_total[5m])) |
| 正在运行的实验 | litmus_experiment_status == 1 |
| 实验平均运行时长 | rate(litmus_experiment_run_duration_seconds_sum[1h]) / rate(litmus_experiment_run_duration_seconds_count[1h]) |
| 每个项目的 Agent 在线数 | sum by (project_id) (litmus_connected_agents) |
八、测试与质量保障
该包附带完整的单元测试 metrics_test.go,覆盖了指标体系的正确性,可作为理解指标语义的最佳参考:
- TestMetricsRegistration:验证 11 个指标向量均可被 Prometheus Registry 注册,不会引发重复注册 panic;
- TestAPIRequestsTotal / TestExperimentRunsTotal:验证 Counter 在多次 Inc() 后计数正确,且不同标签组合互不干扰;
- TestExperimentStatus / TestExperimentsTotal / TestAgentMetrics:验证 Gauge 的 Set/Inc 语义,其中 Agent 测试还校验了 connected + disconnected = total 的守恒关系;
- TestMetricsMiddleware_SuccessRequest / TestMetricsMiddleware_ErrorRequest / TestMetricsMiddleware_UnmatchedRoute:通过 httptest 构造真实 Gin 路由,验证中间件对 200、500、404(未匹配路由记 unmatched)三种场景的指标写入;
- TestContextKeys:锁定 context 键常量的取值。
如需在本地运行测试:
cd chaoscenter/graphql/server && go test ./pkg/metrics/…
九、小结与最佳实践
Litmus ChaosCenter GraphQL 服务器的指标体系以 pkg/metrics 包为单一事实来源,通过独立端口 8889 暴露,具有以下特点:
建议实践路径:先按第六章完成端点验证与采集配置,确认 Prometheus target 为 UP;再导入第七章的 Grafana 仪表盘建立可视化基线;随后针对 litmus_api_error_requests_total、litmus_api_authentication_failures_total、litmus_disconnected_agents 与 litmus_experiment_status == 1(长时间无变化)配置告警规则,即可形成一套完整的 ChaosCenter 控制平面可观测闭环。
赞
【免费下载链接】litmus
Litmus helps SREs and developers practice chaos engineering in a Cloud-native way. Chaos experiments are published at the ChaosHub (https://hub.litmuschaos.io). Community notes is at https://hackmd.io/a4Zu_sH4TZGeih-xCimi3Q
项目地址:
https://gitcode.com/gh_mirrors/li/litmus
点击查看 免费下载
相关推荐
ATProto Feed Generator API 完全参考:方法、参数与响应详解
EasySwoole 路由系统详解:高性能 RESTful API 设计终极指南
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网硕互联帮助中心




评论前必须登录!
注册