
Vector Sample 采样转换器全解从 rate/ratio 配置到哈希分桶的降采样实现【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector导读本文围绕 Vector 数据管道中的sample转换器transform展开系统讲解如何按固定速率或百分比对日志log与链路trace事件流进行降采样并深入rate、ratio、key_field、group_by、exclude等核心配置参数的语义与实现原理。读完本文你将掌握 sample 的完整配置方法、静态采样与动态采样的取舍以及其哈希分桶与计数器的底层工作机制可直接用于生产管道中控制下游写入量与成本。本文以 sample.md 所对应的组件文档为主体结合仓库中的 CUE 元数据与 Rust 源码进行纵深佐证。sample 转换器是什么sample 是一个无状态stateful: false、流式egress_method: stream、开发状态为 stable的转换器其官方定位是Sample events from an event stream based on supplied criteria and at a configurable rate.即按照用户提供的条件criteria和可配置的采样率对事件流进行抽样放行——被采中的事件继续沿管道下发未采中的事件被丢弃。它接受log 与 trace两类事件作为输入metrics输入为null见 sample.cue输出仍为这两类事件。典型应用场景包括成本与带宽控制在访问日志、审计日志等海量场景下只保留1/N或x%的事件进入下游 sink显著降低存储与出口流量分布式追踪降采样按trace_id分桶采样保证同一条 trace 的所有 span 要么全部保留、要么全部丢弃避免出现“有头无尾”的残缺链路按服务维度独立采样通过group_by让不同服务各自独立计数采样互不干扰关键事件豁免配合exclude条件让 ERROR 级别等关键事件绕过采样、永远放行。核心配置参数详解sample 的全部配置项由 generated/sample.cue 定义其对应的 Rust 结构体在 config.rs。下表汇总了各参数参数类型必填说明rateuint二选一采样率以1/N表示如rate 1500表示每 1500 个事件放行 1 个ratiofloat二选一采样比例取值[0, 1]如ratio 0.13表示放行 13%ratio_fieldstring否逐事件读取的采样比例字段数值须在(0, 1]与rate_field互斥rate_fieldstring否逐事件读取的采样速率字段正整数1/N语义与ratio_field互斥key_fieldstring否对指定字段值做哈希按“值分桶”采样与ratio_field/rate_field互斥group_bytemplate否按模板渲染结果分组各组独立计数采样excludecondition否逻辑条件命中条件的事件跳过采样直接放行sample_rate_keystring否记录实际采样率的字段名默认sample_rate设为空字符串则不再写入其中rate与ratio属于同一互斥组required_one_of二者必须且只能配置一个动态采样字段与静态配置的关系、合法性校验逻辑在 config.rs 中通过sample_rate()严格实现具体约束见下文“配置合法性校验”。rate 与 ratio 的差异rate N语义为“每 N 个事件放行 1 个”即保留1/N。当需要保留超过 50% 的事件如 80%时用 rate 无法表达1/1.25不是整数此时应使用 ratio。ratio p语义为“放行p比例的事件”支持更高精度例如0.672、0.8均可直接表达。这一点在 CUE 描述与代码注释中均被强调ratio允许“retain values of greater than 50% of all events”其实现也对应两种不同的采样模式见下文SampleMode。一个最小可用配置transforms: my_sample: type: sample inputs: [my_source] ratio: 0.1该配置对来自my_source的每条事件独立进行 10% 概率采样放行的事件会额外写入sample_rate 0.1字段。按字段哈希采样key_field 与 key 一致性key_field是 sample 最具特色的能力它不是对每个事件独立掷骰子而是对指定字段的值做哈希以“值”为单位形成采样桶。字段值相同的所有事件共享同一个桶桶整体被决定保留或丢弃。语义key_field: message时系统对message的取值做seahash哈希见 transform.rs 的hash_within_ratio并判断该哈希是否命中保留区间效果例如对trace_id做 key_field可以保证“同一条 trace 的日志要么全部保留、要么全部丢弃”从而实现整体1/N的 trace 级采样注意由于实际保真度取决于字段取值的均匀分布整体采样率可能与配置值存在偏差——CUE 描述明确提示“if values in the field are not uniformly distributed”这是使用 key_field 时必须接受的特性限制key_field与ratio_field/rate_field互斥config.rs因为动态值逐事件变化会破坏“同 key 同桶”的一致性对应错误InvalidKeyFieldDynamicCombination。在 tests.rs 中hash_consistently_samples_the_same_events测试验证了哈希采样的确定性对同一批事件运行两轮采样结果完全一致——这意味着 key_field 采样在管道重启后对相同数据仍然稳定可复现。按模板分组采样group_bygroup_by接受一个模板字符串如{{ service }}、{{ hostname }}-{{ service }}渲染结果作为分组键。其核心价值是独立计数每个分组拥有独立的计数器或采样器组与组之间互不影响。测试group_by_uses_independent_ratio_samplerstests.rs演示了service-a与service-b各自按 0.5 比例独立采样维度控量常用于“每个服务各保留一半日志”避免热门服务因流量大而占据全部保留额度、冷门服务被整体饿死与动态采样叠加group_by可与ratio_field/rate_field联合使用实现“按渲染出的分组值对每个组应用该组事件自带的采样率”模板渲染失败时不会丢弃事件而是记录TemplateRenderingError内部事件后按未分组处理transform.rs。实现上分组键OptionString作为HashMap的键counters/samplers/dynamic_event_counters未命中分组的事件统一归入None桶。动态采样ratio_field 与 rate_field当不同事件需要携带各自不同的采样率时例如上游日志已带sample_rate标注可使用动态采样字段ratio_field读取事件字段的数值作为比例。接受整数、浮点数或能解析为数字的字符串合法区间为(0, 1]浮点字段会直接用于比例计算rate_field读取事件字段作为速率1/N。只接受正整数或可解析为正整数的字符串浮点值会被拒绝——测试dynamic_rate_field_rejects_float_and_falls_back_to_static_ratiotests.rs专门验证了浮点值触发回退回退机制若字段缺失或取值非法则回退到静态配置的rate/ratio。对应的两个回退测试见 tests.rs优先级ratio_field优先于rate_fieldevent_sample_mode先查 ratio 再查 rate见 transform.rs动态模式下仍需要配置一个静态rate/ratio作为兜底——单配动态字段而没有静态策略会报MissingStaticConfiguration错误见 config.rs 及对应单元测试。动态采样与group_by结合时各组内以哈希 计数器实现“按比例命中”let hash Self::dynamic_sample_hash(group_by_key.as_deref(), old_counter_value); hash hash_ratio_threshold即对(分组键, 序号)做哈希并与按比例放大的阈值比较从而在每组内近似实现配置的比例transform.rs。配置合法性校验规则sample_rate()集中承载了配置的静态校验config.rs并在validate_structure中被调用。汇总所有约束错误触发条件InvalidDynamicConfiguration同时配置ratio_field与rate_fieldInvalidKeyFieldDynamicCombinationkey_field与ratio_field/rate_field并存InvalidStaticConfiguration同时配置rate与ratioInvalidRatioratio非正数ratio 0.0InvalidRaterate 0MissingStaticConfigurationrate、ratio均未配置包括只配动态字段的情形上述规则均有对应单元测试佐证例如rejects_both_dynamic_fields_configuration、rejects_key_field_with_dynamic_configuration等见 config.rs。值得说明的是ratio的上界1.0由 CUE 侧的validation(range(min 0.0, max 1.0))约束generated/sample.cue而下界 0由 Rust 侧强校验双重保障。底层实现原理两种采样模式SampleModetransform.rs区分了两种实现路径Rate 模式维护HashMapOptionString, u64计数器每来一个事件对分组键对应的计数加一当“旧计数对 rate 取模为 0”时放行——即经典的1/N节流若配置了key_field则额外对字段值哈希要求hash % rate 0才放行实现“值分桶”。Ratio 模式使用RatioSampler来自vector_lib::sampling按比例采样配合key_field时将ratio放大到u64全宽作为阈值hash_ratio_threshold ratio * u64::MAX再与字段值哈希比较hash threshold以规避浮点精度问题——代码注释明确说明这是“to address issues with precision”。动态采样ratio_field/rate_field则统一走“(分组键, 计数器)联合哈希”的第三条路径sample_with_dynamic_ratio/sample_with_dynamic_rate其命中判定同样基于阈值比较或取模。采样率标记与内部观测被放行的事件会写入采样率标记字段默认sample_rate对于日志事件以“源元数据”的形式写入insert_source_metadata命名空间为转换器名sample对于 trace 事件直接插入到事件路径sample_rate字段名可通过sample_rate_key自定义设为空字符串时不再写入任何标记注意通过exclude条件豁免放行的事件不会被打上采样率标记测试sampler_adds_sampling_rate_to_event对此有断言见 tests.rs。被丢弃的事件会触发内部事件SampleEventDiscarded它最终映射为ComponentEventsDropped::INTENTIONALreason: Sample discarded.见 sample.rs。这意味着一方面采样属于“有意丢弃”INTENTIONAL而非错误另一方面你可以在 Vector 的internal_metrics中观测component_discarded_events_total等指标量化实际丢弃量用于校准采样率。完整实战示例trace 级采样与关键日志豁免综合以上能力一个贴合生产实践的配置示例如下transforms: sample_traces: type: sample inputs: [normalized_logs] rate: 10 key_field: trace_id group_by: {{ service }} sample_rate_key: sampling.rate sample_errors_exempt: type: sample inputs: [normalized_logs] ratio: 0.1 exclude: | .level error第一个转换器按trace_id哈希分桶、以 1/10 采样同时按service分组——每个服务独立采样同一条 trace 的日志保持一致采样率写入sampling.rate字段第二个转换器按 10% 概率采样但凡是level error的事件直接放行确保错误日志不因采样而丢失。小结sample 转换器用极少的配置项覆盖了从“全局简单降采样”到“trace 级一致性采样”“按服务独立采样”“逐事件动态采样”的完整需求谱系rate/ratio决定整体策略key_field引入哈希分桶以保一致性group_by提供独立维度exclude保护关键事件sample_rate_key保证下游可感知采样率。其实现transform.rs以计数器 seahash 哈希 阈值比较为基石配合 config.rs 的严格校验与 tests.rs 中针对哈希确定性、回退行为、分组独立性的大量测试是一套可放心用于生产的高质量降采样方案。【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考