38{
40 const ConfigParser config(input.cmdOptionExists(
"--config") ? input.getCmdOption(
"--config") :
"config.json");
41
42
43 if (!config.isValid())
44 {
45 std::invalid_argument(std::format("{} {}", "Failed to load configuration:", config.getLastError()));
46 }
47
48 const MainLogger logger(config.get(
"LOKI_ADDRESS"), config.get(
"SENTRY_ADDRESS"));
49
50
51 if (curl_global_init(CURL_GLOBAL_DEFAULT) < 0)
52 {
53 spdlog::critical("Can't init curl");
54 return EXIT_FAILURE;
55 }
56
57
58
59
60
61
62
63
64
65
66 if (input.cmdOptionExists("-v"))
67 {
68 spdlog::set_level(spdlog::level::info);
69 }
70 if (input.cmdOptionExists("-vv"))
71 {
72 spdlog::set_level(spdlog::level::debug);
73 }
74 if (input.cmdOptionExists("-vvv"))
75 {
76 spdlog::set_level(spdlog::level::trace);
77 }
78
79
80
81
82
83
84
85
86
87
88 spdlog::debug("======== Detected input arguments ========");
89 for (const auto &entry : input.getCmdOptions())
90 {
91 spdlog::debug("{} = {}", entry.first, entry.second);
92 }
93
94
95 spdlog::debug("======== Detected configuration ========");
96 for (const auto &entry : config.getConfigMap())
97 {
98 spdlog::debug("{} = {}", entry.first, entry.second);
99 }
100
101
102 if (std::signal(SIGINT, interruptFunc) == SIG_ERR)
103 {
104 spdlog::critical(
"Can't set signal handler (SIGINT): {}",
getErrnoString(errno));
105 return EXIT_FAILURE;
106 }
107
108
109 if (std::signal(SIGTERM, interruptFunc) == SIG_ERR)
110 {
111 spdlog::critical(
"Can't set signal handler (SIGTERM): {}",
getErrnoString(errno));
112 return EXIT_FAILURE;
113 }
114
115
116 if (std::signal(SIGALRM, alarmFunc) == SIG_ERR)
117 {
118 spdlog::critical(
"Can't set signal handler (SIGALRM): {}",
getErrnoString(errno));
119 return EXIT_FAILURE;
120 }
122
123
124 std::unique_ptr<Tracer> crashpadController(nullptr);
125 vCheckFlag.emplace_back(
"Crashpad Handler", std::make_shared<std::atomic_flag>(
false));
126 crashpadController = std::make_unique<Tracer>(
127 vCheckFlag[
vCheckFlag.size() - 1].second, config.get(
"CRASHPAD_REMOTE"), config.get(
"CRASHPAD_PROXY"),
128 config.get("CRASHPAD_EXECUTABLE_PATH"), config.get("CRASHPAD_REPORT_DIR"));
129
130
131 std::unique_ptr<PrometheusServer> mainPrometheusServer(nullptr);
132 const std::string prometheusAddr = input.getCmdOption("--enable-prometheus");
133 if (!prometheusAddr.empty())
134 {
135 try
136 {
137 mainPrometheusServer = std::make_unique<PrometheusServer>(prometheusAddr);
138 spdlog::info("Prometheus server start at {}", prometheusAddr);
139 }
140 catch (const std::exception &e)
141 {
142 spdlog::error("Can't start Prometheus Server: {}", e.what());
143 return EXIT_FAILURE;
144 }
145 }
146
147
148 std::unique_ptr<ProcessMetrics> selfMonitor(nullptr);
149 vCheckFlag.emplace_back(
"Self Monitor", std::make_shared<std::atomic_flag>(
false));
150 if (mainPrometheusServer)
151 {
153 mainPrometheusServer->createNewRegistry());
154 }
155
156
157 std::unique_ptr<ZeroMQServer> zmqController(nullptr);
158 vCheckFlag.emplace_back(
"ZeroMQ Server", std::make_shared<std::atomic_flag>(
false));
159 const std::string zeromqServerAddr = input.getCmdOption("--enable-zeromq");
160 if (!zeromqServerAddr.empty())
161 {
162 try
163 {
164 zmqController = std::make_unique<ZeroMQServer>(
166 mainPrometheusServer ? mainPrometheusServer->createNewRegistry() : nullptr);
168 zmqController->initialise();
169 }
170 catch (const std::exception &e)
171 {
172 spdlog::error("Can't start ZeroMQ Server: {}", e.what());
173 return EXIT_FAILURE;
174 }
175 }
176
177
178 std::shared_ptr<TelnetServer> telnetController(nullptr);
179 vCheckFlag.emplace_back(
"Telnet Server", std::make_shared<std::atomic_flag>(
false));
180 const unsigned long telnetPort =
181 input.cmdOptionExists("--enable-telnet") ? std::stoul(input.getCmdOption("--enable-telnet")) : 0;
182 if (telnetPort > 0 && telnetPort < 65536)
183 {
184 try
185 {
186 telnetController = std::make_shared<TelnetServer>();
191 mainPrometheusServer ? mainPrometheusServer->createNewRegistry() : nullptr);
192 }
193 catch (const std::exception &e)
194 {
195 spdlog::error("Can't start Telnet Server: {}", e.what());
196 return EXIT_FAILURE;
197 }
198 }
199 else if (telnetPort != 0)
200 {
201 spdlog::error("Invalid Telnet port: {}", telnetPort);
202 return EXIT_FAILURE;
203 }
204
205
206
207
208
209
210
211
212
213 while (interruptFlag == 0)
214 {
215 std::this_thread::sleep_for(std::chrono::milliseconds(500));
216 }
217
218
219
220
221
222
223
224
225
226 curl_global_cleanup();
227
228 return EXIT_SUCCESS;
229}
std::vector< std::pair< std::string, std::shared_ptr< std::atomic_flag > > > vCheckFlag
Global variable to check if the servers are running.
std::string getErrnoString(int errVal)
void TelnetConnectedCallback(const SP_TelnetSession &session)
std::string TelnetTabCallback(const SP_TelnetSession &session, std::string_view line)
bool TelnetMessageCallback(const SP_TelnetSession &session, const std::string &line)
bool ZeroMQServerMessageCallback(const std::vector< zmq::message_t > &recvMsgs, std::vector< zmq::message_t > &replyMsgs)
constexpr uintmax_t alarmInterval