news 2026/9/13 6:26:17

Envoy OpenTelemetry Stat Sink 深度解析:将 Envoy 指标以 OTLP 协议导出到 Collector

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Envoy OpenTelemetry Stat Sink 深度解析:将 Envoy 指标以 OTLP 协议导出到 Collector

Envoy OpenTelemetry Stat Sink 深度解析:将 Envoy 指标以 OTLP 协议导出到 Collector

【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy

Envoy 的envoy.stat_sinks.open_telemetrystat sink 将代理内部指标(counters、gauges、histograms)按照 OpenTelemetry Protocol(OTLP)规范打包,通过 gRPC 或 HTTP 发送到任意 OTLP Collector 服务。本文以该 sink 的官方文档与SinkConfigproto 为核心,结合 open_telemetry.proto 的字段定义和 source/extensions/stat_sinks/open_telemetry/ 下的实现源码,完整讲解其配置参数、导出流程、聚合时间性(temporality)语义与自定义指标转换机制,读完后可直接在生产 bootstrap 中配置该 sink 并理解每条请求在源码中的生成路径。

一、这个 Stat Sink 做什么

Envoy 的指标体系默认可以通过 Statsd、DogStatsd、Hystrix、Prometheus(admin 端点)等途径暴露。OpenTelemetry Stat Sink 提供另一条路径:把指标序列化为 OTLP 的ExportMetricsServiceRequest,调用MetricsService/Export接口推送到 Collector。根据文档与实现,它有三个核心特征:

  1. 协议层面:导出请求严格遵循 OTLP 的MetricService/Export请求结构,导出的指标资源对应 OTLP 的metrics.proto定义(ResourceMetrics/ScopeMetrics/Metric)。
  2. 请求粒度:sink 发出的每一个导出请求都只包含单个ResourceMetrics消息、单个ScopeMetrics和若干Metric记录(原文档的核心约束),数量取决于本次运行周期内采集到的指标数。这一约束在源码中由RequestStreamer::initNewRequest()强制保证——每个新请求只add_resource_metrics()一次,并只追加一个ScopeMetrics(见 open_telemetry_impl.cc);当数据点达到上限时,RequestStreamer::sendIfFullAndPrepareRequest()会把当前请求通过send_callback_发出并初始化一个新请求(open_telemetry_impl.cc)。
  3. 传输方式:二选一——OTLP/gRPC(grpc_service)或 OTLP/HTTP(http_service),由配置中的 oneof 决定,两者在 config.cc 中分派到不同的 exporter。

工厂注册名是envoy.stat_sinks.open_telemetry,旧版兼容名envoy.open_telemetry_stat_sink,注册代码见 config.cc。

二、SinkConfig 完整字段解析

配置 proto 为envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig[#extension: envoy.stat_sinks.open_telemetry]),完整定义见 open_telemetry.proto。各字段含义与源码解析位置如下:

字段类型默认值说明源码解析位置
grpc_serviceconfig.core.v3.GrpcServiceoneof 分支①:实现 OTLP/gRPC Collector 的上游 gRPC clusteropen_telemetry.proto
http_serviceconfig.core.v3.HttpServiceoneof 分支②:实现 OTLP/HTTP Collector 的上游 HTTP cluster同上
report_counters_as_deltasboolfalsetrue时 counter 以 delta 时间性导出,请求中AggregationTemporality设为AGGREGATION_TEMPORALITY_DELTAopen_telemetry_impl.cc
report_histograms_as_deltasboolfalse同上,作用于 histogram同上
emit_tags_as_attributesBoolValuetrue是否把 stat 的 tags 作为 OTLP 数据点 attributes 导出;不设置时不携带任何 attributeopen_telemetry_impl.cc
use_tag_extracted_nameBoolValuetruetrue时 metric name 用 tag 提取后的名字(如cluster.cluster_0.upstream_rq_200提取为upstream_rq_200),而非完整 stat 名open_telemetry_impl.cc
prefixstring指标名前缀,最终 stat 名为<prefix>.<stat_name>;未设置则不加前缀open_telemetry_impl.cc(拼接为prefix + "."
resource_detectorsrepeated TypedExtensionConfig为 OTLP 消息中的 resource 附加属性,扩展类别为envoy.tracers.opentelemetry.resource_detectorsconfig.cc
custom_metric_conversionsxds.type.matcher.v3.Matcher自定义 stat→metric 转换规则,支持改名、加静态标签、丢弃、多 stat 聚合stat_match_action.h
max_data_points_per_requestuint32未设置时无限制每个导出请求的最大数据点数,显式设为 0 表示无限制;达到上限后剩余数据点放入后续请求open_telemetry_impl.cc

两个 BoolValue 字段使用PROTOBUF_GET_WRAPPED_OR_DEFAULT(..., true)读取,即默认都是 true,这与部分旧文档中"按 false 处理"的说法不同,以当前 proto 与 OtlpOptions 构造函数为准。

grpc_servicehttp_service是必填的 oneof(validate.required),且SinkConfig中两者只能出现其一;未命中任一分支时工厂会返回InvalidArgumentError(config.cc)。

另外,proto 中对http_service有一个专门注意事项:OTLP HTTP exporter 服务里的request_headers_to_add不支持access log format specifier,配置值会原样作为 HTTP 头添加,不做格式化。

三、bootstrap 配置示例

stat sink 在 bootstrap 的stats_sinks字段中声明,并依赖全局stats_flush_interval控制上报节奏。以下示例参照 open_telemetry_integration_test.cc 中真实的 bootstrap 构造方式(测试中使用envoy.stat_sinks.open_telemetry名称 + 500ms 的stats_flush_interval):

3.1 OTLP/gRPC 导出

stats_flush_interval: 5s stats_sinks: - name: envoy.stat_sinks.open_telemetry typed_config: "@type": type.googleapis.com/envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig # 实现 OTLP/gRPC Collector 的上游 gRPC 服务(目标 cluster) grpc_service: cluster: otlp_collector transport_api_version: V3 # 指标名前缀:envoy.<stat_name> prefix: "envoy" # counter 以 delta 时间性上报(默认 false,即 cumulative) report_counters_as_deltas: true # tags 作为 OTLP attributes 导出(默认 true) emit_tags_as_attributes: value: true # 每个请求最多 1000 个数据点,超出部分拆到后续请求 max_data_points_per_request: 1000

3.2 OTLP/HTTP 导出

stats_sinks: - name: envoy.stat_sinks.open_telemetry typed_config: "@type": type.googleapis.com/envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig http_service: cluster: otlp_http_collector endpoint_mode: GRPC path: /v1/metrics report_histograms_as_deltas: true # 把完整 stat 名(含 cluster/listener 等 tag 前缀)用作 metric name use_tag_extracted_name: value: false

注意grpc_service/http_service引用的 cluster 必须先在static_resources.clusters中定义(gRPC 分支在 config.cc 中通过clusterManager().grpcAsyncClientManager().getOrCreateRawAsyncClient()创建异步客户端)。

四、Sink 创建链路:工厂、资源探测与分派

OpenTelemetrySinkFactory::createStatsSink(config.cc)的完整流程:

  1. validateProtoDescriptors()校验 OTLP proto 描述符与本地依赖一致,防止版本错位;
  2. downcastAndValidateSinkConfig的 schema 校验;
  3. 通过Tracers::OpenTelemetry::ResourceProviderImpl执行resource_detectors,生成 OTLPResource(复用了 OpenTelemetry tracer 的资源探测框架,service_name传空字符串);
  4. 用 sink 配置 + 资源构造OtlpOptions(承载前文所有字段的运行时视图),再构造OtlpMetricsFlusherImpl
  5. 按 oneof 分派:
    • gRPC 分支:拿到RawAsyncClient,构造OpenTelemetryGrpcMetricsExporterImpl
    • HTTP 分支:构造OpenTelemetryHttpMetricsExporter(open_telemetry_http_impl.h);
  6. 两者封装进OpenTelemetrySink,并以当前系统时间作为初始的last_flush_time_ns_/proxy_start_time_ns_

OpenTelemetrySink::flush(open_telemetry_impl.h)是每次 stats flush 的入口:取 snapshot 时间作为snapshot_time,把last_flush_time_ns_(上一次 flush 时间,首次即进程创建时间)作为 delta 起点、proxy_start_time_ns_作为 cumulative 起点传给 flusher,然后更新last_flush_time_ns_。这解释了 delta 与 cumulative 两种时间性的起止时间差异来自何处。

五、flush 流水线:Flusher → (Aggregator) → RequestStreamer

OtlpMetricsFlusherImpl::flush(open_telemetry_impl.cc)有两种路径,选择依据是一个容易忽略的源码细节:enable_metric_aggregation_只有在配置了custom_metric_conversions时才为 true(open_telemetry_impl.cc)。

  • 未配置自定义转换sinkMetrics直接遍历 snapshot,把每个 gauge / counter / histogram 写入RequestStreamer,然后streamer.send()收尾。
  • 配置了自定义转换:先经过MetricAggregator按「metric 名 + 排序后的 attributes」分组求和/合并,再交给RequestStreamer输出。这是 proto 注释中"aggregate multiple stats into a single metric"能力的实现基础——多个不同 stat 经ConversionAction改名为同一个metric_name后,在MetricAggregator中同 key 合并(counter 求和见 addCounter,histogram 合并 count/sum/桶计数见 addHistogram,bounds 不匹配会打 error 日志)。

MetricAggregator用「排序后的InlinedVector<pair<string,string>, 8>」而不是 hash map 存 attributes,源码注释说明:对典型少于 10 个 attribute 的场景,内存与线性比较都更高效(open_telemetry_impl.h)。

指标筛选由谓词predicate_控制,生产实现默认只导出metric.used()为 true 的指标,即只上报被显式订阅/使用过的 stat,避免无关指标外泄。

5.1 数据点写入与拆分

RequestStreamer的三个add*方法在每次写入前都先调用sendIfFullAndPrepareRequest():当max_dp_ != 0dp_num_ >= max_dp_时,立即send()当前请求(只有dp_num_ > 0才真正发送,空请求不发),并初始化新请求。因此拆分是"到达上限即切",数据点不会丢失,只是延迟到下一个请求

写入时按类型填充:

  • gauge:mutable_gauge()->add_data_points(),时间性为UNSPECIFIED
  • counter:首次写入该 metric 时设置is_monotonic = trueaggregation_temporality
  • histogram:设置 count、sum、explicit_boundsbucket_counts(含越界桶);源码中标注了 min/max/variance 尚不支持(OTLP 规范中的扩展字段)。

setCommonFields负责时间戳:time_unix_nano为本次 snapshot 时间;start_time_unix_nano在 cumulative 时间性下取cumulative_start_time_ns(进程启动时间),delta 时间性下取delta_start_time_ns(上次 flush 时间)(open_telemetry_impl.cc)。

5.2 delta 时间性的零值优化

开启 delta 上报后,delta 为 0 的 counter 与 sampleCount 为 0 的 histogram 直接跳过,不生成数据点(addCounter、addHistogram),减少请求体积。而 histogram 在 delta/cumulative 下的取数源也不同:report_histograms_as_deltas为 true 时取intervalStatistics(),否则取cumulativeStatistics()(open_telemetry_impl.cc)。

六、指标命名与 attributes 规则

对每条 stat,OtlpMetricsFlusherImpl依次做三件事:

  1. 匹配自定义规则getMetricConfigxds.type.matcher.v3.MatcherStatFullNameMatchInput求值,命中DropAction则丢弃该 stat,命中ConversionAction则携带其配置,未命中则按默认规则转换(open_telemetry_impl.cc);
  2. 确定 metric 名getMetricName的优先级是——若命中ConversionAction用其metric_name;否则为prefix + (tagExtractedName 或完整名)(open_telemetry_impl.cc);
  3. 拼装 attributesgetCombinedAttributesemit_tags_as_attributes为 true 时把 stat 的全部 tags 转为 KV,再追加ConversionAction.static_metric_labels,最后按字典序排序——排序是必须的,因为排序后的 attributes 向量是聚合查找的 key 组成部分(open_telemetry_impl.cc)。

6.1 custom_metric_conversions 示例

matcher 的 input 仅支持envoy.extensions.matching.common_inputs.stats.v3.StatFullNameMatchInput,action 为两种工厂之一:otlp_metric_conversion_action_factoryotlp_metric_drop_action_factory(见 stat_match_action.h)。一个"丢弃 + 改名 + 加静态标签"的示例结构:

custom_metric_conversions: matcher_tree: input: stat_full_name_match_input: {} action_selector: match_type: INPUT_MATCH_INPUT on_match: - input_matcher: and_match: predicate: - single_predicate: predicate: string_match: safe_regex: regex: ".*\.downstream_cx_active" action: name: envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig.ConversionAction typed_config: "@type": type.googleapis.com/envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig.ConversionAction metric_name: envoy_active_connections static_metric_labels: - key: env value: string_value: production - input_matcher: and_match: predicate: - single_predicate: predicate: string_match: safe_regex: regex: ".*\.ssl_handshake" action: name: envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig.DropAction typed_config: "@type": type.googleapis.com/envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig.DropAction

未匹配任何规则的 stat 按默认规则(前缀 + 命名开关)转换为 OTLP metric,行为不受影响。

七、传输层:gRPC 与 HTTP 两种 Exporter

7.1 gRPC Exporter

OpenTelemetryGrpcMetricsExporterImpl持有Grpc::AsyncClientMetricsService.Export方法描述符(按名字从 generated pool 查找opentelemetry.proto.collector.metrics.v1.MetricsService.Export)。send()对每个请求调用client_->send(...);回调中:

  • onSuccess:若响应含partial_success,以 debug 级别记录rejected_data_points与错误信息——即 Collector 可以部分接受,被拒数据点数量会在日志中可见(open_telemetry_impl.cc);
  • onFailure:仅 debug 日志,失败的数据点不会重试或持久化,从实现看导出是"尽力而为"的推送模型。

7.2 HTTP Exporter

OpenTelemetryHttpMetricsExporter基于Http::AsyncClient,用HttpServiceHeadersApplicator处理http_service.request_headers_to_add等头部(open_telemetry_http_impl.h),并维护AsyncClientRequestTracker以便析构时取消在途请求。再次提醒:该路径下头部值不做 format specifier 解析,与 access log formatter 的行为不同。

八、Resource 属性:resource_detectors

resource_detectors字段复用 OpenTelemetry tracer 的 resource detector 扩展类别(envoy.tracers.opentelemetry.resource_detectors),由ResourceProviderImpl::getResource()执行后产出Resource,其 attributes 被generateResourceAttributes转成KeyValue列表,并写入每个导出请求的ResourceMetrics.resource.attributes(open_telemetry_impl.cc、config.cc)。因此每个请求虽然只有一个ResourceMetrics,但 resource 属性在请求间保持一致。

九、验证方式与测试参考

该 sink 的行为有完整的测试覆盖,可用作行为契约的参考:

  • open_telemetry_integration_test.cc:在真实集成测试框架中分别以 gRPC 与 HTTP 两种 exporter 类型(enum class ExporterType { GRPC, HTTP })启动带envoy.stat_sinks.open_telemetry的 bootstrap,断言 fake collector 收到的请求中包含 counter / gauge / histogram 三类指标,并验证prefix拼接后的指标名(getFullStatName);
  • open_telemetry_impl_test.cc:flusher/streamer 层面的单元测试;
  • open_telemetry_http_impl_test.cc:HTTP exporter 专项测试;
  • open_telemetry_benchmark.cc:性能基准。

十、小结:关键行为速查

关注点行为依据
请求结构每请求恰好 1 个 ResourceMetrics + 1 个 ScopeMetricsopen_telemetry_impl.cc
请求拆分max_data_points_per_request达上限即切新请求,0/未设置=无限制open_telemetry_impl.cc
时间性默认 cumulative;delta 模式下零值 counter/histogram 被跳过open_telemetry_impl.cc
聚合开关仅当配置custom_metric_conversions时启用按 (名+attributes) 聚合open_telemetry_impl.cc
指标筛选默认只导出metric.used()的指标open_telemetry_impl.h
失败处理gRPC/HTTP 失败仅记 debug 日志,无重试与持久化open_telemetry_impl.cc
扩展元数据该扩展的 config type 为SinkConfig,见 extensions_metadata.yaml扩展清单

适用前提:该 sink 属于 core 扩展envoy.stat_sinks.open_telemetry,依赖stats_flush_interval驱动周期性 flush;gRPC 分支要求配置的上游 cluster 支持 HTTP/2;OTLP 请求结构以当前仓库依赖的 opentelemetry-proto 版本为准。

【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 6:25:54

企业AI平台接入能力横评:业务系统72小时打通实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 6:22:39

CarSim与Simulink联合仿真实现停车场低速导航跟踪

1. 项目背景与核心需求 停车场低速导航跟踪是智能驾驶领域的关键技术难点之一。与高速公路场景不同&#xff0c;停车场环境具有以下典型特征&#xff1a; 空间结构复杂&#xff08;直角弯、窄道、坡道混合&#xff09; 动态障碍物多&#xff08;行人、推车、宠物随机出现&…

作者头像 李华
网站建设 2026/9/13 6:17:31

5分钟解除PDF限制:用PDFPatcher免费去除PDF复制与打印限制完整指南

5分钟解除PDF限制&#xff1a;用PDFPatcher免费去除PDF复制与打印限制完整指南 【免费下载链接】PDFPatcher PDF补丁丁——PDF工具箱&#xff0c;可以编辑书签、剪裁旋转页面、解除限制、提取或合并文档&#xff0c;探查文档结构&#xff0c;提取图片、转成图片等等 项目地址…

作者头像 李华
网站建设 2026/9/13 6:17:03

51单片机三传感器声控灯仿真设计与状态机实现

简介&#xff1a;本资源是一套面向电子类专业本科生与单片机初学者的毕业设计实践方案&#xff0c;聚焦基于51单片机的多模态智能声控灯系统开发&#xff0c;解决传统照明设备无法自适应环境光、声音与人体活动等多因素触发的问题&#xff0c;适用于课程设计、毕设选题及嵌入式…

作者头像 李华
网站建设 2026/9/13 6:17:01

Matlab GUI图传上位机开发:串口协议、图像重组与显示实践

简介&#xff1a;这是一份基于Matlab GUI的图传上位机完整源码&#xff0c;专为电子信息、计算机等专业学生完成课程设计或期末大作业而整理。程序包含代码动态编译、常用基础图像处理功能、串口通信以及无线图传模块&#xff0c;可直接作为远程图像传输演示系统的底层框架。压…

作者头像 李华