From 5593cbd759d3b6832694e1bed0bf64d9ddcb61b5 Mon Sep 17 00:00:00 2001 From: Yusuke Matsumoto <2matzzz@gmail.com> Date: Thu, 20 Aug 2026 18:56:32 +0900 Subject: [PATCH] qdisc: expose fq throttled events as node_qdisc_throttled_total The ema/qdisc library has parsed the fq qdisc's extended statistics (including the throttled counter) since 2017, one day after this collector was merged, but the field was never wired into a metric. Expose it as node_qdisc_throttled_total so that users running fq with maxrate pacing can observe how often the qdisc throttles transmission, e.g. to verify whether egress pacing is actually engaging. For qdiscs other than fq the value is reported as 0, consistent with how the other uniform per-qdisc metrics behave. Assisted-by: Claude Code Signed-off-by: Yusuke Matsumoto <2matzzz@gmail.com> --- collector/fixtures/e2e-64k-page-output.txt | 4 ++++ collector/fixtures/e2e-output.txt | 4 ++++ collector/fixtures/qdisc/results.json | 3 ++- collector/qdisc_linux.go | 7 +++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/collector/fixtures/e2e-64k-page-output.txt b/collector/fixtures/e2e-64k-page-output.txt index 7b8e4be5e4..cf467f5fa6 100644 --- a/collector/fixtures/e2e-64k-page-output.txt +++ b/collector/fixtures/e2e-64k-page-output.txt @@ -3702,6 +3702,10 @@ node_qdisc_packets_total{device="wlan0",kind="fq"} 42 # TYPE node_qdisc_requeues_total counter node_qdisc_requeues_total{device="eth0",kind="pfifo_fast"} 2 node_qdisc_requeues_total{device="wlan0",kind="fq"} 1 +# HELP node_qdisc_throttled_total Number of times the qdisc has been throttled to enforce pacing (fq). +# TYPE node_qdisc_throttled_total counter +node_qdisc_throttled_total{device="eth0",kind="pfifo_fast"} 0 +node_qdisc_throttled_total{device="wlan0",kind="fq"} 3 # HELP node_rapl_core_joules_total Current RAPL core value in joules # TYPE node_rapl_core_joules_total counter node_rapl_core_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0:0"} 118821.284256 diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index d03fb08f44..b380e632fb 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -3734,6 +3734,10 @@ node_qdisc_packets_total{device="wlan0",kind="fq"} 42 # TYPE node_qdisc_requeues_total counter node_qdisc_requeues_total{device="eth0",kind="pfifo_fast"} 2 node_qdisc_requeues_total{device="wlan0",kind="fq"} 1 +# HELP node_qdisc_throttled_total Number of times the qdisc has been throttled to enforce pacing (fq). +# TYPE node_qdisc_throttled_total counter +node_qdisc_throttled_total{device="eth0",kind="pfifo_fast"} 0 +node_qdisc_throttled_total{device="wlan0",kind="fq"} 3 # HELP node_rapl_core_joules_total Current RAPL core value in joules # TYPE node_rapl_core_joules_total counter node_rapl_core_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0:0"} 118821.284256 diff --git a/collector/fixtures/qdisc/results.json b/collector/fixtures/qdisc/results.json index fe282bdd3d..c928af4258 100644 --- a/collector/fixtures/qdisc/results.json +++ b/collector/fixtures/qdisc/results.json @@ -5,7 +5,8 @@ "Packets": 42, "Requeues": 1, "Kind": "fq", - "Drops": 1 + "Drops": 1, + "Throttled": 3 }, { "IfaceName": "eth0", diff --git a/collector/qdisc_linux.go b/collector/qdisc_linux.go index 9062da122c..0f55fb6018 100644 --- a/collector/qdisc_linux.go +++ b/collector/qdisc_linux.go @@ -35,6 +35,7 @@ type qdiscStatCollector struct { drops typedDesc requeues typedDesc overlimits typedDesc + throttled typedDesc qlength typedDesc backlog typedDesc } @@ -101,6 +102,11 @@ func NewQdiscStatCollector(logger *slog.Logger) (Collector, error) { "Number of overlimit packets.", []string{"device", "kind"}, nil, ), prometheus.CounterValue}, + throttled: typedDesc{prometheus.NewDesc( + prometheus.BuildFQName(namespace, "qdisc", "throttled_total"), + "Number of times the qdisc has been throttled to enforce pacing (fq).", + []string{"device", "kind"}, nil, + ), prometheus.CounterValue}, qlength: typedDesc{prometheus.NewDesc( prometheus.BuildFQName(namespace, "qdisc", "current_queue_length"), "Number of packets currently in queue to be sent.", @@ -159,6 +165,7 @@ func (c *qdiscStatCollector) Update(ch chan<- prometheus.Metric) error { ch <- c.drops.mustNewConstMetric(float64(msg.Drops), msg.IfaceName, msg.Kind) ch <- c.requeues.mustNewConstMetric(float64(msg.Requeues), msg.IfaceName, msg.Kind) ch <- c.overlimits.mustNewConstMetric(float64(msg.Overlimits), msg.IfaceName, msg.Kind) + ch <- c.throttled.mustNewConstMetric(float64(msg.Throttled), msg.IfaceName, msg.Kind) ch <- c.qlength.mustNewConstMetric(float64(msg.Qlen), msg.IfaceName, msg.Kind) ch <- c.backlog.mustNewConstMetric(float64(msg.Backlog), msg.IfaceName, msg.Kind) }