From: Simon Lucido Date: Mon, 4 May 2026 09:40:41 +0000 (+0200) Subject: core/varlink-metrics: expose ReloadCount as a metric X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=71ebb276861e28b63c9a1b86bc8fee4ca7de5500;p=thirdparty%2Fsystemd.git core/varlink-metrics: expose ReloadCount as a metric Add ReloadCount to the io.systemd.Metrics family table so it can be queried alongside other manager-level metrics via systemd-report. Also extend the existing integration test to cross-check the value returned by systemd-report against the D-Bus and Varlink transports on every assertion. Co-developed-by: Claude Opus 4.7 Signed-off-by: Simon Lucido --- diff --git a/src/core/varlink-metrics.c b/src/core/varlink-metrics.c index 82bc3cf4cba..f1ac0791bc9 100644 --- a/src/core/varlink-metrics.c +++ b/src/core/varlink-metrics.c @@ -189,6 +189,18 @@ static int nrestarts_build_json(MetricFamilyContext *context, void *userdata) { return 0; } +static int reload_count_build_json(MetricFamilyContext *context, void *userdata) { + Manager *manager = ASSERT_PTR(userdata); + + assert(context); + + return metric_build_send_unsigned( + context, + /* object= */ NULL, + manager->reload_count, + /* fields= */ NULL); +} + static int units_by_type_total_build_json(MetricFamilyContext *context, void *userdata) { Manager *manager = ASSERT_PTR(userdata); int r; @@ -364,6 +376,12 @@ static const MetricFamily metric_family_table[] = { .type = METRIC_FAMILY_TYPE_COUNTER, .generate = nrestarts_build_json, }, + { + .name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "ReloadCount", + .description = "Number of successful manager reloads since startup; resets across daemon-reexec", + .type = METRIC_FAMILY_TYPE_COUNTER, + .generate = reload_count_build_json, + }, { .name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "StateChangeTimestamp", .description = "Per unit metric: timestamp of the last state change in microseconds; 0 indicates no state change has occurred", diff --git a/test/units/TEST-07-PID1.reload-count.sh b/test/units/TEST-07-PID1.reload-count.sh index 7c31b65c5fc..a41a4e467d2 100755 --- a/test/units/TEST-07-PID1.reload-count.sh +++ b/test/units/TEST-07-PID1.reload-count.sh @@ -5,7 +5,13 @@ set -o pipefail # Verify that the manager exposes a ReloadCount property that increments on # every daemon-reload, resets to zero across daemon-reexec (since the count -# is not serialized), and is reachable over both D-Bus and Varlink. +# is not serialized), and is reachable over D-Bus, Varlink Describe, and the +# io.systemd.Metrics interface (queried via systemd-report). + +# systemd-report silently returns empty if the metrics source is missing, +# which would falsely pass the cross-checks below. Assert the socket exists +# so any failure points at the real problem. +test -S /run/systemd/report/io.systemd.Manager read_count_dbus() { busctl -j get-property org.freedesktop.systemd1 \ @@ -19,10 +25,23 @@ read_count_varlink() { io.systemd.Manager.Describe '{}' | jq -r '.runtime.ReloadCount' } -# Sanity: both transports must agree. +read_count_report() { + local out + # Strip the RS separator that jq --seq re-emits on output. + out=$(/usr/lib/systemd/systemd-report metrics --json=short \ + io.systemd.Manager.ReloadCount \ + | jq --seq -r 'select(.name == "io.systemd.Manager.ReloadCount") | .value' \ + | tr -d '\036') + [[ -n "$out" ]] || { echo "ReloadCount metric missing from systemd-report output" >&2; return 1; } + echo "$out" +} + +# Sanity: all three transports must agree. dbus_count=$(read_count_dbus) varlink_count=$(read_count_varlink) +report_count=$(read_count_report) (( dbus_count == varlink_count )) +(( dbus_count == report_count )) # A single reload bumps the counter by one. before=$(read_count_dbus) @@ -34,18 +53,22 @@ systemctl daemon-reload systemctl daemon-reload (( $(read_count_dbus) == before + 3 )) -# And both transports still agree after the reload. +# And all three transports still agree after the reload. dbus_count=$(read_count_dbus) varlink_count=$(read_count_varlink) +report_count=$(read_count_report) (( dbus_count == varlink_count )) +(( dbus_count == report_count )) -# A daemon-reexec resets the counter back to zero on both transports, since -# reload_count lives only in memory and is not carried across the reexec. +# A daemon-reexec resets the counter back to zero on all three transports, +# since the counter lives only in memory and is not carried across the reexec. # `systemctl daemon-reexec` returns as soon as the old PID 1 closes its bus # connection, which is before the new PID 1 has rebound /run/systemd/private. # Use --watch-bind=yes to block on inotify until the new socket is live. systemctl daemon-reexec busctl --watch-bind=yes call org.freedesktop.systemd1 /org/freedesktop/systemd1 \ org.freedesktop.DBus.Peer Ping >/dev/null + (( $(read_count_dbus) == 0 )) (( $(read_count_varlink) == 0 )) +(( $(read_count_report) == 0 ))