尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Vector Exclusive Route(独占路由)转换详解:按条件将事件独占分流到唯一子流

Vector Exclusive Route(独占路由)转换详解:按条件将事件独占分流到唯一子流 Vector Exclusive Route独占路由转换详解按条件将事件独占分流到唯一子流【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vectorExclusive Route独占路由是 Vector 可观测性数据管道中一类特殊的transform组件它的职责是将一个或多个输入流中的事件按照用户定义的一组条件路由到互斥的唯一子流中。与普通 Route 转换一份事件可同时进入多条子流不同Exclusive Route 遵循**先匹配先得first-match-wins**原则路由按声明顺序依次求值一旦事件命中某个路由它就被独占性地送入该路由对应的输出端口后续路由不再参与求值。读完本文你将掌握 Exclusive Route 的完整配置语法、_unmatched兜底输出的行为、它与 Route 转换的本质区别以及其底层 Rust 实现与校验逻辑。一、Exclusive Route 是什么一次事件只进入一条子流在 Vector 的组件模型中exclusive_route属于 transform 类别官方对它的定义是Routes events from one or more streams to unique sub-streams based on a set of user-defined conditions. Routes are evaluated in order and once an event matches a route, it is sent exclusively to that route and no further routes are evaluated.即把事件从一条或多条输入流路由到唯一的子流路由按顺序求值事件一旦匹配某条路由就被独占发送到该路由不再继续求值后续路由。组件元数据见 exclusive_route.cue明确了它的特性开发成熟度development classbeta出口方式egress methodstream以子流形式输出有状态statefulfalse无状态转换可以安全地并行处理输入类型logs、metricscounter / distribution / gauge / histogram / set / summary 全类型、traces 均可作为输入输出类型每个路由一个输出端口端口上输出的事件就是原始输入事件本身log 事件、metric 事件、trace 事件原样透传一个事件只能被路由到一个输出这是 Exclusive Route 与 Route 转换可将同一事件复制到多个子流最核心的差异。二、配置结构routes 数组 命名条件Exclusive Route 的配置非常简单核心只有一个必填字段routes。其完整参数定义位于生成配置 CUE 中见 generated/exclusive_route.cue参数类型是否必填说明routesarrayobject 数组是一组命名路由。路由名必须唯一路由按声明顺序从第一个到最后一个依次求值只有第一个匹配的路由会收到每个事件first-match-winsroutes[].namestring是路由名称同时就是该转换的输出端口名。_unmatched为保留名称不能用作路由 ID其他组件可用transform_name.name引用该输出未匹配任何路由的事件会被发送到transform_name._unmatchedroutes[].conditioncondition是应用于每个事件的过滤条件官方给出的最小化配置示例routes: - name: foo-and-bar-exist condition: type: vrl source: exists(.foo) exists(.bar) - name: only-foo-exists condition: type: vrl source: exists(.foo)2.1 condition 支持的条件类型condition字段在源码中定义为AnyCondition见 src/conditions/mod.rs它是一个宽泛的条件类型既可以直接写字符串自动按 VRL 编译也可以写成 map 结构。map 结构下支持的条件类型ConditionConfig枚举包括vrl基于 VRLVector Remap Language表达式的条件最常用例如source: .level erroris_log/is_metric/is_trace按事件类型判定例如在混流场景下先按类型拆分datadog_searchDatadog 日志搜索语法条件也支持type: vrl之外的运行时条件组合如and/or/not等组合条件。由于AnyCondition支持字符串简写配置中也可以把条件直接写成字符串例如condition: exists(.foo)它与type: vrl的 map 写法等价。2.2 输出端口每条路由 隐式 _unmatched从源码outputs()的实现见 src/transforms/exclusive_route/config.rs可以看到Exclusive Route 的输出端口由两部分构成为每个声明的路由生成一个以路由名命名的端口始终额外追加一个名为_unmatched的兜底端口——任何没有命中任何路由的事件都会被送到这里。也就是说声明 N 条路由就会产生 N1 个输出端口。这一点在设计下游组件时非常重要即使你认为事件必然命中某条路由_unmatched端口依然存在并承载未被命中的事件需要显式消费或丢弃否则可能造成事件在拓扑中悬空。三、完整实战示例按日志级别独占分流官方文档的 how-it-works 部分见 exclusive_route.cue给出了一个可以直接落地的完整示例。下面的配置创建了两条独占路由外加隐式创建的_unmatched路由并通过 Vector 内置的单元测试框架验证路由行为transforms: transform0: inputs: - source0 type: exclusive_route routes: - name: a condition: type: vrl source: .level 1 - name: b condition: type: vrl # 注意第一个条件其实是冗余的前一条路由总是拥有更高优先级 source: .level 1 || .level 2 tests: - name: case-1 inputs: - type: log insert_at: transform0 log_fields: level: 1 - type: log insert_at: transform0 log_fields: level: 2 outputs: - extract_from: transform0.a conditions: - type: vrl source: | assert!(.level 1) - extract_from: transform0.b conditions: - type: vrl source: | assert!(.level 2)3.1 示例行为解读路由a捕获level 1的事件路由b声明捕获level 1 || level 2但由于路由a优先求值level 1的事件已经全部被a独占拿走所以路由b实际只会收到level 2的事件——这正是示例注释中所说的第一个条件冗余前一条路由总是拥有更高优先级。单元测试case-1中extract_from: transform0.a断言收到的日志level 1extract_from: transform0.b断言收到的日志level 2从测试层面锁定了先匹配先得的语义。若还有level 3之类的事件它将不会命中任何路由被送入transform0._unmatched。3.2 下游如何引用路由输出每条路由的输出端口可被其他组件以transform_name.route_id的形式作为inputs引用。例如假设上面的转换名为transform0那么下游可以这样接transforms: transform0: inputs: [source0] type: exclusive_route routes: - name: errors condition: type: vrl source: .level error - name: others condition: type: vrl source: .level ! error error-pipeline: type: remap inputs: [transform0.errors] # 只处理 error 事件 source: | .alert true fallback-pipeline: type: remap inputs: [transform0.others] # 处理其余事件 source: | .alert false sinks: ...一个事件只会出现在transform0.errors或transform0.others中的某一个输出上_unmatched输出同样可用transform0._unmatched引用。四、源码级原理first-match-wins 是如何实现的4.1 核心处理逻辑Exclusive Route 的核心运行逻辑非常简洁完整实现在 src/transforms/exclusive_route/transform.rsimpl SyncTransform for ExclusiveRoute { fn transform(mut self, event: Event, output: mut TransformOutputsBuf) { for route in self.routes { let (result, event) route.condition.check(event.clone()); if result { output.push(Some(route.name), event); return; // 命中后立即返回不再求值后续路由 } } output.push(Some(UNMATCHED_ROUTE), event); // 全部未命中进入 _unmatched } }这段代码对应了文档描述的全部关键语义按声明顺序遍历路由for route in self.routes中的顺序即配置中routes数组的书写顺序命中即独占output.push(Some(route.name), event)后立即return后续路由完全不会被求值条件失败恢复事件route.condition.check(event.clone())返回(result, event)二元组——条件引擎在执行 VRL 等条件时可能消耗事件所有权因此通过返回值把事件交还保证未命中时事件仍可继续参与后续路由判断兜底输出循环结束后若仍无命中事件进入保留端口_unmatched常量定义见 config.rs 中的pub(super) const UNMATCHED_ROUTE: str _unmatched;。从TransformConfig的实现可见该转换实现了Transform::synchronous(route)同步转换见 config.rs并声明enable_concurrency() - true允许 Vector 对事件流进行并发处理由于组件stateful: false并发下也不存在共享状态问题。4.2 配置期校验重复名与保留名validate_structure()见 config.rs在配置加载阶段就会做两项硬校验路由名重复如果routes中出现两个同名的路由会报错Found routes with duplicate names: [...]使用保留名_unmatched任何路由不允许命名为_unmatched否则报错Using reserved _unmatched name.。此外validate_with_context()会对每条路由的条件做上下文校验如检查 VRL 条件能否在给定的 enrichment tables 与 metrics storage 下编译运行错误信息会带上具体路由名route xxx: ...便于定位是哪个路由的条件写错了。4.3 单元测试验证仓库内置的测试见 src/transforms/exclusive_route/tests.rs直接验证了独占语义exclusive_routes测试构造了路由a.service a与路由b.service b分别注入servicea/b/c三种事件断言service a只出现在输出aservice b只出现在输出b而service c只出现在_unmatched输出——一次事件绝不跨多条子流route_metrics_with_output_tag测试则验证了多输出组件相关的可观测性组件内部指标会携带output标签tag以区分不同路由端口的统计。五、Exclusive Route 与 Route 的区别何时用哪个Vector 同时提供route与exclusive_route两个转换官方文档在各自的 CUE 元数据中互相引用了对方作为对照见 exclusive_route.cue 与 route.cue维度routeRouteexclusive_routeExclusive Route路由语义条件为 map 形式route: { key: condition }事件可同时进入所有命中的路由条件为数组形式routes: [{name, condition}]事件只能进入第一个命中的路由求值方式各路由条件独立求值不互斥按声明顺序依次求值先匹配先得兜底输出无隐式兜底端口未命中即无处可去自动生成_unmatched兜底端口开发成熟度stablebeta典型场景需要把一条事件复制到多个下游如同时告警 存储 审计需要把事件切分到互斥的分支如按错误级别分流到不同处理管道Route 的配置形态routemap 写法与 Exclusive Route 的数组写法也完全不同例如 Route 的按日志级别拆分transforms: my-routes: inputs: [some_source] type: route route: debug: .level debug info: .level info warn: .level warn error: .level error对照可见如果下游语义要求一份事件只能属于一条分支例如互斥的降级/丢弃策略请选exclusive_route如果要求一份事件可以同时流入多条分支请选route。六、使用建议与注意事项路由顺序即优先级由于 first-match-wins 语义应当把最具体 / 优先级最高的条件写在数组前面。前文示例中路由b条件里包含.level 1但从不会收到level 1的事件就是顺序决定行为的典型体现。不要漏掉_unmatched每声明 N 条路由实际会产生 N1 个输出端口。如果下游拓扑只消费了命名的路由而漏掉_unmatched未匹配事件会无处可去规划拓扑时请显式为_unmatched指定去向或使用blackhole等 sink 显式丢弃。充分利用内置单元测试如第三节所示可以在配置文件的tests段用insert_at: transform_name注入事件、用extract_from: transform_name.route_id断言各路由收到的内容配合vrl条件的assert!/assert_eq!在部署前锁定路由行为。条件类型按需选择纯类型判断可用is_log/is_metric/is_trace基于字段的复杂判断用vrlDatadog 用户可用datadog_search语法。所有条件在配置加载时即被校验错误信息会精确到具体路由名。配置加载即校验重复路由名与_unmatched保留名都会在validate_structure阶段被直接拒绝而不是运行期才发现因此写好配置后先用vector validate或vector validate --no-environment校验是一个低成本高收益的习惯。七、小结Exclusive Route 是 Vector 中实现互斥分流的标准组件一条路由数组 先匹配先得语义 自动_unmatched兜底输出构成了一次事件恰好进入一条子流的完整机制。其无状态、可并发、支持全事件类型的特性使其非常适合在日志/指标/追踪混流管道中做按类型、按级别、按字段的独占切分。配合文档中的配置示例、仓库中的单元测试与vector validate校验你可以快速构建出行为确定、可验证的分流拓扑。进一步探索可参考组件元数据定义website/cue/reference/components/transforms/exclusive_route.cue生成配置参数说明website/cue/reference/components/transforms/generated/exclusive_route.cue配置与校验实现src/transforms/exclusive_route/config.rs运行期路由逻辑src/transforms/exclusive_route/transform.rs行为测试用例src/transforms/exclusive_route/tests.rs对照组件 Routewebsite/cue/reference/components/transforms/route.cue条件类型定义src/conditions/mod.rs【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表