尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Vector Log Namespacing 完全指南:从 Legacy 命名空间迁移到 Vector 命名空间的事件数据模型

发布时间:2026/9/13 10:33:21

资讯中心
01
ARTICLE

Vector Log Namespacing 完全指南:从 Legacy 命名空间迁移到 Vector 命名空间的事件数据模型

Vector Log Namespacing 完全指南:从 Legacy 命名空间迁移到 Vector 命名空间的事件数据模型
Vector Log Namespacing 完全指南从 Legacy 命名空间迁移到 Vector 命名空间的事件数据模型【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector本文基于 Vector 仓库中的设计文档 RFC 12187 - Log Namespacing 编写并结合仓库源码验证其落地实现。读者将掌握Vector 为什么引入事件元数据Event Metadata与命名空间机制、log_namespace配置的全局与按源使用方式、Data / Metadata / Secret Metadata 三类数据的组织规则以及各主流 source codec 组合下的完整事件结构示例从而安全地完成从 Legacy 模式到 Vector 模式的迁移。背景与问题任意键与根键冲突在引入命名空间之前Vector 反序列化事件数据时键key是任意的解码器产出的数据被直接放到事件根root上而这些任意键可能和已经存在于根上的数据发生碰撞。这种冲突带来的问题不只是数据丢失这么简单——它同时阻碍了 Vector 充分利用 Schema类型系统的能力。正因如此事件数据应当被重新结构化以杜绝碰撞并让事件整体更容易使用。该问题在 RFC 12187 中被正式提出并成为本设计的出发点。设计目标RFC 为 Log Namespacing 设定了三个核心目标类型可知当使用 Vector 命名空间时任何情况下 Schema / 类型都应该是已知的。忽略全局日志模式Global Log Schema全局日志模式应被忽略改用静态键。按需启用用户可以在每个 source 上单独启用新命名空间同时也能全局启用。这三个目标决定了后续所有方案细节Vector 命名空间必须是可选的、可逐步迁移的并且一旦启用就要让数据模型变得完全确定。方案总览Legacy 与 Vector 两种命名空间Vector 将引入两种日志命名空间默认使用Legacy旧版命名空间保持命名空间引入之前完全一致的行为新增的Vector命名空间则应用上述全部改动。这一设计的意图是让用户能够选择迁移opt-in migration最终 Legacy 命名空间可以被弃用并移除。在源码中这一点体现为lib/vector-core/src/config/mod.rs中定义的枚举#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, PartialOrd, Ord, Eq, Default)] pub enum LogNamespace { /// Vector native namespacing /// /// Deserialized data is placed in the root of the event. /// Extra data is placed in event metadata Vector, /// This is the legacy namespacing. /// /// All data is set in the root of the event. Since this can lead /// to collisions, deserialized data has priority over metadata #[default] Legacy, }见 lib/vector-core/src/config/mod.rs#L396-L410可以看到Legacy 模式下所有数据都放在事件根上正因为如此才可能发生碰撞碰撞时反序列化数据拥有优先权而 Vector 模式将反序列化数据放在事件根、把额外数据放进 event metadata。从源码注释看该模式从设计之初就明确了根 元数据的职责划分。用户配置log_namespace 布尔开关全局与按源面向用户的配置从简单的log_namespace布尔值开始。它同时作为全局设置和每个 source 的设置存在两者默认都为falsefalse→ 使用 Legacy 命名空间true→ 使用 Vector 命名空间。这种布尔形态让用户感觉只是在启用 / 禁用 log namespace 功能但设计上为未来留出了空间以后可以允许字符串值来指定命名空间名称如果引入更多命名空间的话。在源码中全局配置位于src/config/schema.rs的Options结构体#[configurable(metadata( status beta, docs::warnings Enabling log namespacing currently does not work when disk buffers are used. Avoid combining schema.log_namespace true with disk buffers until #18574 is resolved. ))] pub log_namespace: Optionbool,见 src/config/schema.rs#L40-L47配置的读取逻辑如下pub fn log_namespace(self) - LogNamespace { self.log_namespace .map_or(LogNamespace::Legacy, |use_vector_namespace| { use_vector_namespace.into() }) }见 src/config/schema.rs#L50-L57注意两个实现细节布尔值通过Frombool for LogNamespace转换为枚举lib/vector-core/src/config/mod.rs#L414-L422这正对应 RFC 中布尔开关内部转为枚举的说明。配置标注为beta状态且存在一个明确的运行时警告启用 log namespacing 目前不能与磁盘缓冲区disk buffers同时使用schema.log_namespace true与磁盘缓冲区的组合应避免直到 issue #18574 解决。这一点与 RFC 中未来需在磁盘缓冲区中持久化元数据的规划相呼应。全局配置在 Vector 配置文件中的写法示例schema: log_namespace: true # 全局启用 Vector 命名空间而 per-source 启用时例如为 kafka source 单独开启sources: my_kafka: type: kafka bootstrap_servers: localhost:9092 topics: [logs] log_namespace: true # 仅该 source 使用 Vector 命名空间在 src/sources/kafka.rs#L251 可以看到 kafka source 的log_namespace: Optionbool字段定义并在outputs方法中通过global_log_namespace.merge(self.log_namespace)src/sources/kafka.rs#L366-L367实现全局默认值 按源覆盖的合并逻辑。Options::appendsrc/config/schema.rs#L59-L72还会在同一个组件上同时出现冲突值时向错误列表写入提示。全局日志模式Global Log Schema被忽略当使用 Vector 命名空间时Global Log Schema 将被忽略改用静态键。此前 Global Log Schema 之所以存在是因为用户可以自定义键名从而避免与事件中的其他数据碰撞引入命名空间后这不再是问题因此该机制在 Vector 模式下不再需要。这一点在源码中有清晰的对应实现LogNamespace::insert_standard_vector_source_metadatalib/vector-core/src/config/mod.rs#L494-L512在 Vector 模式下把source_type与ingest_timestamp写进名为vector的元数据命名空间而不再依赖log_schema().source_type_key()/timestamp_key()这些可配置键。移除可配置的存储键与 Global Log Schema 类似部分 source 允许用户选择某些数据的存放键名这在使用 Vector 命名空间时也会被移除改用静态名称通常就是默认值。RFC 中给出的例子是 kafka source 的key_field和headers_key。源码证实了这一点src/sources/kafka.rs#L174-L212 中保留了key_field与headers_key配置用于 Legacy 模式同时 src/sources/kafka.rs#L1056-L1092 中apply逻辑会根据log_namespace决定把 key 与 headers 写进事件根还是事件元数据。在 Vector 模式下key与headers使用静态键并嵌套在kafka元数据命名空间下。运行时如何判定命名空间许多 transform / sink 依赖 Global Log Schema 来读取或修改 timestamp 等信息。由于 log schema 是按 source 可定制的transform 和 sink 必须能判断每条 log 使用的是哪个命名空间。RFC 给出的判定手段是只读的vector命名空间在元数据中的存在性——如果事件的元数据中存在vector命名空间即表明该事件使用 Vector 命名空间。事件的三类数据RFC 将事件中的数据明确划分为三类Data、Metadata 与 Secret Metadata。理解这三类数据的存放位置是使用 Vector 命名空间的核心。Data这是日志的主体内容即用配置的 decoder 解码出的数据放置在事件的根上。有一个特殊场景当 codec 为bytes时数据只是一个字符串此时根本身就是一个字符串。历史上这种形态是被禁止的但在命名空间设计中它成为可能。典型例子是 socket source 配合 bytes codec。Metadata这是来自 source、但没有放进事件的任何有用数据统一存储在事件元数据event metadata中Vector 自身元数据如ingest_timestamp、source_type嵌套在vector命名空间下Source 元数据使用source 类型名作为命名空间如kafka、syslog、datadog_agent。Secret Metadata诸如datadog_api_key、splunk_hec_token之类的密钥会被放进独立的容器使其更难被意外访问或泄漏。VRL 将提供访问 secrets 的函数类似于现有的get_metadata_field/set_metadata_field。这一设计已在仓库中落地lib/vector-vrl/functions/src/get_secret.rs实现了get_secret函数示例用法为get_secret(datadog_api_key)其作用是从事件中获取指定名称的 secret 值见 lib/vector-vrl/functions/src/get_secret.rs。docs/generated目录下同样收录了 get_secret.json、set_secret.json、remove_secret.json 等 VRL 函数文档说明 secret 的读、写、删除函数均已形成完整的能力集。各 Codec 下的行为命名空间方案针对不同 codec 定义了明确的落盘规则Bytes / Json解码后的数据根据 source 的具体实现被放到事件根或嵌套放置。Syslog所有数据放在事件根。因为 syslog 的结构是已知的命名碰撞很容易避免。syslog 的 message 字段理论上可以再套一层 codec但目前不支持本方案也不新增该支持。Native / Native JSON当这些 codec 用于 Vector source 时行为不变事件原样透传。Metadata 的三个来源与底层实现RFC 明确指出事件元数据有 3 个信息源Vector 内部 元数据如datadog_api_key供用户读写。这类数据已经存在但将被移动到独立的 secret metadata 中并新增 VRL 函数访问。Vector 元数据如ingest_timestamp和source_type每个 source 都会设置嵌套在vector命名空间下。Source 元数据随每个 source 而变化嵌套在 source 类型名下。源码中LogNamespace提供了一组对称的读写方法实现上述三类数据的存取方法作用Vector 模式行为Legacy 模式行为insert_source_metadata写入源元数据写入metadata.source_name路径按LegacyKey写入事件根Overwrite强制覆盖 /InsertIfEmpty仅空时插入None不写get_source_metadata读取源元数据从metadata.source_name读取从事件根读取insert_standard_vector_source_metadata写入标准 Vector 元数据写入vector.source_type与vector.ingest_timestamp使用source_type_key/timestamp_key写入事件根仅在字段为空时insert_vector_metadata/get_vector_metadata读写 Vector 元数据写入 / 读取vector.*路径写入 / 读取事件根实现见 lib/vector-core/src/config/mod.rs#L440-L549值得注意的底层细节Vector 命名空间下写入的元数据在 VRL 中被标记为只读read-onlyLegacyKey枚举区分Overwrite总是插入即使字段已存在与InsertIfEmpty仅在字段为空时插入两种策略lib/vector-core/src/config/mod.rs#L433-L438具体 source 在使用时会按需传入LegacyKey。例如 Datadog Agent source 以LegacyKey::InsertIfEmpty(owned_value_path!(ddsource))调用insert_source_metadatasrc/sources/datadog_agent/mod.rs#L310-L311保证 Legacy 模式下ddsource仅在根上不存在时才写入。元数据访问函数的改造需求RFC 指出当时事件元数据的支持非常有限需要立即完成以下改动支持任意嵌套的值访问元数据的函数get_metadata_field、remove_metadata_field、set_metadata_field应支持完整路径作为键并返回any类型而非仅string新增独立的 secret metadata新增访问 secret metadata 的 VRL 函数。同时 RFC 也坦承即使完成上述改动由于返回值类型总是any即便在同一段 VRL 程序中写入又读取元数据使用体验仍可能有些不便后续会有改进。具体示例完整以下示例全部使用新的 Vector 命名空间来自 RFC 12187 原文。Datadog Agent source / JSON codecevent{ derivative: -2.266778047142367e125, integral: 13028769352377685187, mineral: H 9 , proportional: 3673342615, vegetable: -30083 }metadata{ datadog_agent: { ddsource: waters, ddtags: env:prod, hostname: beta, service: cernan, status: notice, timestamp: 2066-08-09T04:24:42.1234Z }, vector: { source_type: datadog_agent, ingest_timestamp: 2022-04-14T19:14:21.899623781Z } }注timestamp由 DD agent 提供的 unix 时间戳解析而来。secrets各 source 形态相似后续示例不再重复列出{ datadog_api_key: 2o86gyhufa2ugyf4, splunk_hec_token: 386ygfhawnfud6rjftg }Datadog Agent source / bytes codecevent{\proportional\:702036423,\integral\:15089925750456892008,\derivative\:-6.4676193438086e263,\vegetable\:20003,\mineral\:\vsd5fwYBv\}metadata{ datadog_agent: { message: , ddsource: waters, ddtags: env:prod, hostname: beta, service: cernan, status: notice, timestamp: 2066-08-09T04:24:42.1234Z }, vector: { source_type: datadog_agent, ingest_timestamp: 2022-04-14T19:14:21.899623781Z } }bytes codec 下事件根为字符串原始报文原样保留在根上而message字段出现在源元数据中。Kafka source / json codecevent{ derivative: -2.266778047142367e125, integral: 13028769352377685187, mineral: H 9 , proportional: 3673342615, vegetable: -30083 }metadata{ kafka: { key: the key of the message, headers: { header-a-key: header-a-value, header-b-key: header-b-value }, topic: name of topic, partition: 3, offset: 1829448 }, vector: { log_namespace: vector, source_type: kafka, ingest_timestamp: 2022-04-14T19:14:21.899623781Z } }注headers 原本嵌套在可配置的headers_key下这里改用静态值headerskey与headers均不再进入事件根因此也不会与业务数据发生碰撞。Kubernetes Logs / Vector namespaceevent根事件元素为字符串F1015 11:01:46.499073 1 main.go:39] error getting server version: Get \https://10.96.0.1:443/version?timeout32s\: dial tcp 10.96.0.1:443: connect: network is unreachablemetadata{ kubernetes_logs: { file: /var/log/pods/kube-system_storage-provisioner_93bde4d0-9731-4785-a80e-cd27ba8ad7c2/storage-provisioner/1.log, container_image: gcr.io/k8s-minikube/storage-provisioner:v3, container_name: storage-provisioner, namespace_labels: { kubernetes.io/metadata.name: kube-system }, pod_annotations: { prometheus.io/scrape: false }, pod_ip: 192.168.1.1, pod_ips: [ 192.168.1.1, ::1 ], pod_labels: { addonmanager.kubernetes.io/mode: Reconcile, gcp-auth-skip-secret: true, integration-test: storage-provisioner }, pod_name: storage-provisioner, pod_namespace: kube-system, pod_node_name: minikube, pod_uid: 93bde4d0-9731-4785-a80e-cd27ba8ad7c2, stream: stderr }, vector: { source_type: kubernetes_logs, ingest_timestamp: 2020-10-15T11:01:46.499555308Z } }kubernetes_logs 源的海量 Pod 元数据labels、annotations、IP、node 等全部被收进kubernetes_logs命名空间不再与日志正文混在根上。Syslog / Vector namespaceeventHello Vectormetadata{ syslog: { source_ip: 127.0.0.1, hostname: localhost, severity: info, facility: facility, appname: Vector Hello World, msgid: 238467-435-235-a3478fh, procid: 13512, structured_data: { origin: timber.io } }, vector: { source_type: syslog, ingest_timestamp: 2020-10-15T11:01:46.499555308Z } }注structured_data的命名仍有讨论空间但任意键必须被嵌套在某个名称之下以避免冲突。Socket sourcemodeudp/ syslog codec / Vector namespaceevent{ message: Hello Vector, hostname: localhost, severity: info, facility: facility, appname: Vector Hello World, msgid: 238467-435-235-a3478fh, procid: 13512 }metadata{ socket: { source_ip: 192.168.0.1, hostname: localhost }, vector: { source_type: socket, ingest_timestamp: 2020-10-15T11:01:46.499555308Z } }注意syslog codec 在 socket source 下将结构化字段放在事件根因为结构已知、可防碰撞而仅把传输层信息source_ip放入socket元数据命名空间。HTTP source / JSON codec / Vector namespaceevent{ mineral: quartz, food: sushi }metadata{ http: { path: /foo/bar, headers: { Content-Type: application/json }, query_params: { page: 14, size: 3 } }, vector: { source_type: http, ingest_timestamp: 2020-10-15T11:01:46.499555308Z } }注headers 与 query params 此前直接放在事件根上这里必须嵌套以避免潜在的命名冲突。Kafka source / Native codec / Vector namespace这是一个端到端链路示例事件先经 Kafka sourceJSON codec进入经 Kafka sinknative codec写出再从 Kafka sourcenative codec读回。可以看到由于第一次 Kafka source 的key与headers没有被搬进事件它们只存在于事件元数据中这些值在链路中丢失了。event{ derivative: -2.266778047142367e125, integral: 13028769352377685187, mineral: H 9 , proportional: 3673342615, vegetable: -30083 }metadata仅来自第二个 kafka source{ kafka: { key: the key of the message (from the 2nd kafka source), headers: { header-a-key: header-a-value (from the 2nd kafka source), header-b-key: header-b-value (from the 2nd kafka source) }, topic: name of topic, partition: 3, offset: 1829448 }, vector: { source_type: kafka, ingest_timestamp: 2022-04-14T19:14:21.899623781Z } }这个例子直观展示了元数据与事件数据的生命周期差异元数据默认不随 native 编码持久化流转除非未来将元数据持久化到磁盘缓冲区这正是 RFC 将在磁盘缓冲区中持久化元数据列为未来增强的原因——sink 将需要元数据来区分不同的命名空间。未来增强方向RFC 明确列出以下后续演进项增加特殊的路径语法引用元数据及 secrets替代现有的函数调用方式将 schema 支持扩展到元数据将语义含义semantic meaning扩展到元数据允许 source 被配置为把额外数据来自元数据拉取进事件允许 sink 被配置为从元数据拉取额外数据在磁盘缓冲区中持久化元数据——sink 将需要元数据以区分命名空间。参考先例Prior Art本设计参考了 OpenTelemetry 的日志数据模型规范OpenTelemetry Logs Data Model其事件结构同样是日志体 属性/资源元数据的分离式设计与 Vector 的 Data Metadata 划分思路一致。落地实施路径Plan of AttackRFC 规划了两步实施路径完成 Datadog Agent Logs source 的 proof of conceptPOCPRRFC 中编号 12218先在一个 source 上验证命名空间的全链路可行性为每个组件逐步添加 log namespace 支持。从当前仓库源码看该方案已大面积落地log_namespace配置出现在 kafka、datadog_agent、docker_logs、exec、file、http_server、fluent、journald、kubernetes_logs、heroku_logs、demo_logs、dnstap 等数十个 source 中见 src/sources 下各模块LogNamespace枚举及其读写方法已成为事件模型的通用设施secret 相关的get_secret/set_secret/remove_secretVRL 函数也已实现并有独立文档docs/generated。源码索引为方便读者深入阅读将本文引用的关键实现汇总如下设计文档rfcs/2022-04-20-12187-log-namespacing.mdLogNamespace枚举与LegacyKeylib/vector-core/src/config/mod.rs#L396-L549全局schema.log_namespace配置src/config/schema.rs#L40-L78kafka source 的log_namespace/key_field/headers_keysrc/sources/kafka.rs#L174-L251Datadog Agent source 的命名空间接入src/sources/datadog_agent/mod.rs#L141-L361get_secretVRL 函数实现lib/vector-vrl/functions/src/get_secret.rs生成的 VRL 函数文档docs/generated/get_secret.json、docs/generated/set_secret.json、docs/generated/remove_secret.json结语Log Namespacing 是 Vector 事件模型的一次结构性升级它通过事件根承载业务数据 元数据承载来源信息 独立容器承载密钥的三层划分从根源上解决了任意键与根键的碰撞问题并让事件结构对 Schema 完全可预期。对于正在使用 Vector 的用户建议从单个 source 开启log_namespace: true开始小范围验证同时留意 beta 状态与磁盘缓冲区不兼容的已知限制再逐步扩大到全链路最终完成从 Legacy 到 Vector 命名空间的平滑迁移。【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。