diff --git a/libs/snitch/inc/public/tfc/snitch.hpp b/libs/snitch/inc/public/tfc/snitch.hpp index d1326d9a50..ca78069cea 100644 --- a/libs/snitch/inc/public/tfc/snitch.hpp +++ b/libs/snitch/inc/public/tfc/snitch.hpp @@ -1,21 +1,26 @@ #pragma once +#include #include #include +#include -#include #include +#include +#include -#include #include -#include -#include +#include #include -#include #include +#include +#include +#include namespace tfc::snitch { +namespace asio = boost::asio; + struct variance { bool resettable{}; level_e lvl{ level_e::unknown }; @@ -39,10 +44,9 @@ class alarm { /// \example alarm<{}, "short desc", "long desc"> warn(fmt::arg("key", "value"), fmt::arg("key2", 1)); /// \param unique_id A unique identifier for the alarm within this process /// \param default_args Default fmt::arg values to populate the alarm with, e.g. fmt::arg("index", 1) for tank 1 etc. - alarm(std::shared_ptr conn, std::string_view unique_id, named_arg auto&& ... default_args) : - conn_{ std::move(conn) }, - given_id_{ unique_id }, - default_values_{ std::make_pair(default_args.name, fmt::format("{}", default_args.value))... } { + alarm(std::shared_ptr conn, std::string_view unique_id, named_arg auto&&... default_args) + : conn_{ std::move(conn) }, given_id_{ unique_id }, + default_values_{ std::make_pair(default_args.name, fmt::format("{}", default_args.value))... } { static_assert(detail::check_all_arguments_named(description), "All arguments must be named"); static_assert(detail::check_all_arguments_no_format(description), "All arguments may not have format specifiers"); [[maybe_unused]] static constexpr int num_args = sizeof...(default_args); @@ -56,7 +60,7 @@ class alarm { ~alarm() = default; template - requires (var.resettable) + requires(var.resettable) void on_try_reset(callback_t&& callback) { dbus_client_.on_try_reset_alarm([this, callback](api::alarm_id_t id) { if (active_ && id == alarm_id_) { @@ -70,7 +74,7 @@ class alarm { }); } - void set(named_arg auto&& ... args) { + void set(named_arg auto&&... args) { fmt::dynamic_format_arg_store store; for (auto const& [key, value] : default_values_) { store.push_back(fmt::arg(key.c_str(), value)); @@ -79,31 +83,79 @@ class alarm { logger_.debug(fmt::vformat(description, store)); logger_.debug(fmt::vformat(details, store)); - std::unordered_map params; - // for (auto const& arg : store) { - // params[key] = fmt::format("{}", value); - // } + auto params{ default_values_ }; + params.emplace(std::make_pair(args.name, fmt::format("{}", args.value))...); + + if (active_) { + logger_.info("alarm already active, not doing anything"); + } + + active_ = true; + + if (alarm_id_) { + dbus_client_.set_alarm(alarm_id_.value(), params, [this](std::error_code const& ec) { + if (ec) { + logger_.error("Failed to set alarm: {}", ec.message()); + // I am both inclined to reset active flag here aswell as not ... I think I will not + // active_ = false; + } + }); + } else { + retry_timer_.expires_after(std::chrono::seconds(1)); + retry_timer_.async_wait([this, args...](std::error_code const& ec) { + if (ec) { + logger_.error("Retry set timer failed: {}", ec.message()); + return; + } + logger_.debug("Retrying set alarm"); + set(args...); + }); + } } -private: - void register_alarm() { - dbus_client_.register_alarm(tfc_id_, description, details, var.resettable, var.lvl, [this](std::error_code const& ec, api::alarm_id_t id) { + + void reset() { + if (!active_) { + logger_.info("alarm already inactive, not doing anything"); + return; + } + active_ = false; + if (!alarm_id_) { + logger_.info("NO alarm ID, forget that alarm ever happened, the timings would be off so would not be valuable information"); + return; + } + dbus_client_.reset_alarm(alarm_id_.value(), [this](std::error_code const& ec) { if (ec) { - logger_.error("Failed to register alarm: {}", ec.message()); - return; + logger_.error("Failed to reset alarm: {}", ec.message()); + // I am both inclined to set active flag here aswell as not ... I think I will not + // active_ = true; } - alarm_id_ = id; }); } + +private: + void register_alarm() { + dbus_client_.register_alarm(tfc_id_, description, details, var.resettable, var.lvl, + [this](std::error_code const& ec, api::alarm_id_t id) { + if (ec) { + logger_.error("Failed to register alarm: {}", ec.message()); + return; + } + alarm_id_ = id; + }); + } bool active_{}; std::shared_ptr conn_; std::string given_id_; std::string tfc_id_{ fmt::format("{}.{}.{}", base::get_exe_name(), base::get_proc_name(), given_id_) }; std::unordered_map default_values_; std::optional alarm_id_{}; + asio::steady_timer retry_timer_{ conn_->get_io_context() }; detail::dbus_client dbus_client_{ conn_ }; logger::logger logger_{ fmt::format("snitch.{}", given_id_) }; }; + + template using info = alarm; template @@ -115,5 +167,4 @@ using warning_resettable = warning_latched; template using error = alarm; - -} // namespace tfc::snitch +} // namespace tfc::snitch diff --git a/libs/snitch/inc/public/tfc/snitch/format_extension.hpp b/libs/snitch/inc/public/tfc/snitch/format_extension.hpp index 8bccc7f297..b8dcd9dbaa 100644 --- a/libs/snitch/inc/public/tfc/snitch/format_extension.hpp +++ b/libs/snitch/inc/public/tfc/snitch/format_extension.hpp @@ -2,6 +2,7 @@ #include #include +#include #include