summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJuan Miguel Olmo Martínez <jolmomar@redhat.com>2024-10-25 14:57:44 +0200
committerJuan Miguel Olmo Martínez <jolmomar@redhat.com>2024-11-15 14:35:56 +0100
commit6e0324f26b25eba333feb4684c05b26391f2a24a (patch)
tree6bdadaeb9a76b9fe71d5e11afe2d4de1640fd3f4 /src
parentMerge pull request #60433 from indirasawant/doc_fix_1 (diff)
downloadceph-6e0324f26b25eba333feb4684c05b26391f2a24a.tar.xz
ceph-6e0324f26b25eba333feb4684c05b26391f2a24a.zip
exporter: SIGTERM/SIGINT/SIGHUP management
Ceph exporter manages SIGINT, SIGTERM and SIGHUP signals Fixes: https://tracker.ceph.com/issues/68721 Signed-off-by: Juan Miguel Olmo Martínez <jolmomar@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/exporter/DaemonMetricCollector.cc31
-rw-r--r--src/exporter/DaemonMetricCollector.h11
-rw-r--r--src/exporter/ceph_exporter.cc46
-rw-r--r--src/exporter/web_server.cc35
-rw-r--r--src/exporter/web_server.h1
5 files changed, 97 insertions, 27 deletions
diff --git a/src/exporter/DaemonMetricCollector.cc b/src/exporter/DaemonMetricCollector.cc
index 4b8a8131bcf..d27b3ac43c5 100644
--- a/src/exporter/DaemonMetricCollector.cc
+++ b/src/exporter/DaemonMetricCollector.cc
@@ -29,9 +29,16 @@ using json_object = boost::json::object;
using json_value = boost::json::value;
using json_array = boost::json::array;
-void DaemonMetricCollector::request_loop(boost::asio::steady_timer &timer) {
- timer.async_wait([&](const boost::system::error_code &e) {
- std::cerr << e << std::endl;
+void DaemonMetricCollector::request_loop() {
+ timer.async_wait([this](const boost::system::error_code &e) {
+ if (shutdown_flag) {
+ dout(1) << "Metric collector request loop cancelled" << dendl;
+ return;
+ }
+
+ if (e) return; // Exit on error or cancellation
+
+ dout(10) << "Getting metrics loop..." << dendl;
update_sockets();
bool sort_metrics = g_conf().get_val<bool>("exporter_sort_metrics");
@@ -42,19 +49,24 @@ void DaemonMetricCollector::request_loop(boost::asio::steady_timer &timer) {
auto stats_period = g_conf().get_val<int64_t>("exporter_stats_period");
// time to wait before sending requests again
timer.expires_from_now(std::chrono::seconds(stats_period));
- request_loop(timer);
+ request_loop();
});
}
void DaemonMetricCollector::main() {
- // time to wait before sending requests again
-
- boost::asio::io_context io;
- boost::asio::steady_timer timer{io, std::chrono::seconds(0)};
- request_loop(timer);
+ shutdown_flag = false;
+ timer.expires_from_now(std::chrono::seconds(0));
+ request_loop();
io.run();
}
+void DaemonMetricCollector::shutdown(){
+ shutdown_flag = true;
+ timer.cancel(); // Explicitly cancel the timer
+ dout(1) << "Collector shutdown initiated, timer canceled" << dendl;
+ io.stop();
+}
+
std::string DaemonMetricCollector::get_metrics() {
const std::lock_guard<std::mutex> lock(metrics_mutex);
return metrics;
@@ -499,3 +511,4 @@ DaemonMetricCollector &collector_instance() {
static DaemonMetricCollector instance;
return instance;
}
+
diff --git a/src/exporter/DaemonMetricCollector.h b/src/exporter/DaemonMetricCollector.h
index 3302e95df91..5831a0fa3b0 100644
--- a/src/exporter/DaemonMetricCollector.h
+++ b/src/exporter/DaemonMetricCollector.h
@@ -1,17 +1,20 @@
#pragma once
#include "common/admin_socket_client.h"
+#include <atomic>
#include <map>
#include <string>
#include <vector>
#include <boost/asio/steady_timer.hpp>
+#include <boost/thread.hpp>
#include <boost/json/object.hpp>
#include <filesystem>
#include <map>
#include <string>
#include <vector>
+
struct pstat {
unsigned long utime;
unsigned long stime;
@@ -43,11 +46,16 @@ public:
std::string metrics;
std::pair<labels_t, std::string> add_fixed_name_metrics(std::string metric_name);
void update_sockets();
+ void shutdown();
private:
std::mutex metrics_mutex;
std::unique_ptr<MetricsBuilder> builder;
- void request_loop(boost::asio::steady_timer &timer);
+ boost::asio::io_context io;
+ boost::asio::steady_timer timer{io};
+ std::atomic<bool> shutdown_flag{false};
+
+ void request_loop();
void dump_asok_metric(boost::json::object perf_info,
boost::json::value perf_values, std::string name,
@@ -108,3 +116,4 @@ public:
};
DaemonMetricCollector &collector_instance();
+
diff --git a/src/exporter/ceph_exporter.cc b/src/exporter/ceph_exporter.cc
index 2e2c16bb085..44b67c7e615 100644
--- a/src/exporter/ceph_exporter.cc
+++ b/src/exporter/ceph_exporter.cc
@@ -1,16 +1,31 @@
#include "common/ceph_argparse.h"
#include "common/config.h"
-#include "exporter/DaemonMetricCollector.h"
-#include "exporter/web_server.h"
+#include "common/debug.h"
#include "global/global_init.h"
#include "global/global_context.h"
-
+#include "global/signal_handler.h"
+#include "exporter/DaemonMetricCollector.h"
+#include "exporter/web_server.h"
#include <boost/thread/thread.hpp>
#include <iostream>
#include <map>
#include <string>
+#include <atomic>
+#include <chrono>
+#include <thread>
#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_ceph_exporter
+
+DaemonMetricCollector &collector = collector_instance();
+
+static void handle_signal(int signum)
+{
+ ceph_assert(signum == SIGINT || signum == SIGTERM);
+ derr << "*** Got signal " << sig_str(signum) << " ***" << dendl;
+ // Finish the DaemonMetricCollector
+ collector.shutdown();
+}
static void usage() {
std::cout << "usage: ceph-exporter [options]\n"
@@ -27,7 +42,6 @@ static void usage() {
}
int main(int argc, char **argv) {
-
auto args = argv_to_vec(argc, argv);
if (args.empty()) {
std::cerr << argv[0] << ": -h or --help for usage" << std::endl;
@@ -64,8 +78,30 @@ int main(int argc, char **argv) {
}
common_init_finish(g_ceph_context);
+ // Register signal handlers
+ init_async_signal_handler();
+ register_async_signal_handler(SIGHUP, sighup_handler);
+ register_async_signal_handler_oneshot(SIGINT, handle_signal);
+ register_async_signal_handler_oneshot(SIGTERM, handle_signal);
+
+ // Start the web server thread
boost::thread server_thread(web_server_thread_entrypoint);
- DaemonMetricCollector &collector = collector_instance();
+
+ // Start the DaemonMetricCollector
collector.main();
+
+ // Interrupted. Time to terminate
+ unregister_async_signal_handler(SIGHUP, sighup_handler);
+ unregister_async_signal_handler(SIGINT, handle_signal);
+ unregister_async_signal_handler(SIGTERM, handle_signal);
+ shutdown_async_signal_handler();
+
+ // Stop the web server thread by interrupting it
+ stop_web_server();
+ server_thread.interrupt(); // Interrupt the web server thread
server_thread.join();
+
+ dout(1) << "Ceph exporter stopped" << dendl;
+
+ return 0;
}
diff --git a/src/exporter/web_server.cc b/src/exporter/web_server.cc
index 96cc02b389f..c01205f26bb 100644
--- a/src/exporter/web_server.cc
+++ b/src/exporter/web_server.cc
@@ -28,6 +28,9 @@ namespace net = boost::asio; // from <boost/asio.hpp>
namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+//common io context for the web servers
+std::shared_ptr<net::io_context> global_ioc;
+
// Base class for common functionality
class web_connection {
public:
@@ -43,7 +46,7 @@ protected:
web_connection(net::any_io_executor executor, std::chrono::seconds timeout)
: deadline_(executor, timeout) {}
- // Common request processing logic
+ // Common request processing logic
void process_request() {
response_.version(request_.version());
response_.keep_alive(request_.keep_alive());
@@ -64,7 +67,7 @@ protected:
write_response();
}
- // Construct a response message based on the request target
+ // Construct a response message based on the request target
void create_response() {
if (request_.target() == "/") {
response_.result(http::status::moved_permanently);
@@ -81,7 +84,7 @@ protected:
}
}
- // Asynchronously transmit the response message
+ // Asynchronously transmit the response message
virtual void write_response() = 0;
// Check whether we have spent enough time on this connection
@@ -228,28 +231,33 @@ void https_server(tcp::acceptor &acceptor, ssl::context &ssl_ctx) {
}
void run_http_server(const std::string& exporter_addr, short unsigned int port) {
- net::io_context ioc{1};
- tcp::acceptor acceptor{ioc, {net::ip::make_address(exporter_addr), port}};
- tcp::socket socket{ioc};
+ tcp::acceptor acceptor{*global_ioc, {net::ip::make_address(exporter_addr), port}};
+ tcp::socket socket{*global_ioc};
http_server(acceptor, socket);
dout(1) << "HTTP server running on " << exporter_addr << ":" << port << dendl;
- ioc.run();
+ global_ioc->run();
}
void run_https_server(const std::string& exporter_addr, short unsigned int port, const std::string& cert_file, const std::string& key_file) {
- net::io_context ioc{1};
ssl::context ssl_ctx(ssl::context::tlsv13);
ssl_ctx.use_certificate_chain_file(cert_file);
ssl_ctx.use_private_key_file(key_file, ssl::context::pem);
- tcp::acceptor acceptor{ioc, {net::ip::make_address(exporter_addr), port}};
+ tcp::acceptor acceptor{*global_ioc, {net::ip::make_address(exporter_addr), port}};
https_server(acceptor, ssl_ctx);
dout(1) << "HTTPS server running on " << exporter_addr << ":" << port << dendl;
- ioc.run();
+ global_ioc->run();
+}
+
+void stop_web_server() {
+ if (global_ioc) {
+ global_ioc->stop();
+ dout(1) << "Ceph exporter web server stopped" << dendl;
+ }
}
void web_server_thread_entrypoint() {
@@ -259,18 +267,21 @@ void web_server_thread_entrypoint() {
std::string cert_file = g_conf().get_val<std::string>("exporter_cert_file");
std::string key_file = g_conf().get_val<std::string>("exporter_key_file");
+ // Initialize global_ioc
+ global_ioc = std::make_shared<net::io_context>(1);
+
if (cert_file.empty() && key_file.empty()) {
run_http_server(exporter_addr, port);
} else {
try {
run_https_server(exporter_addr, port, cert_file, key_file);
} catch (const std::exception &e) {
- dout(1) << "Failed to start HTTPS server: " << e.what() << dendl;
+ derr << "Failed to start HTTPS server: " << e.what() << dendl;
exit(EXIT_FAILURE);
}
}
} catch (std::exception const &e) {
- dout(1) << "Error: " << e.what() << dendl;
+ derr << "Error: " << e.what() << dendl;
exit(EXIT_FAILURE);
}
}
diff --git a/src/exporter/web_server.h b/src/exporter/web_server.h
index c3339a8d43a..c6d4c54eca4 100644
--- a/src/exporter/web_server.h
+++ b/src/exporter/web_server.h
@@ -3,3 +3,4 @@
#include <string>
void web_server_thread_entrypoint();
+void stop_web_server();