Argo Workflows Histogram 指标模型详解:从 Java SDK 模型到控制器实现
2026/9/23 14:02:10 网站建设 项目流程
  • 云原生
  • 容器编排
  • 工作流自动化
  • 任务调度
  • 后端

【免费下载链接】argo-workflows

Workflow Engine for Kubernetes

项目地址:https://gitcode.com/gh_mirrors/ar/argo-workflows
点击查看免费下载

Argo Workflows 在metrics.prometheus中提供三种 Prometheus 指标类型:GaugeCounterHistogram,其中 Histogram 用于对工作流运行中产生的数值(如任务耗时、输出参数值)做客户端聚合统计,适合回答"有多少次请求耗时小于 1 秒"这类分布类问题。本文以 Java SDK 生成的模型文档IoArgoprojWorkflowV1alpha1Histogram为核心,结合仓库内的 CRD 类型定义、控制器指标实现与真实示例,完整讲解 Histogram 的字段语义、YAML 配置方法、底层处理链路与 PromQL 查询方式。

一、Histogram 指标在 Argo Workflows 中的定位

官方文档 docs/metrics.md 明确引用了 OpenTelemetry 对三类指标工具的定义:

  • counter:随时间累积的值,类似汽车里程表,只会单调递增;
  • gauge:读取时刻的当前值,类似汽车油量表;
  • histogram:客户端侧聚合的值,如请求延迟。当关心数值统计分布时("有多少请求耗时少于 1 秒?")应选用 histogram。

Argo Workflows 把这三种类型统一建模在Prometheus结构体中,通过gaugehistogramcounter三个互斥字段之一来声明具体类型。类型常量定义于 pkg/apis/workflow/v1alpha1/workflow_types.go#L4058-L4065:

type MetricType string const ( MetricTypeGauge MetricType = "Gauge" MetricTypeHistogram MetricType = "Histogram" MetricTypeCounter MetricType = "Counter" MetricTypeUnknown MetricType = "Unknown" )

Prometheus.GetMetricType()(workflow_types.go#L4103-L4114)会按Gauge → Histogram → Counter的优先级推断类型:只要p.Histogram != nil即为 Histogram。因此 Histogram 是每个工作流/模板metrics.prometheus列表中的一个独立条目类型,只能与 Gauge、Counter 互斥出现。

二、模型定义与字段语义

Java SDK 生成的模型文档 sdks/java/client/docs/IoArgoprojWorkflowV1alpha1Histogram.md 中,IoArgoprojWorkflowV1alpha1Histogram仅有如下两个属性:

字段Java 类型说明
bucketsList<BigDecimal>Buckets is a list of bucket divisors for the histogram(直方图的桶除数列表)
valueStringValue is the value of the metric(指标的值)

这两个字段与 CRD 底层的 Go 类型一一对应。Go 侧的Histogram结构体定义在 pkg/apis/workflow/v1alpha1/workflow_types.go#L4206-L4213:

// Histogram is a Histogram prometheus metric type Histogram struct { // Value is the value of the metric // +kubebuilder:validation:MinLength=1 Value string `json:"value" protobuf:"bytes,3,opt,name=value"` // Buckets is a list of bucket divisors for the histogram Buckets []Amount `json:"buckets" protobuf:"bytes,4,rep,name=buckets"` } func (in *Histogram) GetBuckets() []float64 { buckets := make([]float64, len(in.Buckets)) for i, bucket := range in.Buckets { buckets[i], _ = bucket.Float64() } return buckets }

值得注意的细节:

  1. valueString而非数值:因为 Argo Workflows 的指标值普遍支持模板变量(如{{workflow.duration}}{{outputs.parameters.xxx}}),必须在运行时解析成字符串后再转为数值。CRD 上标注了MinLength=1,即该字段不允许为空字符串。
  2. buckets的类型是[]AmountAmount是仓库自定义的数值类型(pkg/apis/workflow/v1alpha1/amount.go),内部持有json.Number并通过Float64()转成float64GetBuckets()正是逐桶调用该方法完成转换。在 Java SDK 中对应为List<BigDecimal>,均为高精度十进制表示,避免浮点精度损失。

Histogram挂在Prometheus结构体的可选字段上(workflow_types.go#L4076-L4093),Prometheus还包含name^[a-zA-Z_][a-zA-Z0-9_]*$)、labelshelpMinLength=1)、when等公共字段。

三、在 Workflow 中声明 Histogram 指标

仓库自带的示例 examples/custom-metrics.yaml 展示了一个完整的 Histogram 配置:它在模板random-intmetrics.prometheus下声明了random_int_step_histogram

- name: random-int metrics: prometheus: - name: random_int_step_histogram help: "Value of the int emitted by random-int at step level" when: "{{status}} == Succeeded" # Only emit metric when step succeeds histogram: buckets: - 2.01 - 4.01 - 6.01 - 8.01 - 10.01 value: "{{outputs.parameters.rand-int-value}}"

配置要点拆解:

  • buckets:一组递增的桶边界(bucket divisors)。控制器会为每个桶分别记录落入该边界以内的观测次数,最终在 Prometheus 端生成_bucket{le="..."}系列序列。示例中从 2.01 到 10.01 共 5 个边界,意味着输出值被切分为 6 个区间(含+Inf上界)。
  • value:每次要观测的数值,支持模板变量。示例取上游步骤输出的参数{{outputs.parameters.rand-int-value}};在工作流级指标中常用{{workflow.duration}},在模板级则用{{duration}}
  • when:条件表达式,仅当条件成立(此处为步骤成功)时才上报该指标。
  • help:必填的指标说明字符串(MinLength=1)。
  • labels:可选键值对标签,键需符合^[a-zA-Z_][a-zA-Z0-9_]*$(MetricLabel 定义)。

运行该 Workflow 后,Prometheus 端会出现random_int_step_histogram_bucketrandom_int_step_histogram_countrandom_int_step_histogram_sum等序列,可用于后续分位数计算。

四、控制器侧的处理链路

1. 指标声明校验

在指标注册之前,控制器会先做合法性校验。workflow/metrics/util.go#L37-L38 中强制要求 Histogram 必须填写value

if metric.Histogram != nil && metric.Histogram.Value == "" { return errors.New("missing histogram.value") }

这与 CRD 上MinLength=1的校验约束相互印证:缺少value的 Histogram 配置会被拒绝。

2. 指标的创建与注册

workflow/metrics/metrics_custom.go#L290-L293 中,Histogram 类型会创建 OpenTelemetry 的Float64Histogram仪器,并把 YAML 中的 buckets 通过GetBuckets()转换为默认桶配置:

case metricType == wfv1.MetricTypeHistogram: return m.CreateInstrument(telemetry.Float64Histogram, metricSpec.Name, metricSpec.Help, "{item}", telemetry.WithDefaultBuckets(metricSpec.Histogram.GetBuckets()))

由此可见,buckets并非仅仅透传给 Prometheus 的静态描述,而是直接决定了 OTel 仪器实例的桶划分策略,进而影响最终导出的_bucket序列粒度。

3. 数值的观测与上报

当工作流/模板满足上报条件时,metrics_custom.go#L244-L250 会把模板变量解析后的value字符串转成float64并调用Record记录一次观测:

case metricType == wfv1.MetricTypeHistogram: val, err := strconv.ParseFloat(metricSpec.Histogram.Value, 64) if err != nil { return err } // Record does its own locking if needed by the exporter baseMetric.Record(ctx, val, metricValue.getLabels())

与 Gauge 的加减操作(Set/Add/Sub)不同,Histogram 没有操作符语义:每次上报就是向对应桶累积一次观测值,这也是直方图"客户端聚合分布"特性的体现。

五、用 PromQL 查询 Histogram 分布

Histogram 指标最常见的消费方式是配合histogram_quantile计算分位数。仓库自带的 Grafana 仪表盘 examples/grafana-dashboard.json 中就有现成的示例表达式(针对控制器内置的operation_duration_seconds直方图):

histogram_quantile(0.95, sum(rate(argo_workflows_operation_duration_seconds_bucket{kubernetes_namespace=~"^$ns$"}[5m])) by (le))

同理,对于自定义的random_int_step_histogram,可写为:

histogram_quantile(0.95, sum(rate(random_int_step_histogram_bucket[5m])) by (le))

需要提醒的是,docs/metrics.md 明确指出 Prometheus 指标不应被视为数据存储:它们只反映系统当前状态,不保证持久化,也不适合记录单个工作流实例或单次步骤的历史耗时。如需留存历史数据,应使用工作流归档或日志上报。

六、使用建议与注意事项

  1. 桶边界应合理覆盖业务取值范围:桶过密会拉高基数与存储开销,过疏则分位数精度下降。示例中选择 2.01、4.01 等带小数点的边界,是为了让边界与整型输出值错开,避免"值恰好等于边界"时的归属歧义。
  2. value必须能在运行时解析为合法浮点数:若模板变量缺失或内容非法,strconv.ParseFloat会直接返回错误,导致该次上报失败。
  3. 注意高基数风险labels中若使用高基数的取值(如随机值或完整工作流名),会使序列数量膨胀,官方文档对部分内置指标已用 ⚠️ 标注此类风险。
  4. Java SDK 使用IoArgoprojWorkflowV1alpha1Histogram仅用于在 Java 程序中以类型安全方式构造 Workflow CRD 对象(bucketsList<BigDecimal>valueString),其语义与 YAML 完全一致,最终序列化结果与示例 YAML 等价。

七、相关参考

  • 模型文档:sdks/java/client/docs/IoArgoprojWorkflowV1alpha1Histogram.md
  • Go 类型定义:pkg/apis/workflow/v1alpha1/workflow_types.go#L4206-L4221
  • 数值类型Amount:pkg/apis/workflow/v1alpha1/amount.go
  • 完整指标示例:examples/custom-metrics.yaml
  • 指标概念与内置指标清单:docs/metrics.md
  • 控制器实现:workflow/metrics/metrics_custom.go、workflow/metrics/util.go
  • Grafana 查询示例:examples/grafana-dashboard.json
  • 云原生
  • 容器编排
  • 工作流自动化
  • 任务调度
  • 后端

【免费下载链接】argo-workflows

Workflow Engine for Kubernetes

项目地址:https://gitcode.com/gh_mirrors/ar/argo-workflows
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询