Prhub

#48937 [Rust][Benchmark] Use `tracing` for logs

原始 PR 作者 BugenZhao 合并时间 2026-07-21 13:18 文件变更 24 提交数 5 评论 8 代码增减 +498 / -249

执行摘要

Rust bench 改用 tracing 输出日志到 stderr

PR body 指出:替换 raw printlneprintlntracing 及其结构化字段,与 Rust 前端约定保持一致,并统一日志输出目的地到 stderr,使最终结果 stdout 不受日志干扰,对解析结果的脚本兼容。

该 PR 是 Rust 日志系统规范化的重要步骤,设计简单但清晰。值得关注的是 RowDownloadReporter 如何优雅降级处理 TTY 和非 TTY 场景,以及 log_failed_requests 提取重复模式。对于类似需要同时支持交互式进度和日志输出的场景有参考价值。

讨论亮点
  • 初始化顺序tahsintunan 指出将 init_tracing 移至 Cli::parse() 之后,会使解析时产生的 no-op 警告被静默丢弃。作者采纳建议,回退为先初始化再解析,通过检查第一个参数决定标签。
  • 非 TTY 静默tahsintunan 提到非交互运行时 indicatif 进度条完全隐藏,Fetched 行数更新丢失,会导致数据集下载长时间无输出。作者提取了 RowDownloadReporter,在进度条隐藏时自动降级为 10 秒一次的 tracing::info,已解决此问题。
  • 独立二进制初始化chatgpt-codex-connector[bot] 指出独立 vllm-bench 二进制未安装 subscriber,会导致所有 tracing 事件被静默丢弃。作者后续提交 revert to init logging firstsimple subscriber 修复了此问题。

实现拆解

  1. 日志基础设施调整:修改 rust/src/cmd/src/logging.rsinit_tracing 函数,接受一个 process_label 参数,并将输出写入 std::io::stderr(原本输出到 stdout)。移除了硬编码的 PROCESS_LABEL 常量,改为由调用方传入(如 "Bench""RustFrontend")。
  2. 入口初始化rust/src/cmd/src/main.rs 中原本在 Cli::parse() 之前调用 init_tracing(),但为了能根据子命令传入不同的 process_label,一度改为先解析再初始化。Review 指出这会导致 Cli::parse() 中的警告丢失,最终版本回退为先初始化再解析,并通过手动匹配 std::env::args() 获取子命令来设置标签。
  3. 替换所有 println / eprintln:在 rust/bench 子包的 benchmark.rsmulti_turn.rshf_dataset.rsspeed_bench.rstokenizer.rstiktoken.rsconfig.rssharegpt.rs 等文件中,将进度提示、错误报告、配置输出等全部替换为 tracing::info! / tracing::warn!,并附带结构化字段。例如 DNS 预解析结果、模型选择、数据集下载进度等。
  4. 提取 log_failed_requests 函数:在 rust/src/bench/src/metrics/calculator.rs 中,将 calculate_metricscalculate_embedding_metrics 中重复的失败请求输出逻辑提取为独立函数,统一使用 tracing::warn! 记录,输出结构化的 failed_requestsdisplayed_errors 和每条错误详情。
  5. 新增 RowDownloadReporter 处理非 TTY 降级:新增 rust/src/bench/src/datasets/progress.rs,定义一个 RowDownloadReporter 结构体。当进度条隐藏(非 TTY)时,以 10 秒间隔通过 tracing::info! 报告行数。附带单元测试 hidden_reporter_uses_ten_second_deadline 验证时间逻辑。
文件 模块 状态 重要度
rust/src/bench/src/datasets/progress.rs 进度报告 added 8.68
rust/src/bench/src/benchmark.rs 基准入口 modified 7.64
rust/src/cmd/src/logging.rs 日志模块 modified 6.94
rust/src/bench/src/metrics/calculator.rs 指标计算 modified 7.0
rust/src/bench/src/main.rs 入口 modified 6.03

关键符号

RowDownloadReporter::new RowDownloadReporter::update RowDownloadReporter::finish RowDownloadReporter::should_report log_failed_requests init_tracing VllmEventFormatter::new pre_resolve_dns run_benchmark hidden_reporter_uses_ten_second_deadline formatter_prefix_uses_process_label

关键源码片段

rust/src/bench/src/datasets/progress.rs core-logic

新文件,实现了 RowDownloadReporter 结构体,在非 TTY 下降级为 tracing 日志报告进度,替代之前直输出到 stderr 的 eprint!。

// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright contributors to the vLLM projectuse std::time::{Duration, Instant};
use indicatif::{ProgressBar, ProgressStyle};const REPORT_INTERVAL: Duration = Duration::from_secs(10);/// Reports row download progress to an interactive progress bar, or through
/// periodic tracing events when the progress bar is hidden on a non-TTY.
pub(super) struct RowDownloadReporter {
    progress: ProgressBar,
    next_report: Instant,
}impl RowDownloadReporter {
    /// Creates a reporter that emits non-TTY updates every 10 seconds.
    pub fn new() -> Self {
        let progress = ProgressBar::new(0);
        progress.set_style(
            ProgressStyle::with_template(
                "{spinner:.green} Fetching rows [{bar:30.cyan/blue}] {pos}/{len}",
            )
            .unwrap()
            .progress_chars("#>-"),
        );
        Self {
            progress,
            next_report: Instant::now() + REPORT_INTERVAL,
        }
    }    /// Updates the current row count and reports progress when due.
    pub fn update(&mut self, rows: usize, total: u64) {
        let rows = rows as u64;
        let total = total.max(rows);
        self.progress.set_length(total);
        self.progress.set_position(rows);        if self.should_report(Instant::now()) {
            // 在非 TTY 模式下,通过 tracing 输出结构化日志,避免静默
            tracing::info!(rows, total, "fetching dataset rows");
        }
    }    /// Clears the interactive progress bar after the download completes.
    pub fn finish(self) {
        self.progress.finish_and_clear();
    }    // 判断是否应通过 tracing 上报:仅当进度条隐藏(非 TTY)且距上次报告已超 10 秒
    fn should_report(&mut self, now: Instant) -> bool {
        if !self.progress.is_hidden() || now < self.next_report {
            return false;
        }
        self.next_report = now + REPORT_INTERVAL;
        true
    }
}#[cfg(test)]
mod tests {
    use super::*;    #[test]
    fn hidden_reporter_uses_ten_second_deadline() {
        // 验证时间间隔逻辑:9 秒内不报,10 秒内报,19 秒内不报,20 秒报
        let start = Instant::now();
        let mut reporter = RowDownloadReporter {
            progress: ProgressBar::hidden(),
            next_report: start + REPORT_INTERVAL,
        };        assert!(!reporter.should_report(start + Duration::from_secs(9)));
        assert!(reporter.should_report(start + Duration::from_secs(10)));
        assert!(!reporter.should_report(start + Duration::from_secs(19)));
        assert!(reporter.should_report(start + Duration::from_secs(20)));
    }
}

评论区精华

初始化顺序导致警告丢失 正确性

tahsintunan 指出将 init_tracing 移至 Cli::parse 之后会丢失 no-op 参数解析警告。

结论:作者回退为先 init_tracing 再解析,通过匹配第一个参数确定进程标签。 · 已解决

非 TTY 环境进度条静默 性能

tahsintunan 提到非交互运行时 indicatif 隐藏进度条导致无输出。

结论:作者提取 RowDownloadReporter,在进度条隐藏时降级为定期 tracing::info 输出。 · 已解决

独立二进制需初始化 tracing 正确性

chatgpt-codex-connector[bot] 指出 standalone vllm-bench 未安装 subscriber,所有 tracing 事件被静默丢弃。

结论:作者在后续提交中为 bench 添加了 init_tracing 调用。 · 已解决

风险与影响

  • 回归风险(低):所有 println / eprintln 被替换,如果外部工具依赖 stderr 输出内容,可能需要调整。但 PR 明确说明 stdout 仅输出最终结果,之前日志混在 stdout 的情形被隔离,对外部脚本实际更友好。
  • 日志丢失风险(已修复):独立二进制未初始化 subscriber 会导致日志静默丢弃。作者通过尽早初始化并设置默认 subscriber 解决。
  • 性能影响(近乎为零)tracing 相比 println 有额外开销,但在 bench 场景下可忽略。
  • 兼容性(高):仅更改 Rust bench 工具的内部日志方式,不涉及 API、模型或调度逻辑,不影响 Python 层。
  • 用户:使用 vllm-bench 的用户会发现日志输出更结构化(JSON 格式),且 stdout 更干净。解析基准测试结果的脚本不受影响。
  • 开发者:调试 Rust bench 时日志更易过滤和查询,可观测性提升。
  • 系统:日志重定向到 stderr 是更好的实践,方便与 stdout 分离。
独立二进制缺少 tracing 初始化 非 TTY 环境日志丢失 初始化顺序导致警告丢失

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论