
Vector File Descriptor 源从已有文件描述符读取日志数据的完整解析【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector本文以 Vector 的file_descriptor数据源为对象系统讲解其配置参数fd、max_length、host_key、framing、decoding、行分隔与解码机制、事件输出结构并结合 源码实现 与 测试用例 说明该组件从裸 fd 读取字节、切帧解码并注入元数据的完整调用链读完即可掌握在 sidecar 场景中复用宿主机已有管道pipe文件描述符采集日志的实战方法。组件定位与核心能力file_descriptor是 Vector 的一个source数据源组件用于从一个已经存在的文件描述符file descriptor编号中读取日志数据。其官方文档页 file_descriptor.md 的定位即Collect logs from a file descriptor组件的详细元数据则维护在 CUE 文件 file_descriptor.cue 中。与stdin源固定绑定标准输入不同file_descriptor源让你通过配置直接指定任意已打开的 fd 编号例如通过pipe()系统调用获得并传递给 Vector 进程的管道读端。根据组件元数据classes与features段该组件具备如下特性特性取值说明投递语义deliveryat_least_once至少一次投递部署角色deployment_rolessidecar定位为 sidecar 场景开发状态developmentstable稳定版本数据出方式egress_methodstream流式输出是否有状态statefulfalse无状态组件确认机制acknowledgements不支持can_acknowledge返回false多行日志multiline不支持仅按行处理编解码codecs支持默认帧分隔为newline_delimitednative编解码器除外其为length_delimited接收来源stdin 服务接口从标准输入服务接口接收TLS不支持无网络接收面从源码结构看该组件仅在Unix 平台且启用sources-file_descriptorfeature 时编译见 mod.rs 中的#[cfg(all(unix, feature sources-file_descriptor))]它和stdin源共用同一套FileDescriptorConfigtrait 与流处理逻辑。配置参数详解组件的完整配置 schema 由代码宏生成并同步到 generated/file_descriptor.cue对应的 Rust 配置结构体为 FileDescriptorSourceConfig。字段如下fd必填# 要从中读取的文件描述符编号 fd 10类型uintRust 中为u32含义要读取的文件描述符编号The file descriptor number to read from示例值10。在 SourceConfig 实现 中build()方法通过File::from_raw_fd(self.fd as i32)将裸 fd 包装为File再套上io::BufReader进行缓冲读取。这里使用了unsafe代码块——fd 的所有权由外部通常是父进程或容器运行时负责管理Vector 只是借用这个编号来读因此必须确保配置中的 fd 在本进程内处于打开状态且可读否则会读到 Bad file descriptor 错误这一点被测试用例专门验证见下文。此外该组件通过resources()方法将Resource::Fd(self.fd)声明为自身占用的系统资源Vector 在组件管理如优雅关闭时会感知这一 fd 依赖。max_length选填# 接收消息的最大缓冲区大小字节超过该长度的消息将被截断 max_length 102400默认值102400字节约 100 KB由crate::serde::default_max_length提供默认值单位bytes行为超过该大小的消息会被截断而非丢弃整个事件。host_key选填# 覆盖用于向每个事件添加当前主机名的日志字段名 # 默认使用全局 log_schema.host_key 选项 host_key host类型字符串路径OptionalValuePath默认使用全局log_schema.host_key配置若未设置全局值则回退到log_schema().host_key()的默认值在 source() 构建逻辑 中可以推断其解析优先级为组件级 host_key → 全局 host_key → 默认值最终将主机名插入日志事件的host字段在 legacy 命名空间下为日志字段在 vector 命名空间下为元数据。framing选填# 帧framing配置定义原始字节流中每个事件帧如何分隔 framing { method newline_delimited }含义帧处理了原始字节形式下事件的分界方式——每个事件是一个帧必须以某种前缀或分隔符标记事件的起止边界若不显式配置则取decoding.default_stream_framing()即默认编解码器对应的newline_delimitednative编解码器为length_delimited。decoding选填# 配置如何从原始字节解码事件部分解码器还能决定事件输出类型log/metric/trace decoding { codec plain }类型DeserializerConfig默认值为plaindefault_decoding()部分解码器如json、native能同时决定输出事件的类型这也是为什么该源虽然主要输出日志但 schema 上仍保留了 metrics/traces 的输出声明见下文输出结构。完整配置示例[sources.file_descriptor_logs] type file_descriptor # 组件类型 fd 10 # 读取的文件描述符编号必填 max_length 102400 # 可选默认 102400 字节 # host_key host # 可选覆盖全局 host_key # framing { method newline_delimited } # 可选 # decoding { codec plain } # 可选默认 plain工作机制行分隔与解码管线行分隔符组件元数据中的 Line Delimiters 一节说明每一行读取到0xA字节换行符为止。即默认按\n切分行写入端每写一行以\n结尾就会产生一个候选事件再经framing/decoding配置进一步解析。从 fd 到事件的完整调用链核心流处理逻辑集中在 src/sources/file_descriptors/mod.rs调用链如下包装 fd 并启动后台读取线程source()方法L41-L88解析host_key与当前主机名构建DecodingConfigframing decoding log_namespace得到Decoder创建一个容量为 1024 的futures::channel::mpsc通道std::thread::spawn启动一个阻塞 I/O 线程调用read_from_fd()。源码注释明确指出这是 Tokio 的推荐做法——否则进程在收到换行前无法干净退出阻塞读取循环read_from_fd()L92-L111循环调用reader.fill_buf()读到空EOF时退出循环Interrupted错误则继续其他错误连同错误值一起发给通道每次将缓冲区内容拷贝为Bytes通过通道发出接收端关闭即退出异步解码与事件加工process_stream()L116-L199用StreamReaderDecoderFramedRead将字节流按帧切分并解码为事件读取错误会触发内部事件FileDescriptorReadError定义于 internal_events/file_descriptor.rs解码不可恢复错误!error.can_continue()则终止流对每个Log事件按log_namespace注入标准 Vector 源元数据source_type、ingest_timestamp等并通过host_key插入主机名下游接收端关闭时发出StreamClosedError并记录未发送事件数定义于 internal_events/common.rs全程发出BytesReceived与EventsReceived内部遥测事件供内部监控指标使用。这一设计与stdin源完全同构——两者共用outputs()辅助函数L203-L227其文档注释也明确写着Builds theOutputsfor stdin and file_descriptor sources。输出结构组件输出的字段结构由 CUE 元数据的output段定义数据面事件说明logsline逐行事件单个来自该文件描述符的事件包含host主机名、message原始行、timestamp当前时间戳三个字段metrics无专属事件仅可能由解码器顺带产生traces无专属事件仅可能由解码器顺带产生以line输出为例给定输入行2019-02-13T19:48:3400:00 [info] Started GET / for 127.0.0.1配置fd 10后输出的 log 事件为{ timestamp: current_timestamp, message: 2019-02-13T19:48:3400:00 [info] Started GET \/\ for 127.0.0.1, host: local_host }这正是 CUE 元数据examples段中 Line sent over pipe 示例所描述的输入→输出映射。源码与测试印证的行为细节该组件的行为有大量内联测试支撑位于 file_descriptor.rs 测试模块覆盖了三个关键场景正常解码file_descriptor_decodes_line测试通过nix::unistd::pipe()创建匿名管道将读端 fd 写入配置向写端写入hello world\nhello world again\n后关闭写端。断言事件流依次产出message hello world、hello world again随后 EOF 结束——印证了按\n分行、EOF 时流结束的行为。Vector 命名空间元数据file_descriptor_decodes_line_vector_namespace开启log_namespace true后日志值本身为纯行内容而vector.source_type file_descriptor、vector.ingest_timestamp等元数据挂在事件 metadata 上——对应process_stream中insert_standard_vector_source_metadata的调用。无效 fd 的容错file_descriptor_handles_invalid_fd故意给源一个写端 fdwrite-only源在首次读取时记录 Bad file descriptor 错误日志事件流安静结束而不 panic——印证了read_from_fd将 I/O 错误经通道转发、由FileDescriptorReadError内部事件上报的设计。另外GenerateConfig实现L71-L91揭示了生成默认配置时的一个细节由于测试环境没有真实可读管道generate_config()会通过null_fd()打开/dev/nullWindows 下为C:\NUL取一个合法 fd 填充fd字段保证生成的示例配置语法可解析。适用前提与限制平台限制该源依赖FromRawFd/IntoRawFd仅在 Unix 系平台编译启用fd必须是当前 Vector 进程内处于打开状态的文件描述符常见做法是父进程创建管道并将读端 fd 通过环境变量/约定编号传给 Vector 子进程无确认、无多行不支持端到端 ack也不做跨行的多行日志聚合日志切割逻辑必须在上游完成或依靠下游 transform截断策略单条消息超过max_length默认 102400 字节时截断而非丢弃无状态、至少一次组件不持久化任何读取进度进程重启后从 fd 的当前位置而非历史继续读可能漏掉上游重发窗口外的数据。小结file_descriptor源是 Vector 面向 sidecar/容器化场景的一个轻量入口以fd一个必填参数为锚点复用stdin源成熟的阻塞线程读取 通道 帧解码管线按0xA行分隔符切分事件并注入host/时间戳/源类型等标准元数据。配置侧仅需理解fd、max_length、host_key、framing、decoding五个参数实现侧的关键文件为 src/sources/file_descriptors/file_descriptor.rs 与 src/sources/file_descriptors/mod.rs行为边界可参照其内联测试与 文档元数据 交叉验证。【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考