ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Envoy Wasm Stats Filter Sink:用 WebAssembly 插件在代理内过滤、重命名并注入指标

Envoy Wasm Stats Filter Sink:用 WebAssembly 插件在代理内过滤、重命名并注入指标 Envoy Wasm Stats Filter Sink用 WebAssembly 插件在代理内过滤、重命名并注入指标【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本篇指南围绕 Envoy contrib 扩展中的Wasm Stats Filter Sinkenvoy.stat_sinks.wasm_filter展开它作为一种统计下沉中间件在每次 metrics flush 时用 WASM 插件对MetricSnapshot做过滤、重命名、全局标签注入与合成指标注入然后把富化后的快照交给任意内层 stats sink如 Kafka、Prometheus 等。读完后你将掌握它的完整 YAML 配置方式、7 个 Foreign Function 的二进制线格式wire format、索引映射与回退语义以及如何依据源码定位其行为边界。扩展定位contrib 中间件且当前处于实验阶段Wasm Stats Filter Sink 由配置消息WasmFilterStatsSinkConfig定义见 wasm_filter.proto它指定一个 stats sink 中间件运行一个 WebAssembly 插件来过滤、转换、富化指标然后再委托给内层 stats sink。它适用于需要可编程逻辑决定哪些指标被导出的场景例如按名称模式丢弃高基数指标从 node metadata 注入标签如 datacenter、pod重命名指标如统一加envoy.前缀注入合成指标如版本号计数。用分布式、代理内嵌的逻辑替代集中式的指标处理服务是这个扩展的核心价值。两个必须知晓的约束见 官方文档该扩展只包含在 contrib 镜像中源码也确实位于 contrib/stat_sinks/wasm_filter 目录它是实验特性正在积极开发中能力会逐步扩展配置结构也可能变化。配置要点扩展类型为envoy.stat_sinks.wasm_filter对应 config.h 中的WasmFilterName常量配置消息使用类型 URLtype.googleapis.com/envoy.extensions.stat_sinks.wasm_filter.v3.WasmFilterStatsSinkConfig配置消息只有两个必填字段proto 中均标注required: true字段类型说明wasm_configwasm.v3.PluginConfig承载过滤/转换/富化逻辑的 WASM 插件配置标准 Envoy Wasm PluginConfigvm_config、root_id、configuration等inner_sinkconfig.metrics.v3.StatsSink过滤后指标要委托给的内层 sink可为任意已注册的 stats sink工厂实现WasmFilterSinkFactory::createStatsSinkconfig.cc在构造 sink 时会解析inner_sink配置并实例化内层 sink随后通过REGISTER_FACTORY注册到StatsSinkFactory注册表从而允许在 bootstrap 的stats_sinks列表中任意组合。工作原理flush 周期内的五步流水线官方文档描述的 flush 流程为Envoy 的 flush 定时器触发把完整MetricSnapshot交给wasm_filtersinksink 将全部counters与gauges序列化为紧凑二进制 buffer调用 WASM 插件的onStatsUpdate()回调插件遍历指标并应用自定义逻辑通过 foreign function 可以获取直方图名称、获取单指标标签、设置全局标签、重命名指标、注入合成指标、声明保留的指标索引host 端构建富化快照保留的指标被包装上标签/名称覆写并附加注入的合成指标富化快照 flush 到内层 sink。Text readouts与host counters/gauges不做过滤直接透传。源码侧的调用链与文档一一对应核心入口是WasmFilterStatsSink::flushwasm_filter_stat_sink_impl.ccflush(snapshot) ├─ context_.clear(); context_.snapshot snapshot; ├─ wasm nullptr 时直接透传给 inner_sink // 插件尚未就绪的兜底 ├─ buildBufferToSnapshotMaps(snapshot, context_) ├─ setActiveContext(context_); setGlobalTags(global_tags_); │ wasm-onStatsUpdate(plugin, snapshot) // 触发插件回调 ├─ setActiveContext(nullptr); setGlobalTags(nullptr); └─ processFilterDecisionsAndFlush(...) // 应用决策并 flush 内层几个值得注意的实现细节插件未加载完成时零风险flush()发现plugin_config_-wasm()为空时直接把原始快照交给内层 sink保证 sink 永不阻塞指标导出thread-local 上下文active_context与active_global_tags是thread_local指针impl.cc在调用 WASM 前后设置/清除所有 foreign function 通过它访问当前快照与决策状态全局标签的启动期语义工厂在构造PluginConfig即触发插件onConfigure期间把一个作用域化的TagVector作为active_global_tags插件的stats_filter_set_global_tags写入的就是它config.cc。这样既实现了“启动时一次设置”又避免了多个wasm_filtersink 之间的共享线程局部状态污染。保留语义emit 调用与否决定行为processFilterDecisionsAndFlushimpl.cc实现了文档隐含的精细语义这也是读懂该扩展行为的关键插件未调用stats_filter_emit且无任何富化操作直接把原始快照 flush 给内层 sink完全透传未调用 emit 但有富化操作全局标签/改名/注入视为“保留全部指标”再叠加富化调用了 emit只有插件声明的索引被保留但未使用过unused的 counter/gauge 无论如何都会透传——因为序列化 buffer 只包含used()为真的指标插件本来“看不见”它们emit 中若未包含 histogram 索引块histogram_block_present为 false所有直方图保留并参与富化只有插件显式给出 histogram 块时才按块过滤。能力矩阵7 个 Foreign Function 一览能力Foreign Function说明Filter过滤stats_filter_emit声明保留哪些 counter、gauge、histogram 索引全局标签注入stats_filter_set_global_tags设置应用于所有指标的标签如 datacenter、pod启动时从onConfigure()调用一次指标重命名stats_filter_set_name_overrides覆写特定指标名称如加envoy.前缀每次 flush 调用合成指标注入stats_filter_inject_metrics注入带自定义名称、数值和标签的新 counter/gauge每次 flush 调用直方图发现stats_filter_get_histograms获取直方图名称列表不在标准onStatsUpdatebuffer 中单指标标签stats_filter_get_metric_tags按类型和索引获取单个指标的标签批量标签stats_filter_get_all_metric_tags一次调用获取所有指标的标签这 7 个函数全部在 wasm_filter_stat_sink_impl.cc 中以proxy_wasm::RegisterForeignFunction注册host 端对每个入参 buffer 都有严格的越界检查如readIndexBlock、readTagVector解析失败返回BadArgument上下文缺失非 flush 期调用返回InternalFailure。配置示例完整的 bootstrap 配置继承自官方文档如下wasm_filtersink 包裹一个 Kafka 内层 sinkstats_flush_interval: 10s stats_sinks: - name: envoy.stat_sinks.wasm_filter typed_config: type: type.googleapis.com/envoy.extensions.stat_sinks.wasm_filter.v3.WasmFilterStatsSinkConfig wasm_config: name: my_stats_filter root_id: stats_filter vm_config: runtime: envoy.wasm.runtime.v8 code: local: filename: /etc/envoy/stats_filter_plugin.wasm configuration: type: type.googleapis.com/google.protobuf.StringValue value: {exclude_prefixes: [server.compilation, runtime.], rename_with_prefix: true} inner_sink: name: envoy.stat_sinks.kafka typed_config: type: type.googleapis.com/envoy.extensions.stat_sinks.kafka.v3.KafkaStatsSinkConfig broker_list: kafka:9092 topic: envoy-metrics format: PROTOBUF emit_tags_as_labels: true字段说明stats_flush_interval顶层字段决定 flush 周期也即 WASM 过滤逻辑的触发频率wasm_config标准wasm.v3.PluginConfig。vm_config.runtime选择 WASM 运行时如 v8code.local.filename指向本地插件文件configuration传给插件的 JSON 字符串——上例中的exclude_prefixes与rename_with_prefix属于插件自身约定host 端不解析inner_sink任意已注册 sink 的嵌套配置wasm_filter对其内容不做假设。注意示例中的 Kafka sink 本身也是 contrib 扩展与wasm_filter一样需要 contrib 构建。Wire Format 参考所有 foreign function 都使用“uint32长度前缀 原始字节”的二进制格式。以下逐一给出与文档一致并标注 host 端对应解析代码stats_filter_emit[counter_count] [counter_idx_0] ... [counter_idx_N] [gauge_count] [gauge_idx_0] ... [gauge_idx_M] [hist_count] [hist_idx_0] ... [hist_idx_K] (optional)counter/gauge 两个索引块必填histogram 块可选。host 端解析见 registerStatsFilterEmit若 buffer 中还有剩余字节则解析第三块并置位histogram_block_present。stats_filter_set_global_tags[tag_count: uint32] For each tag: [name_len: uint32] [name bytes] [value_len: uint32] [value bytes]stats_filter_set_name_overrides[count: uint32] For each override: [type: uint32 (1counter, 2gauge, 3histogram)] [index: uint32] [new_name_len: uint32] [new_name bytes]stats_filter_inject_metrics[counter_count: uint32] For each counter: [name_len: uint32] [name bytes] [value: uint64] [tag_count: uint32] for each tag: [name_len][name][value_len][value] [gauge_count: uint32] For each gauge: [name_len: uint32] [name bytes] [value: uint64] [tag_count: uint32] for each tag: [name_len][name][value_len][value]stats_filter_get_histograms输入空。输出[count: uint32] for each: [name_len: uint32] [name bytes]stats_filter_get_metric_tags单个输入[type: uint32] [index: uint32]。输出[tag_count: uint32] For each tag: [name_len: uint32] [name] [value_len: uint32] [value]stats_filter_get_all_metric_tags批量输入空。输出三个连续块counters、gauges、histograms[metric_count: uint32] For each metric: [tag_count: uint32] For each tag: [name_len: uint32] [name] [value_len: uint32] [value]批量接口在 host 端一次alloc_result分配、一次写回三个块impl.cc这正是文档“Performance considerations”中“一次跨界 vs N 次”的由来。深入索引语义buffer 顺序与 snapshot 顺序插件看到的指标索引是buffer 顺序序列化时跳过未使用的指标而富化快照操作的是snapshot 顺序完整数组。二者之间的映射由buildBufferToSnapshotMaps建立impl.cc遍历快照凡used()为真的 counter/gauge 记录其数组下标形成counter_buffer_to_snapshot/gauge_buffer_to_snapshot两个映射表。processFilterDecisionsAndFlush在 flush 前用映射表把插件返回的保留索引、以及 name override 中的索引从 buffer 顺序翻译成 snapshot 顺序histogram 因序列化 buffer 本身不含 histogram索引直接即 snapshot 顺序在stats_filter_get_metric_tags中可以看到三种类型的索引处理方式不同impl.cc。富化本身由EnrichedMetricSnapshot完成impl.cc其包装对象定义在 enriched_metric.hEnrichedCounter/EnrichedGauge/EnrichedHistogram包装原指标覆写name()、statName()、tags()原有标签 全局标签合并见mergeTags其余方法value()、直方图统计等全部转发给原对象SyntheticCounter/SyntheticGauge独立的合成指标对象持有自定义名称、值与标签追加在富化结果之后textReadouts()、hostCounters()、hostGauges()直接返回原快照对应列表impl.h印证了“Text readouts 与 host counters/gauges 不做过滤、直接透传”的文档声明。读取 Node Metadata插件可在onConfigure()期间通过getProperty()/getValue()读取 Envoy 的 node metadata典型路径[xds, node, id]— node ID主机名[xds, node, cluster]— 集群名[xds, node, metadata, datacenter]— 自定义元数据[xds, node, locality, region]— locality 的 region这些值用于在启动时通过stats_filter_set_global_tags计算全局标签如把datacenter、region打到每个导出指标上。性能考量文档给出的性能特性均可在源码中得到印证全局标签启动时设置一次之后每次 flush 零跨界开销指标过滤整个序列化的指标 buffer 只经历一次WASM 边界穿越onStatsUpdate携带 buffer 传入批量标签查询stats_filter_get_all_metric_tags一次穿越拿到全部标签优于逐指标 N 次穿越名称覆写与指标注入每次 flush 各一次穿越。当前限制Text readouts 不可过滤——它们直接透传到内层 sink不支持数值转换——插件可以重命名和加标签但不能修改 counter/gauge 的数值从源码看包装类对value()只做只读转发add()/set()等写操作全部为空实现。参考实现测试插件演示完整用法仓库自带一个功能完备的示例插件 stats_filter_plugin.cc演示了全部 foreign function 的调用方式可作为自研插件的骨架onConfigure()中调用stats_filter_set_global_tags写入一个test_tagtest_value全局标签onStatsUpdate()中解析标准 stats buffer保留所有 counter 中除excluded_前缀之外的索引过滤演示通过stats_filter_get_histograms获取直方图名称并保留全部直方图调用stats_filter_set_name_overrides将第一个被保留的 counter 重命名为envoy.前缀调用stats_filter_inject_metrics注入一个名为wasm_filter.metrics_kept的合成 counter值等于保留的 counter 数量最后组装 wire buffer 调用stats_filter_emit声明保留集合。对应的验证测试位于 wasm_filter_stat_sink_test.cc针对EnrichedMetricSnapshot与 foreign function 的单元测试、wasm_filter_stat_sink_integration_test.cc 与 config_test.cc可直接查阅以确认各行为语义。关键文件索引文件作用docs/root/configuration/observability/stat_sinks/wasm_filter_stat_sink.rst本扩展的官方文档api/contrib/envoy/extensions/stat_sinks/wasm_filter/v3/wasm_filter.protoWasmFilterStatsSinkConfigAPI 定义contrib/stat_sinks/wasm_filter/source/config.cc工厂注册、内层 sink 构造、启动期全局标签contrib/stat_sinks/wasm_filter/source/wasm_filter_stat_sink_impl.cc7 个 foreign function 实现、flush 主流程、富化快照contrib/stat_sinks/wasm_filter/source/enriched_metric.hEnriched*/Synthetic*指标包装类contrib/stat_sinks/wasm_filter/test/test_data/stats_filter_plugin.cc示例 WASM 插件覆盖全部能力contrib/stat_sinks/wasm_filter/test/wasm_filter_stat_sink_test.cc行为语义单元测试适用前提使用本特性需要 contrib 构建的 Envoy并自行编译或获取符合上述 wire format 的 WASM 插件由于该扩展被标记为实验性生产环境采用前应关注版本间配置结构的变化。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表