modules: systemd_failed_units: Introduce systemd state variables

Systemd provides the status of a given user and system session as a
human readable string.

Retrieve this information via RequestSystemState and guard the
retrieve of failed units depending on this request.

The functionality is extended but does not change, which means that
failed units in any granularity are displayed as before.

Update documentation in the meantime.

Signed-off-by: Steffen Kothe <steffen.kothe@skothe.net>
This commit is contained in:
Steffen Kothe
2025-06-21 15:09:05 +00:00
parent d5e3a9f894
commit cfb47790ad
3 changed files with 49 additions and 9 deletions

View File

@ -19,6 +19,7 @@ class SystemdFailedUnits : public ALabel {
std::string format_ok; std::string format_ok;
bool update_pending; bool update_pending;
std::string system_state, user_state, overall_state;
uint32_t nr_failed_system, nr_failed_user, nr_failed; uint32_t nr_failed_system, nr_failed_user, nr_failed;
std::string last_status; std::string last_status;
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy; Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
@ -26,6 +27,7 @@ class SystemdFailedUnits : public ALabel {
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name, void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
const Glib::VariantContainerBase &arguments); const Glib::VariantContainerBase &arguments);
void RequestFailedUnits(); void RequestFailedUnits();
void RequestSystemState();
void updateData(); void updateData();
}; };

View File

@ -62,6 +62,12 @@ Addressed by *systemd-failed-units*
*{nr_failed}*: Number of total failed units. *{nr_failed}*: Number of total failed units.
*{systemd_state}:* State of the systemd system session
*{user_state}:* State of the systemd user session
*{overall_state}:* Overall state of the systemd and user session. ("Ok" or "Degraded")
# EXAMPLES # EXAMPLES
``` ```

View File

@ -68,6 +68,34 @@ auto SystemdFailedUnits::notify_cb(const Glib::ustring& sender_name,
} }
} }
void SystemdFailedUnits::RequestSystemState() {
auto load = [](const char* kind, Glib::RefPtr<Gio::DBus::Proxy>& proxy) -> std::string {
try {
if (!proxy) return "unknown";
auto parameters = Glib::VariantContainerBase(
g_variant_new("(ss)", "org.freedesktop.systemd1.Manager", "SystemState"));
Glib::VariantContainerBase data = proxy->call_sync("Get", parameters);
if (data && data.is_of_type(Glib::VariantType("(v)"))) {
Glib::VariantBase variant;
g_variant_get(data.gobj_copy(), "(v)", &variant);
if (variant && variant.is_of_type(Glib::VARIANT_TYPE_STRING)) {
return g_variant_get_string(variant.gobj_copy(), NULL);
}
}
} catch (Glib::Error& e) {
spdlog::error("Failed to get {} state: {}", kind, e.what().c_str());
}
return "unknown";
};
system_state = load("systemwide", system_proxy);
user_state = load("user", user_proxy);
if (system_state == "running" && user_state == "running")
overall_state = "ok";
else
overall_state = "degraded";
}
void SystemdFailedUnits::RequestFailedUnits() { void SystemdFailedUnits::RequestFailedUnits() {
auto load = [](const char* kind, Glib::RefPtr<Gio::DBus::Proxy>& proxy) -> uint32_t { auto load = [](const char* kind, Glib::RefPtr<Gio::DBus::Proxy>& proxy) -> uint32_t {
try { try {
@ -95,17 +123,18 @@ void SystemdFailedUnits::RequestFailedUnits() {
void SystemdFailedUnits::updateData() { void SystemdFailedUnits::updateData() {
update_pending = false; update_pending = false;
RequestFailedUnits();
RequestSystemState();
if (overall_state == "degraded") RequestFailedUnits();
dp.emit(); dp.emit();
} }
auto SystemdFailedUnits::update() -> void { auto SystemdFailedUnits::update() -> void {
const std::string status = nr_failed == 0 ? "ok" : "degraded"; if (last_status == overall_state) return;
if (last_status == status) return;
// Hide if needed. // Hide if needed.
if (nr_failed == 0 && hide_on_ok) { if (overall_state == "ok" && hide_on_ok) {
event_box_.set_visible(false); event_box_.set_visible(false);
return; return;
} }
@ -116,14 +145,17 @@ auto SystemdFailedUnits::update() -> void {
if (!last_status.empty() && label_.get_style_context()->has_class(last_status)) { if (!last_status.empty() && label_.get_style_context()->has_class(last_status)) {
label_.get_style_context()->remove_class(last_status); label_.get_style_context()->remove_class(last_status);
} }
if (!label_.get_style_context()->has_class(status)) { if (!label_.get_style_context()->has_class(overall_state)) {
label_.get_style_context()->add_class(status); label_.get_style_context()->add_class(overall_state);
} }
last_status = status;
last_status = overall_state;
label_.set_markup(fmt::format( label_.set_markup(fmt::format(
fmt::runtime(nr_failed == 0 ? format_ok : format_), fmt::arg("nr_failed", nr_failed), fmt::runtime(nr_failed == 0 ? format_ok : format_), fmt::arg("nr_failed", nr_failed),
fmt::arg("nr_failed_system", nr_failed_system), fmt::arg("nr_failed_user", nr_failed_user))); fmt::arg("nr_failed_system", nr_failed_system), fmt::arg("nr_failed_user", nr_failed_user),
fmt::arg("system_state", system_state), fmt::arg("user_state", user_state),
fmt::arg("overall_state", overall_state)));
ALabel::update(); ALabel::update();
} }