12#ifndef RTCTK_COMPONENTFRAMEWORK_RTCCOMPONENTMAIN_HPP
13#define RTCTK_COMPONENTFRAMEWORK_RTCCOMPONENTMAIN_HPP
34#include <fmt/format.h>
36#include <boost/core/demangle.hpp>
38#include <boost/stacktrace.hpp>
72template <
class BL,
class BLF>
78 LOG4CPLUS_INFO(logger,
"RtcComponent '" << component_name <<
"' started.");
79 using boost::core::demangle;
80 LOG4CPLUS_DEBUG(logger,
"BusinessLogic '" << demangle(
typeid(BL).name()) <<
"'");
88 std::make_unique<ServiceDiscovery>(svc_disc_endpoint, component_name));
97 auto oldb_endpoint = svc_disc.GetOldbEndpoint();
99 services.Add<
OldbIf>(oldb_adapter);
102 auto telegraf_endpoint = svc_disc.GetTelegrafEndpoint();
103 auto telegraf_adapter =
104 std::make_shared<TelegrafAdapter>(telegraf_endpoint, component_name);
108 auto component_metrics = std::make_shared<ComponentMetrics>(
112 DataPointPath(fmt::format(
"/{}/dynamic/metrics", component_name)),
114 telegraf_adapter.get());
118 auto event_service = std::make_shared<MalDdsEventService>();
122 auto alert_service = std::make_shared<AlertService>();
123 alert_service->AddObserver(std::make_unique<AlertLogger>());
124 alert_service->AddObserver(
125 std::make_unique<AlertOldbPublisher>(component_name, *oldb_adapter));
126 alert_service->AddObserver(
127 std::make_unique<AlertEventPublisher>(component_name, *event_service));
128 alert_service->AddObserver(
129 std::make_unique<AlertTelegrafPublisher>(component_name, *telegraf_adapter));
147 LOG4CPLUS_DEBUG(logger,
"Entering State: " << state);
153 if (not oldb.DataPointExists(dp_name)) {
154 oldb.CreateDataPoint<std::string>(dp_name);
156 oldb.SetDataPoint(dp_name, state);
164 LOG4CPLUS_ERROR(logger,
170 static_assert(std::is_base_of_v<typename BL::ComponentType::BizLogicIf, BL>,
171 "BusinessLogic must implement BusinessLogicInterface");
174 std::is_invocable_v<BLF, const std::string&, ServiceContainer&>,
175 "Factory must be invocable with 'const std::string&' and 'ServiceContainer&'");
178 std::is_same_v<std::invoke_result_t<BLF, const std::string&, ServiceContainer&>,
179 std::unique_ptr<BL>>,
180 "Factory must return type 'std::unique_ptr<BusinessLogic>'");
183 std::unique_ptr<BL> biz_logic;
185 biz_logic = invoke(factory, component_name, services);
188 "BusinessLogic factory did not return a valid object");
190 }
catch (
const std::exception& ex) {
191 CII_THROW_WITH_NESTED(
RtctkException, ex,
"BusinessLogic factory failed");
194 typename BL::ComponentType::InputStage input_stage(replier, engine);
196 typename BL::ComponentType::OutputStage output_stage(engine, *biz_logic);
198 typename BL::ComponentType::ModelBuilder model_builder(engine);
201 model_builder.ExportModel(emf->path().to_string());
204 model_builder.RegisterModel();
206 component_metrics->StartMonitoring();
210 LOG4CPLUS_INFO(logger,
"RtcComponent '" << component_name <<
"' terminated.");
212 }
catch (
const std::exception& ex) {
213 CII_THROW_WITH_NESTED(
RtctkException, ex,
"RunAsRtcComponent() failed");
231 std::is_constructible_v<BL, const std::string&, ServiceContainer&>,
232 "BusinessLogic must be constructible with 'const std::string&' and 'ServiceContainer&'");
248int Main(
int argc,
char* argv[]) {
250 Args args{argc, argv};
254 }
catch (
const CLI::ParseError& e) {
255 return args.PrintHelpOrErrMsg(e);
256 }
catch (
const std::exception& e) {
257 fmt::print(stderr,
"RtcComponentMain failed during argument parsing: {}\n", e.what());
265 auto name = args.GetComponentName();
266 auto log_props_file = args.GetLogPropsFile();
268 if (log_props_file.has_value()) {
271 auto debug_mode = args.GetDebugMode();
272 auto level = debug_mode ? log4cplus::DEBUG_LOG_LEVEL : log4cplus::INFO_LOG_LEVEL;
275 }
catch (
const std::exception& e) {
276 fmt::print(stderr,
"Failed to initialise log system: {}\n", e.what());
286 }
catch (
const std::exception& e) {
299int main(
int argc,
char* argv[]) {
300 std::set_terminate([]() {
303 std::exception_ptr eptr{std::current_exception()};
306 "Unhandled Exception caught: "
308 << boost::to_string(boost::stacktrace::stacktrace()));
311 "Exiting without exception.\nBacktrace:\n"
312 << boost::to_string(boost::stacktrace::stacktrace()));
322 constexpr std::string_view msg =
323 "Caught exception leaked from rtctk::componentFramework::Main\n";
324 std::cerr.write(msg.data(), msg.size());
Alert Service interface.
Definition alertServiceIf.hpp:138
Class used to parse default command line arguments.
Definition rtcComponentArgs.hpp:32
std::optional< elt::mal::Uri > GetModelExportFile() const
Get name of optionally provided state machine model export file.
Definition rtcComponentArgs.cpp:39
const std::string & GetComponentName() const
Get component name or identifier.
Definition rtcComponentArgs.cpp:19
elt::mal::Uri GetServiceDiscEndpoint() const
Get service discovery endpoint.
Definition rtcComponentArgs.cpp:23
Class that handles reception of commands using MAL.
Definition commandReplier.hpp:29
Component metrics interface.
Definition componentMetricsIf.hpp:163
This class provides a wrapper for a data point path.
Definition dataPointPath.hpp:76
Interface class for providing pub/sub facilities for JSON events.
Definition eventServiceIf.hpp:28
RAII class to clean-up logging without leaking memory.
Definition logger.hpp:27
Adapter object intended to be used in contexts without direct access to the output-stream object.
Definition exceptions.hpp:168
Base interface for all OLDB adapters.
Definition oldbIf.hpp:24
static std::unique_ptr< OldbIf > CreateAdapter(const elt::mal::Uri &uri)
Factory method used to create the appropriate OLDB adapter depending on the URI scheme.
Definition oldbIf.cpp:17
The RtctkException class is the base class for all Rtctk exceptions.
Definition exceptions.hpp:220
Base interface for all Runtime Configuration Repository adapters.
Definition runtimeRepoIf.hpp:26
static std::unique_ptr< RuntimeRepoIf > CreateAdapter(const elt::mal::Uri &uri)
Factory method used to create the appropriate Runtime Configuration Repository adapter depending on t...
Definition runtimeRepoIf.cpp:18
Container class that holds services of any type.
Definition serviceContainer.hpp:38
Class that implements a very basic service discovery mechanism.
Definition serviceDiscovery.hpp:32
ServiceEndpoint GetRuntimeRepoEndpoint()
Get the Runtime Repository Endpoint from the ServiceDiscovery.
Definition serviceDiscovery.cpp:58
static const std::string COMPONENT_TYPE
the string for component type (default)
Definition serviceRegistryIf.hpp:59
Definition stateMachineEngine.hpp:34
void RegisterStateChangeHandler(StateMethod on_statechange)
Register state changed handler.
Definition stateMachineEngine.cpp:141
void Work()
Runs the event loop of the state machine.
Definition stateMachineEngine.cpp:154
Class used to publish state-changed-topic using MAL.
Definition statePublisher.hpp:35
void PublishState(const std::string &state)
Definition statePublisher.cpp:40
Implementation of the Telegraf Adapter.
Definition telegrafAdapter.hpp:93
std::map< std::string, std::string > BaseTags()
Constructs and returns a map of base tags for InfluxDB.
Definition telegrafAdapter.cpp:77
void SendPoints(const std::vector< InfluxPoint > &points)
Sends vector of points to Telegraf using UDP and Influx line protocol.
Definition telegrafAdapter.cpp:81
Receive commands via MAL.
Declares ComponentMetrics.
log4cplus::Logger & GetLogger(const std::string &name="app")
Get handle to a specific logger.
Definition logger.cpp:191
Provides macros and utilities for exception handling.
void RtcComponentMain(const rtctk::componentFramework::Args &args)
Main entry point for user code, this method must be implemented by component developers.
Definition main.cpp:42
void RunAsRtcComponent(const Args &args, BLF factory)
RTC Component runner function, needed to run custom BusinessLogic as RTC Component.
Definition rtcComponentMain.hpp:73
auto WrapWithNested(E &&exception) noexcept(std::is_nothrow_constructible_v< detail::UnspecifiedNested< typename std::decay_t< E > >, E && >)
Constructs an unspecified exception that derives from both the provided object and std::nested_except...
Definition exceptions.hpp:96
log4cplus::Logger & GetLogger(const std::string &name="app")
Get handle to a specific logger.
Definition logger.cpp:191
void LogConfigure(const std::string &app_name, const std::string &props_file_name)
Performs custom logging configuration for any application.
Definition logger.cpp:69
Logging Support Library based on log4cplus.
Implementation of the event service.
Definition commandReplier.cpp:21
std::vector< InfluxPoint > ParseStateToInfluxPoints(const std::string &component_name, const std::string &states_str, const std::map< std::string, std::string > &base_tags)
Definition telegrafAdapter.cpp:212
int Main(int argc, char *argv[])
Main function implementation.
Definition rtcComponentMain.hpp:248
Header file for OldbIf, which defines the API for OldbAdapters.
Provides argument parsing functionality of an RTC Component.
int main(int argc, char *argv[])
Main function, this is private to the RTC Tk and shall NOT be used by component developers.
Definition rtcComponentMain.hpp:299
Header file for RuntimeRepoIf, which defines the API for RuntimeRepoAdapters.
A container that can hold any type of service.
Class that implements a very basic service discover mechanism.
Class that implements the service registry interface.
Wrapper around the SCXML State Machine Engine.
Publishes the stdif state topic via MAL.
Header file needed to instantiate an TelegrafAdapter.