news 2026/9/29 2:27:23

polkadot-node-metrics:Polkadot 节点指标收集框架与 Runtime 指标上报实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
polkadot-node-metrics:Polkadot 节点指标收集框架与 Runtime 指标上报实战
  • 区块链

【免费下载链接】polkadot

Polkadot Node Implementation

项目地址:https://gitcode.com/gh_mirrors/po/polkadot
点击查看免费下载

本篇技术指南围绕 node/metrics 这一 Subsystem 指标辅助 crate(polkadot-node-metrics)展开,讲解其在 Polkadot 节点中的定位、构建前提、Metronome周期采样机制、Metricstrait 设计,以及基于 Substrate WASM tracing 的 Runtime 指标(runtime-metrics)完整上报链路。读完本文,你将掌握:如何正确构建并测试该 crate、如何在 overseer 中用Metronome周期性采集指标快照、如何用logger_hook()把 Runtime 侧 Prometheus 指标桥接到客户端 Prometheus registry,以及如何验证这条链路的正确性。

一、crate 定位与能力总览

polkadot-node-metrics是一个"子系统指标助手"(Subsystem metric helpers)crate,其职责在 node/metrics/src/lib.rs 的 crate 级文档中定义得很清楚:收集一批指标提供者(metrics providers)以及诸如Metronome之类的配套能力,供指标采集使用,同时重新导出(reexport)子系统需要实现/使用的 Prometheus 指标类型。

该 crate 主要提供四类能力:

能力说明关键源码位置
Metronome以固定周期产生 tick 的Stream,用于周期性采集指标node/metrics/src/metronome.rs
Metricstrait子系统/任务专用 Prometheus 指标的统一注册接口node/metrics/src/lib.rs
Prometheus 类型 reexport重新导出substrate_prometheus_endpoint,子系统可直接复用node/metrics/src/lib.rs
Runtime 指标提供者runtime-metricsfeature 下的logger_hook()与RuntimeMetricsProvidernode/metrics/src/runtime/mod.rs

crate 的依赖设计(见 node/metrics/Cargo.toml)值得注意:它依赖了metered(即prioritized-metered-channel)来获取 channel 的计量数据,并依赖sc-service、sc-cli、substrate-prometheus-endpoint、sc-tracing等 Substrate 组件——注释明确指出sc-service与sc-cli是 Runtime 指标logger_hook()所必需的。

crate 还通过 Cargo features 控制编译开关:

  • default = []:默认不开启任何额外能力,此时logger_hook()退化为一个空操作闭包(见 node/metrics/src/lib.rs);
  • runtime-metrics:启用 Runtime 指标提供者模块(runtime模块仅在开启该 feature 时编译,见 node/metrics/src/lib.rs);
  • runtime-benchmarks:与测试条件配合,控制集成测试的编译范围(见 node/metrics/src/lib.rs)。

二、测试前提:先构建两个 PVF worker 二进制

polkadot-node-metrics的 README 只有一节,但非常关键,它规定了该 crate 的测试前置条件:

Before runningcargo testin this crate, make sure the worker binaries are built first.

在运行本 crate 的cargo test之前,必须先构建 worker 二进制,命令如下:

cargo build --bin polkadot-execute-worker --bin polkadot-prepare-worker

为什么会有这个前提?因为 node/metrics/src/tests.rs 中的集成测试会通过polkadot-test-service(见 node/test/service)启动真实的验证人节点(validator node),而节点运行 PVF(平行链验证函数)需要polkadot-execute-worker(执行 worker)与polkadot-prepare-worker(准备 worker)这两个进程级 worker 二进制。这些 worker 由 node/core/pvf 的execute-worker与prepare-worker子 crate 产出,属于同仓库内编译产物,不会随依赖自动构建,因此必须先显式cargo build,否则测试节点启动时会因找不到 worker 而失败。

测试代码的依赖也印证了这一点:dev-dependencies 中引入了polkadot-test-service(并开启runtime-metricsfeature)、substrate-test-utils、sp-keyring、hyper、tokio、prometheus-parse等(见 node/metrics/Cargo.toml),完整模拟"起节点 → 抓取 Prometheus 指标 → 解析断言"的端到端验证。

三、Metronome:周期驱动的指标采样源

Metronome是一个按固定周期产生 tick 的futures::Stream,其实现位于 node/metrics/src/metronome.rs,核心代码量不大但很精炼:

pub struct Metronome { delay: Delay, period: Duration, state: MetronomeState, // Snooze / SetAlarm } impl Metronome { pub fn new(cycle: Duration) -> Self { let period = cycle.into(); Self { period, delay: Delay::new(period), state: MetronomeState::Snooze } } }

从源码看,它内部持有一个futures_timer::Delay和一个内部状态机:

  • Snooze(休眠)状态:轮询内部Delay,若尚未就绪则返回Poll::Pending;若就绪则切换到SetAlarm并返回Poll::Ready(Some(()))产出一个 tick;
  • SetAlarm(设闹钟)状态:用self.period重置Delay,回到Snooze状态。

由于每次 tick 后都会用同一周期重置计时器,Metronome是一个永不终止的无限流,这一点在 node/subsystem-util/src/tests.rs 的单元测试注释中被直接写为unreachable!("Metronome never stops. qed")。

Metronome的典型使用场景在 node/overseer/src/lib.rs 的spawn_metronome_metrics函数中:overseer 用Metronome::new(std::time::Duration::from_millis(950))创建约950ms 一个周期的采样器,每个 tick 触发:

  1. collect_memory_stats(&metronome_metrics):采集内存分配统计;
  2. metronome_metrics.channel_metrics_snapshot(...):汇总所有子系统到 overseer 的 channel 消息量(将各子系统的subsystem_meters快照合并成一个to_overseer指标)。

这种"周期 tick + 快照采集"的模式正是Metronome存在的意义:把低频、周期性的指标聚合任务与事件驱动的消息处理解耦。若需要其他周期,直接向Metronome::new传入不同的Duration即可。

四、Metrics trait:子系统的 Prometheus 指标注册约定

所有子系统/任务专用的 Prometheus 指标都通过 node/metrics/src/lib.rs 定义的Metricstrait 统一接入:

pub trait Metrics: Default + Clone { fn try_register( registry: &prometheus::Registry, ) -> Result<Self, prometheus::PrometheusError>; fn register( registry: Option<&prometheus::Registry>, ) -> Result<Self, prometheus::PrometheusError> { match registry { None => Ok(Self::default()), Some(registry) => Self::try_register(registry), } } }

该 trait 的设计要点:

  • Default + Clone约束:实现者通常是Option<ActualMetrics>的包装(无 registry 时取Default空实现),或者是单元类型();Prometheus 指标内部持有Arc引用,克隆成本极低,因此可以放心 clone 分发;
  • try_register:真正把指标注册进 Prometheus registry;
  • register:便捷方法——传入None(未启用 Prometheus)时静默返回Default::default(),传入Some(registry)时等价于try_register。这样子系统在"启用/未启用 Prometheus"两种配置下都能统一调用register(registry.as_ref());
  • 为()提供了空实现:try_register直接返回Ok(()),使得"无指标"的子系统也能天然满足Metrics约束。

模块中还pub use substrate_prometheus_endpoint as prometheus重新导出了 Substrate 的 Prometheus 端点(见 node/metrics/src/lib.rs),意味着子系统编写指标时直接使用polkadot_node_metrics::metrics::prometheus::{Counter, Gauge, ...}即可,无需各自引入 Substrate 依赖。overseer 正是这样做的(见 node/overseer/src/lib.rs),它pub use polkadot_node_metrics::{... Metronome, ...}直接复用本 crate 的指标基础设施。

五、Runtime 指标:从 WASM Runtime 到 Prometheus 的完整链路

5.1 整体架构:WASM tracing 事件桥接

polkadot-node-metrics的进阶能力是runtime-metricsfeature 下的 Runtime 指标提供者,其设计思路记录在 node/metrics/src/runtime/mod.rs 的模块文档中:

A runtime metric provider implementation that builds on top of Substrate wasm tracing support. This requires that the custom profiler (TraceHandler) to be registered in substrate via alogger_hook(). Events emitted from runtime are then captured/processed by theTraceHandlerimplementation.

也就是说:Runtime 侧(WASM)发出的指标事件,通过 Substrate 的 WASM tracing 机制传输到客户端(native),由注册在logger_hook()里的TraceHandler捕获并落地到 Prometheus 指标。完整链路为:

  1. Runtime 侧:polkadot-runtime-metrics(runtime/metrics/src/with_runtime_metrics.rs)提供 Prometheus 风格的Counter/CounterVec/Histogram类型。它们的inc_by/observe方法会构造一个RuntimeMetricUpdate结构体(含指标名 + 操作),经 SCALE 编码后用bs58编码,再通过sp_tracing::event!(target: "metrics", Level::TRACE, update_op = ...)发射 tracing 事件(见 runtime/metrics/src/with_runtime_metrics.rs);
  2. 客户端侧:RuntimeMetricsProvider实现sc_tracing::TraceHandler,在handle_event中过滤target == "metrics"的事件,从params字符串解析出bs58编码的RuntimeMetricUpdate,解码后执行对应的指标更新(见 node/metrics/src/runtime/mod.rs);
  3. 落地:RuntimeMetricsProvider持有Registry与三个内部 HashMap(counter_vecs/counters/histograms,均以Arc<Mutex<...>>保护),把更新映射到真正的 PrometheusCounterVec/Counter/Histogram。

数据结构的定义在 primitives/src/v5/metrics.rs:

pub enum RuntimeMetricOp { IncrementCounterVec(u64, RuntimeMetricLabelValues), IncrementCounter(u64), ObserveHistogram(u128), } pub struct RuntimeMetricUpdate { pub metric_name: Vec<u8>, pub op: RuntimeMetricOp, }

5.2 logger_hook():注册 TraceHandler 的入口

客户端侧接入的入口是logger_hook(),其实现位于 node/metrics/src/runtime/mod.rs:

pub fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () { |logger_builder, config| { if config.prometheus_registry().is_none() { return } let registry = config.prometheus_registry().cloned().unwrap(); let metrics_provider = RuntimeMetricsProvider::new(registry); parachain::register_metrics(&metrics_provider); logger_builder.with_custom_profiling(Box::new(metrics_provider)); } }

关键行为:

  • 若节点未配置 Prometheus registry(prometheus_registry().is_none())则直接返回,不做任何事,避免无谓开销;
  • 有 registry 时,创建RuntimeMetricsProvider,调用parachain::register_metrics预注册一组平行链 Runtime 指标,最后通过logger_builder.with_custom_profiling把 provider 注册为 Substrate 自定义 profiler(TraceHandler)。

该 hook 的实际接线发生在 CLI 层:polkadot 命令的主流程在 cli/src/command.rs 调用run_node_inner(..., polkadot_node_metrics::logger_hook()),run_node_inner再把它传给create_runner_with_logger_hook(见 cli/src/command.rs)。因此,只要用polkadotCLI 启动节点并开启 Prometheus 端点,Runtime 指标上报链路就自动生效。

5.3 指标注册与更新:客户端侧实现

RuntimeMetricsProvider暴露三组注册与更新方法(见 node/metrics/src/runtime/mod.rs):

方法作用
register_countervec/register_counter/register_histogram将 Runtime 侧定义的指标注册进 registry,以指标名为 key 去重(or_insert),重复注册不会覆盖
inc_counter_vec_by(name, value, labels)按标签值递增CounterVec
inc_counter_by(name, value)递增普通Counter
observe_histogram(name, value)记录直方图观测值,入参单位为纳秒(ns),内部除以1_000_000_000.0转换为秒后交给 Prometheus Histogram

handle_event的解析细节也值得注意(见 node/metrics/src/runtime/mod.rs):Runtime 侧通过sp_tracing宏格式化出的params形如" { update_op: <bs58字符串> }",客户端先剥掉前缀" { update_op: "和后缀" }",再对剩余 bs58 字符串解码、RuntimeMetricUpdate::decodeSCALE 解码,最后按RuntimeMetricOp分发到对应更新方法。该模块文档特别提醒(见 node/metrics/src/runtime/mod.rs):不要在此文件中加日志,因为它在 logger 初始化之前执行、日志不会送达;需要调试时应使用println!。

5.4 平行链 Runtime 指标清单

parachain::register_metrics(node/metrics/src/runtime/parachain.rs)预注册了六类指标,它们的完整定义(名称、描述、标签、直方图桶)集中在 primitives/src/v5/metrics.rs 的metric_definitions模块中:

指标名(Prometheus)类型描述标签
polkadot_parachain_inherent_data_weightCounterVecinherent data 在过滤前/后的权重when:before-filter/after-filter
polkadot_parachain_inherent_data_bitfields_processedCounterprocess_inherent_data处理的 bitfield 数量—
polkadot_parachain_inherent_data_candidates_processedCounterVec处理的候选区块数量category:total/sanitized/included
polkadot_parachain_inherent_data_dispute_sets_processedCounterVec处理的争议声明集数量category:imported/current/concluded_invalid(以及frozen)
polkadot_parachain_create_inherent_bitfields_signature_checksCounterVecbitfield 签名检查次数validity:valid/invalid
polkadot_parachain_verify_dispute_signatureHistogram验证单个争议声明验证人签名耗时(秒)桶:0.0, 0.00005, 0.00006, 0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.3, 0.5, 1.0

Runtime 侧对应的指标结构体在 runtime/parachains/src/metrics.rs:它使用polkadot_runtime_metrics::{Counter, CounterVec, Histogram}(即 runtime/metrics 的实现),通过on_bitfields_processed、on_candidates_included、on_before_filter、on_after_filter等语义化方法包装底层更新,实际上报点位于 runtime/parachains/src/paras_inherent/mod.rs(METRICS.on_bitfields_processed(bitfields.len() as u64))。

六、端到端验证:runtime_can_publish_metrics 集成测试

node/metrics/src/tests.rs 中的runtime_can_publish_metrics测试完整验证了"Runtime 指标 → Prometheus 端点"这条链路,可作为手工验证的参考流程:

  1. 配置验证人节点并启用 Prometheus:用polkadot_test_service::node_config构建 Alice 配置,alice_config.prometheus_config = Some(test_prometheus_config(DEFAULT_PROMETHEUS_PORT)),默认端口9616(见 node/metrics/src/tests.rs);
  2. 开启 WASM tracing 并注入 logger_hook:builder.with_profiling(Default::default(), "wasm_tracing=trace")启用 Runtime 侧 tracing,随后调用crate::logger_hook()(&mut builder, &alice_config)注册RuntimeMetricsProvider(见 node/metrics/src/tests.rs);
  3. 启动双验证人节点:Alice 与 Bob 组成最小网络,alice.wait_for_finalized_blocks(2)等待两个区块 finalize,保证 Runtime 至少执行过一次process_inherent_data;
  4. 抓取并断言指标:用hyper向http://localhost:9616/metrics发起 GET,用prometheus_parse::Scrape解析响应,断言polkadot_parachain_inherent_data_bitfields_processed的值大于 1(见 node/metrics/src/tests.rs)。

该测试被限定在cfg(all(feature = "runtime-metrics", not(feature = "runtime-benchmarks"), test))条件下编译(见 node/metrics/src/lib.rs),也就是说只有同时满足"开启 runtime-metrics、不开启 runtime-benchmarks、处于测试模式"时才会编译,这再次说明了第三节中先构建 worker 二进制的必要性——没有 PVF worker,测试无法拉起真实节点。

手工复现这一验证的要点可归纳为:启动带--prometheus-port(默认 9615/9616)的 polkadot 节点 → 确认日志出现 runtime-metrics 相关输出 →curl localhost:<port>/metrics | grep polkadot_parachain观察指标。测试代码中的scrape_prometheus_metrics解析函数(node/metrics/src/tests.rs)展示了如何处理/metrics响应中的 Counter/Gauge/Untyped 采样值,可作为自建指标采集脚本的参考实现。

七、小结与实践建议

围绕 node/metrics/README.md 以及本 crate 源码,可以得出以下实践要点:

  1. 测试本 crate 前务必先构建 PVF worker:cargo build --bin polkadot-execute-worker --bin polkadot-prepare-worker,否则cargo test会因真实节点无法启动而失败;
  2. 周期性指标采集首选Metronome:它是一个永不终止的 tick 流,overseer 用它每 ~950ms 聚合内存统计与 channel 消息快照;自定义周期只需修改Duration;
  3. 子系统指标统一实现Metricstrait:无 Prometheus 配置时register(None)自动退化为Default,保证各子系统行为一致;
  4. Runtime 指标开箱即用:polkadotCLI 主流程已经接入polkadot_node_metrics::logger_hook(),只要节点启用了 Prometheus 端点,Runtime 内polkadot_runtime_metrics上报的平行链指标(inherent data 权重、bitfield 处理数、候选处理数、争议签名验证耗时等)就会自动出现在/metrics输出中;
  5. 调试注意:RuntimeMetricsProvider的代码运行在 logger 初始化之前,调试时用println!而不是log/gum。

如需深入了解指标在 Runtime 侧的定义与上报语义,可继续阅读 runtime/metrics、runtime/parachains/src/metrics.rs 与 primitives/src/v5/metrics.rs;如需查看Metronome在真实运行节点中的消费方式,参考 node/overseer/src/lib.rs。

  • 区块链

【免费下载链接】polkadot

Polkadot Node Implementation

项目地址:https://gitcode.com/gh_mirrors/po/polkadot
点击查看免费下载

相关推荐

上一篇:Alternative Frontends未来路线图:探索去中心化选项和新兴服务支持
下一篇:Grok模型解析:L1B3RT45特殊指令格式详解

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 2:26:46

Vane 接入外部 SearXNG 实例的 3 步完整集成指南

Vane 接入外部 SearXNG 实例的 3 步完整集成指南 【免费下载链接】Vane Vane is an AI-powered answering engine. 项目地址: https://gitcode.com/GitHub_Trending/pe/Vane 把 Vane 接到你自己的 SearXNG 实例上&#xff0c;SearXNG 集成就算完成了——这个 AI 问答引擎…

作者头像 李华
网站建设 2026/9/29 2:26:28

用OLED给STM32做实时调试面板:告别串口日志的嵌入式调试方案

从串口屏到OLED小屏&#xff0c;我为什么坚持用这种方式做调试嵌入式调试这事儿&#xff0c;说难不难&#xff0c;说简单也不简单。刚入行那会儿我也跟大多数人一样&#xff0c;全靠串口打印&#xff0c;printf一梭子打出去&#xff0c;数据倒是有了&#xff0c;但脑子里得一边…

作者头像 李华
网站建设 2026/9/29 2:26:14

Java足球俱乐部管理系统实战:Spring Boot+MySQL落地指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 2:25:37

ZeroLaunch-rs字体调整:搜索结果显示优化

ZeroLaunch-rs字体调整&#xff1a;搜索结果显示优化 &#x1f3af; 痛点分析&#xff1a;为什么需要字体优化&#xff1f; 还在为Windows应用启动器的搜索结果看不清而烦恼吗&#xff1f;ZeroLaunch-rs提供了强大的字体自定义功能&#xff0c;让搜索结果显示更加清晰、美观、个…

作者头像 李华
网站建设 2026/9/29 2:25:23

toyDB 架构指南:用 Rust 从零实现一个分布式 SQL 数据库

【免费下载链接】toydb Distributed SQL database in Rust, written as an educational project 项目地址&#xff1a; https://gitcode.com/gh_mirrors/to/toydb 点击查看 免费下载 toyDB 是一个以教学为目的、用 Rust 编写的分布式 SQL 数据库&#xff0c;其目标不是性能与规…

作者头像 李华
网站建设 2026/9/29 2:25:14

生成对抗网络GAN基础:原理与PyTorch实战实现

近几年生成模型发展很快&#xff0c;你可能常听到“AI 绘画”“人脸生成”“图像修复”这些词。背后有一个绕不开的基础模型——GAN&#xff0c;中文通常叫生成对抗网络&#xff08;Generative Adversarial Network&#xff09;。如果你刚进入深度学习的学习路线&#xff0c;看…

作者头像 李华