From 299691493f817be9070b16791f917c8621e7132d Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Fri, 11 Sep 2026 16:31:28 -0700 Subject: [PATCH 1/4] statsmanager: allow multiple instances to share a prometheus server --- src/core/statsmanager.cpp | 66 ++++++++---------- src/core/statsmanager.h | 13 ++-- src/core/statsmanager.rs | 126 ++++++++++++++++++++++++++-------- src/handler/handlerengine.cpp | 15 ++-- src/proxy/proxyapp.cpp | 26 +++++-- src/proxy/proxyengine.cpp | 13 +--- src/proxy/proxyengine.h | 6 +- 7 files changed, 174 insertions(+), 91 deletions(-) diff --git a/src/core/statsmanager.cpp b/src/core/statsmanager.cpp index fbf72dcc..df8cf7c6 100644 --- a/src/core/statsmanager.cpp +++ b/src/core/statsmanager.cpp @@ -301,9 +301,8 @@ class StatsManager::Private { int subscriptionLinger; int reportInterval; std::unique_ptr sock; - QString prometheusPrefix; - ffi::CommonMetrics *commonMetrics; - ffi::PrometheusServer *prometheusServer; + std::shared_ptr commonMetrics; + size_t commonMetricsRegistrationId; QHash routeActivity; QHash connectionInfoById; QHash> connectionInfoByRoute; @@ -345,8 +344,7 @@ class StatsManager::Private { subscriptionTtl(60 * 1000), subscriptionLinger(60 * 1000), reportInterval(10 * 1000), - commonMetrics(nullptr), - prometheusServer(nullptr), + commonMetricsRegistrationId(0), currentConnectionInfoRefreshBucket(0), currentSubscriptionRefreshBucket(0), wheel(TimerWheel((_connectionsMax * 2) + _subscriptionsMax)) { @@ -374,8 +372,8 @@ class StatsManager::Private { } ~Private() { - ffi::prometheus_server_destroy(prometheusServer); - ffi::statsmanager_commonmetrics_destroy(commonMetrics); + if (commonMetrics) + commonMetrics->unregisterInstance(commonMetricsRegistrationId); qDeleteAll(connectionInfoById); @@ -409,35 +407,17 @@ class StatsManager::Private { return true; } - bool setPrometheusPort(const QString &portStr) { - assert(!commonMetrics && !prometheusServer); - - commonMetrics = ffi::statsmanager_commonmetrics_create(prometheusPrefix.toUtf8().data()); - if (!commonMetrics) - return false; - - const ffi::PrometheusRegistry *registry = - ffi::statsmanager_commonmetrics_registry(commonMetrics); - - const char *error = nullptr; - prometheusServer = ffi::prometheus_server_create(portStr.toUtf8().data(), registry, &error); - if (!prometheusServer) { - log_error("prometheus_server_create: %s", error); - ffi::prometheus_server_error_destroy(error); - ffi::statsmanager_commonmetrics_destroy(commonMetrics); - commonMetrics = nullptr; - return false; - } - - return true; + void setCommonMetrics(std::shared_ptr cm) { + assert(!commonMetrics); + commonMetrics = std::move(cm); + commonMetricsRegistrationId = commonMetrics->registerInstance(); } void combinedReportChanged() { if (commonMetrics) { - ffi::statsmanager_commonmetrics_update( - commonMetrics, combinedReport.requestsReceived, combinedReport.connectionsMax, - combinedReport.connectionsMinutes, combinedReport.messagesReceived, - combinedReport.messagesSent); + commonMetrics->update(commonMetricsRegistrationId, combinedReport.requestsReceived, + combinedReport.connectionsMax, combinedReport.connectionsMinutes, + combinedReport.messagesReceived, combinedReport.messagesSent); } } @@ -1339,10 +1319,18 @@ const ffi::PrometheusRegistry *StatsManager::CommonMetrics::registry() const { return ffi::statsmanager_commonmetrics_registry(inner_); } -void StatsManager::CommonMetrics::update(uint32_t requestReceived, uint32_t connectionConnected, - uint32_t connectionMinute, uint32_t messageReceived, - uint32_t messageSent) { - ffi::statsmanager_commonmetrics_update(inner_, requestReceived, connectionConnected, +size_t StatsManager::CommonMetrics::registerInstance() { + return ffi::statsmanager_commonmetrics_register(inner_); +} + +void StatsManager::CommonMetrics::unregisterInstance(size_t id) { + ffi::statsmanager_commonmetrics_unregister(inner_, id); +} + +void StatsManager::CommonMetrics::update(size_t id, uint32_t requestReceived, + uint32_t connectionConnected, uint32_t connectionMinute, + uint32_t messageReceived, uint32_t messageSent) { + ffi::statsmanager_commonmetrics_update(inner_, id, requestReceived, connectionConnected, connectionMinute, messageReceived, messageSent); } @@ -1388,9 +1376,9 @@ void StatsManager::setReportInterval(int secs) { void StatsManager::setOutputFormat(Format format) { d->outputFormat = format; } -bool StatsManager::setPrometheusPort(const QString &port) { return d->setPrometheusPort(port); } - -void StatsManager::setPrometheusPrefix(const QString &prefix) { d->prometheusPrefix = prefix; } +void StatsManager::setCommonMetrics(std::shared_ptr commonMetrics) { + d->setCommonMetrics(std::move(commonMetrics)); +} void StatsManager::addActivity(const QByteArray &routeId, uint32_t count) { if (d->routeActivity.contains(routeId)) diff --git a/src/core/statsmanager.h b/src/core/statsmanager.h index efcee7da..1b34f491 100644 --- a/src/core/statsmanager.h +++ b/src/core/statsmanager.h @@ -28,6 +28,8 @@ #include "rust/bindings.h" #include "stats.h" #include +#include +#include class QHostAddress; @@ -42,7 +44,9 @@ class StatsManager { enum Format { TnetStringFormat, JsonFormat }; /// RAII wrapper around the Rust-backed CommonMetrics object, which holds the prometheus - /// registry and all metric handles. + /// registry and all metric handles. Multiple StatsManager instances may share one + /// CommonMetrics via std::shared_ptr; each registers itself to obtain a per-instance ID + /// that is passed to update(). class CommonMetrics { public: ~CommonMetrics(); @@ -53,7 +57,9 @@ class StatsManager { static std::unique_ptr create(const QString &prefix); const ffi::PrometheusRegistry *registry() const; - void update(uint32_t requestReceived, uint32_t connectionConnected, + size_t registerInstance(); + void unregisterInstance(size_t id); + void update(size_t id, uint32_t requestReceived, uint32_t connectionConnected, uint32_t connectionMinute, uint32_t messageReceived, uint32_t messageSent); private: @@ -77,8 +83,7 @@ class StatsManager { void setSubscriptionLinger(int secs); void setReportInterval(int secs); void setOutputFormat(Format format); - bool setPrometheusPort(const QString &port); - void setPrometheusPrefix(const QString &prefix); + void setCommonMetrics(std::shared_ptr commonMetrics); // RouteId may be empty for non-identified route diff --git a/src/core/statsmanager.rs b/src/core/statsmanager.rs index 4755e199..8cfa01c0 100644 --- a/src/core/statsmanager.rs +++ b/src/core/statsmanager.rs @@ -16,6 +16,16 @@ use crate::core::prometheus::try_register_process_collector; use prometheus::{IntCounter, IntGauge}; +use slab::Slab; + +#[derive(Default)] +struct PrevValues { + request_received: u32, + connection_connected: u32, + connection_minute: u32, + message_received: u32, + message_sent: u32, +} /// Metrics needed by the `StatsManager` C++ class. pub struct CommonMetrics { @@ -25,10 +35,7 @@ pub struct CommonMetrics { connection_minute: IntCounter, message_received: IntCounter, message_sent: IntCounter, - prev_request_received: u32, - prev_connection_minute: u32, - prev_message_received: u32, - prev_message_sent: u32, + instances: Slab, } impl CommonMetrics { @@ -88,45 +95,75 @@ impl CommonMetrics { connection_minute, message_received, message_sent, - prev_request_received: 0, - prev_connection_minute: 0, - prev_message_received: 0, - prev_message_sent: 0, + instances: Slab::new(), + } + } + + fn register(&mut self) -> usize { + self.instances.insert(PrevValues::default()) + } + + fn unregister(&mut self, id: usize) { + let prev = self.instances.remove(id); + if prev.connection_connected > 0 { + self.connection_connected + .sub(prev.connection_connected as i64); } } fn update( &mut self, + id: usize, request_received: u32, connection_connected: u32, connection_minute: u32, message_received: u32, message_sent: u32, ) { - let delta = request_received.saturating_sub(self.prev_request_received); - if delta > 0 { - self.request_received.inc_by(delta as u64); - self.prev_request_received = request_received; + // Compute deltas and update prev values in a scoped borrow so we can + // subsequently call methods on the rest of `self`. + let (req_delta, conn_delta, conn_min_delta, msg_recv_delta, msg_sent_delta) = { + let prev = &mut self.instances[id]; + + let req_delta = request_received.saturating_sub(prev.request_received); + let conn_delta = (connection_connected as i64) - (prev.connection_connected as i64); + let conn_min_delta = connection_minute.saturating_sub(prev.connection_minute); + let msg_recv_delta = message_received.saturating_sub(prev.message_received); + let msg_sent_delta = message_sent.saturating_sub(prev.message_sent); + + prev.request_received = request_received; + prev.connection_connected = connection_connected; + prev.connection_minute = connection_minute; + prev.message_received = message_received; + prev.message_sent = message_sent; + + ( + req_delta, + conn_delta, + conn_min_delta, + msg_recv_delta, + msg_sent_delta, + ) + }; + + if req_delta > 0 { + self.request_received.inc_by(req_delta as u64); } - self.connection_connected.set(connection_connected as i64); + if conn_delta != 0 { + self.connection_connected.add(conn_delta); + } - let delta = connection_minute.saturating_sub(self.prev_connection_minute); - if delta > 0 { - self.connection_minute.inc_by(delta as u64); - self.prev_connection_minute = connection_minute; + if conn_min_delta > 0 { + self.connection_minute.inc_by(conn_min_delta as u64); } - let delta = message_received.saturating_sub(self.prev_message_received); - if delta > 0 { - self.message_received.inc_by(delta as u64); - self.prev_message_received = message_received; + if msg_recv_delta > 0 { + self.message_received.inc_by(msg_recv_delta as u64); } - let delta = message_sent.saturating_sub(self.prev_message_sent); - if delta > 0 { - self.message_sent.inc_by(delta as u64); - self.prev_message_sent = message_sent; + if msg_sent_delta > 0 { + self.message_sent.inc_by(msg_sent_delta as u64); } } } @@ -188,15 +225,49 @@ mod ffi { &m.registry as *const prometheus::Registry as *const PrometheusRegistry } - /// Update all metrics to the current totals. For counters the delta since the last call is - /// computed internally; `connection_connected` is a gauge and is set directly. + /// Register a new StatsManager instance and return an opaque ID for it. Pass this ID to + /// `statsmanager_commonmetrics_update` and `statsmanager_commonmetrics_unregister`. + /// + /// # Safety + /// + /// `m` must be a valid non-null pointer returned by `statsmanager_commonmetrics_create`. + #[no_mangle] + pub unsafe extern "C" fn statsmanager_commonmetrics_register(m: *mut CommonMetrics) -> usize { + let m = unsafe { m.as_mut().unwrap() }; + m.register() + } + + /// Unregister a StatsManager instance previously registered with + /// `statsmanager_commonmetrics_register`. After this call, `id` must not be passed to + /// `statsmanager_commonmetrics_update`. + /// + /// # Safety + /// + /// `m` must be a valid non-null pointer returned by `statsmanager_commonmetrics_create`. + /// `id` must be a value previously returned by `statsmanager_commonmetrics_register` on + /// the same instance that has not yet been unregistered. + #[no_mangle] + pub unsafe extern "C" fn statsmanager_commonmetrics_unregister( + m: *mut CommonMetrics, + id: usize, + ) { + let m = unsafe { m.as_mut().unwrap() }; + m.unregister(id); + } + + /// Update all metrics to the current totals for the given StatsManager instance. For counters + /// the delta since the last call (per instance) is computed internally; + /// `connection_connected` is a gauge and is set directly. /// /// # Safety /// /// `m` must be a valid non-null pointer returned by `statsmanager_commonmetrics_create`. + /// `id` must be a value previously returned by `statsmanager_commonmetrics_register` on + /// the same instance that has not yet been unregistered. #[no_mangle] pub unsafe extern "C" fn statsmanager_commonmetrics_update( m: *mut CommonMetrics, + id: usize, request_received: u32, connection_connected: u32, connection_minute: u32, @@ -206,6 +277,7 @@ mod ffi { let m = unsafe { m.as_mut().unwrap() }; m.update( + id, request_received, connection_connected, connection_minute, diff --git a/src/handler/handlerengine.cpp b/src/handler/handlerengine.cpp index 444a54b5..8391fdb0 100644 --- a/src/handler/handlerengine.cpp +++ b/src/handler/handlerengine.cpp @@ -42,6 +42,7 @@ #include "packet/retryrequestpacket.h" #include "packet/statspacket.h" #include "packet/wscontrolpacket.h" +#include "prometheus.h" #include "publishformat.h" #include "publishitem.h" #include "publishlastids.h" @@ -1120,6 +1121,8 @@ class HandlerEngine::Private { std::unique_ptr proxyStatsSock; std::unique_ptr proxyStatsValve; std::unique_ptr controlHttpServer; + std::shared_ptr commonMetrics; + std::unique_ptr prometheusServer; std::unique_ptr stats; std::unique_ptr publishLimiter; std::unique_ptr updateLimiter; @@ -1391,13 +1394,17 @@ class HandlerEngine::Private { } if (!config.prometheusPort.isEmpty()) { - stats->setPrometheusPrefix(config.prometheusPrefix); + commonMetrics = StatsManager::CommonMetrics::create(config.prometheusPrefix); - if (!stats->setPrometheusPort(config.prometheusPort)) { - log_error("unable to bind to prometheus port: %s", - qPrintable(config.prometheusPort)); + QString promError; + prometheusServer = PrometheusServer::create(config.prometheusPort, + commonMetrics->registry(), &promError); + if (!prometheusServer) { + log_error("unable to bind to prometheus port: %s", qPrintable(promError)); return false; } + + stats->setCommonMetrics(commonMetrics); } if (!config.proxyStatsSpecs.isEmpty()) { diff --git a/src/proxy/proxyapp.cpp b/src/proxy/proxyapp.cpp index 246e1cbf..3d4b8b0c 100644 --- a/src/proxy/proxyapp.cpp +++ b/src/proxy/proxyapp.cpp @@ -27,12 +27,14 @@ #include "eventloop.h" #include "log.h" #include "processquit.h" +#include "prometheus.h" #include "proxyargsdata.h" #include "proxyengine.h" #include "rust/bindings.h" #include "rustthread.h" #include "settings.h" #include "simplehttpserver.h" +#include "statsmanager.h" #include "timer.h" #include "xffrule.h" #include @@ -235,7 +237,23 @@ class EngineThread { }; static int runLoop(const QString &logFile, const Engine::Configuration &config, - const QStringList &routeLines, const QString &routesFile, int workerCount) { + const QStringList &routeLines, const QString &routesFile, int workerCount, + const QString &prometheusPort, const QString &prometheusPrefix) { + std::shared_ptr commonMetrics; + std::unique_ptr prometheusServer; + + if (!prometheusPort.isEmpty()) { + commonMetrics = StatsManager::CommonMetrics::create(prometheusPrefix); + + QString promError; + prometheusServer = + PrometheusServer::create(prometheusPort, commonMetrics->registry(), &promError); + if (!prometheusServer) { + log_error("unable to bind to prometheus port: %s", qPrintable(promError)); + return 1; + } + } + // Plenty for the main thread int timersMax = 100; @@ -291,6 +309,7 @@ static int runLoop(const QString &logFile, const Engine::Configuration &config, Engine::Configuration wconfig = config; wconfig.id = n; + wconfig.commonMetrics = commonMetrics; if (workerCount > 1) { wconfig.clientId += '-' + QByteArray::number(n); @@ -558,9 +577,8 @@ int proxy_init(const ffi::ProxyCliArgs *argsFfi) { config.statsConnectionTtl = statsConnectionTtl; config.statsConnectionsMaxTtl = statsConnectionsMaxTtl; config.statsReportInterval = statsReportInterval; - config.prometheusPort = prometheusPort; - config.prometheusPrefix = prometheusPrefix; - return runLoop(args.logFile, config, args.routeLines, routesFile, workerCount); + return runLoop(args.logFile, config, args.routeLines, routesFile, workerCount, prometheusPort, + prometheusPrefix); } } diff --git a/src/proxy/proxyengine.cpp b/src/proxy/proxyengine.cpp index 887dc8ce..36326bff 100644 --- a/src/proxy/proxyengine.cpp +++ b/src/proxy/proxyengine.cpp @@ -279,7 +279,7 @@ class Engine::Private { } // Set up StatsManager - if (!config.statsSpec.isEmpty() || !config.prometheusPort.isEmpty()) { + if (!config.statsSpec.isEmpty() || config.commonMetrics) { stats = std::make_unique(config.sessionsMax, 0); connMaxConnection = stats->connMax.connect( @@ -300,15 +300,8 @@ class Engine::Private { } } - if (!config.prometheusPort.isEmpty()) { - stats->setPrometheusPrefix(config.prometheusPrefix); - - if (!stats->setPrometheusPort(config.prometheusPort)) { - log_error("unable to bind to prometheus port: %s", - qPrintable(config.prometheusPort)); - return false; - } - } + if (config.commonMetrics) + stats->setCommonMetrics(config.commonMetrics); } if (!config.commandSpec.isEmpty()) { diff --git a/src/proxy/proxyengine.h b/src/proxy/proxyengine.h index 81522091..b048b0a3 100644 --- a/src/proxy/proxyengine.h +++ b/src/proxy/proxyengine.h @@ -25,11 +25,13 @@ #define PROXYENGINE_H #include "jwt.h" +#include "statsmanager.h" #include "xffrule.h" #include #include #include #include +#include // Each session can have a bunch of timers: // 2 per incoming zhttprequest/zwebsocket @@ -50,7 +52,6 @@ using std::map; using Connection = boost::signals2::scoped_connection; -class StatsManager; class DomainMap; /// Orchestrates the core proxy service: @@ -106,8 +107,7 @@ class Engine { int statsConnectionTtl; int statsConnectionsMaxTtl; int statsReportInterval; - QString prometheusPort; - QString prometheusPrefix; + std::shared_ptr commonMetrics; Configuration() : id(0), From 014c4f4b8cb1c6a7dadae405049644472c04c4e0 Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Fri, 11 Sep 2026 17:08:59 -0700 Subject: [PATCH 2/4] nits --- src/core/statsmanager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/statsmanager.cpp b/src/core/statsmanager.cpp index df8cf7c6..77d21ed1 100644 --- a/src/core/statsmanager.cpp +++ b/src/core/statsmanager.cpp @@ -301,7 +301,7 @@ class StatsManager::Private { int subscriptionLinger; int reportInterval; std::unique_ptr sock; - std::shared_ptr commonMetrics; + std::shared_ptr commonMetrics; size_t commonMetricsRegistrationId; QHash routeActivity; QHash connectionInfoById; @@ -407,7 +407,7 @@ class StatsManager::Private { return true; } - void setCommonMetrics(std::shared_ptr cm) { + void setCommonMetrics(std::shared_ptr cm) { assert(!commonMetrics); commonMetrics = std::move(cm); commonMetricsRegistrationId = commonMetrics->registerInstance(); @@ -1312,7 +1312,7 @@ StatsManager::CommonMetrics::create(const QString &prefix) { ffi::CommonMetrics *handle = ffi::statsmanager_commonmetrics_create(prefix.toUtf8().data()); if (!handle) return nullptr; - return std::unique_ptr(new StatsManager::CommonMetrics(handle)); + return std::unique_ptr(new CommonMetrics(handle)); } const ffi::PrometheusRegistry *StatsManager::CommonMetrics::registry() const { From 6f69063c6ff4e6a38ee7ea9ec2a0b2c8c26e27be Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Fri, 11 Sep 2026 17:41:42 -0700 Subject: [PATCH 3/4] thread through commonMetrics independently rather than putting in config --- src/proxy/proxyapp.cpp | 51 ++++++++++++++++++++------------------- src/proxy/proxyengine.cpp | 15 ++++++++---- src/proxy/proxyengine.h | 2 +- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/proxy/proxyapp.cpp b/src/proxy/proxyapp.cpp index 3d4b8b0c..26700cd1 100644 --- a/src/proxy/proxyapp.cpp +++ b/src/proxy/proxyapp.cpp @@ -97,8 +97,9 @@ enum CommandLineParseResult { /// Wraps Engine with lifecycle signals and defer call support class EngineWorker { public: - EngineWorker(const Engine::Configuration &config, DomainMap *domainMap) - : config_(config), engine_(std::make_unique(domainMap)) {} + EngineWorker(const Engine::Configuration &config, DomainMap *domainMap, + std::shared_ptr commonMetrics) + : config_(config), engine_(std::make_unique(domainMap, commonMetrics)) {} DeferCall deferCall; @@ -141,10 +142,12 @@ class EngineThread { QWaitCondition w; Engine::Configuration config; DomainMap *domainMap; + std::shared_ptr commonMetrics; EngineWorker *worker; - EngineThread(const Engine::Configuration &_config, DomainMap *_domainMap) - : config(_config), domainMap(_domainMap), worker(nullptr) {} + EngineThread(const Engine::Configuration &_config, DomainMap *_domainMap, + std::shared_ptr _commonMetrics) + : config(_config), domainMap(_domainMap), commonMetrics(_commonMetrics), worker(nullptr) {} ~EngineThread() { stop(); @@ -199,7 +202,7 @@ class EngineThread { EventLoop loop(registrationsMax); // Create worker on the stack in this thread - EngineWorker worker_local(config, domainMap); + EngineWorker worker_local(config, domainMap, commonMetrics); // Set member pointer for cross-thread access worker = &worker_local; @@ -238,22 +241,7 @@ class EngineThread { static int runLoop(const QString &logFile, const Engine::Configuration &config, const QStringList &routeLines, const QString &routesFile, int workerCount, - const QString &prometheusPort, const QString &prometheusPrefix) { - std::shared_ptr commonMetrics; - std::unique_ptr prometheusServer; - - if (!prometheusPort.isEmpty()) { - commonMetrics = StatsManager::CommonMetrics::create(prometheusPrefix); - - QString promError; - prometheusServer = - PrometheusServer::create(prometheusPort, commonMetrics->registry(), &promError); - if (!prometheusServer) { - log_error("unable to bind to prometheus port: %s", qPrintable(promError)); - return 1; - } - } - + std::shared_ptr commonMetrics) { // Plenty for the main thread int timersMax = 100; @@ -309,7 +297,6 @@ static int runLoop(const QString &logFile, const Engine::Configuration &config, Engine::Configuration wconfig = config; wconfig.id = n; - wconfig.commonMetrics = commonMetrics; if (workerCount > 1) { wconfig.clientId += '-' + QByteArray::number(n); @@ -326,7 +313,7 @@ static int runLoop(const QString &logFile, const Engine::Configuration &config, wconfig.intServerOutSpecs = suffixSpecs(wconfig.intServerOutSpecs, n); } - EngineThread *t = new EngineThread(wconfig, domainMap.get()); + EngineThread *t = new EngineThread(wconfig, domainMap.get(), commonMetrics); if (!t->start()) { delete t; @@ -520,6 +507,21 @@ int proxy_init(const ffi::ProxyCliArgs *argsFfi) { else sessionsMax = clientMaxconn; + std::shared_ptr commonMetrics; + std::unique_ptr prometheusServer; + + if (!prometheusPort.isEmpty()) { + commonMetrics = StatsManager::CommonMetrics::create(prometheusPrefix); + + QString promError; + prometheusServer = + PrometheusServer::create(prometheusPort, commonMetrics->registry(), &promError); + if (!prometheusServer) { + log_error("unable to bind to prometheus port: %s", qPrintable(promError)); + return 1; + } + } + Engine::Configuration config; config.appVersion = Config::get().version; config.clientId = "proxy_" + QByteArray::number(getpid()); @@ -578,7 +580,6 @@ int proxy_init(const ffi::ProxyCliArgs *argsFfi) { config.statsConnectionsMaxTtl = statsConnectionsMaxTtl; config.statsReportInterval = statsReportInterval; - return runLoop(args.logFile, config, args.routeLines, routesFile, workerCount, prometheusPort, - prometheusPrefix); + return runLoop(args.logFile, config, args.routeLines, routesFile, workerCount, commonMetrics); } } diff --git a/src/proxy/proxyengine.cpp b/src/proxy/proxyengine.cpp index 36326bff..99bcb585 100644 --- a/src/proxy/proxyengine.cpp +++ b/src/proxy/proxyengine.cpp @@ -94,6 +94,7 @@ class Engine::Private { Engine *q; bool destroying; DomainMap *domainMap; + std::shared_ptr commonMetrics; Configuration config; std::unique_ptr zhttpIn; std::unique_ptr intZhttpIn; @@ -123,7 +124,9 @@ class Engine::Private { Connection connMaxConnection; Connection rrConnection; - Private(Engine *_q, DomainMap *_domainMap) : q(_q), destroying(false), domainMap(_domainMap) {} + Private(Engine *_q, DomainMap *_domainMap, + std::shared_ptr _commonMetrics) + : q(_q), destroying(false), domainMap(_domainMap), commonMetrics(_commonMetrics) {} ~Private() { destroying = true; @@ -279,7 +282,7 @@ class Engine::Private { } // Set up StatsManager - if (!config.statsSpec.isEmpty() || config.commonMetrics) { + if (!config.statsSpec.isEmpty() || commonMetrics) { stats = std::make_unique(config.sessionsMax, 0); connMaxConnection = stats->connMax.connect( @@ -300,8 +303,8 @@ class Engine::Private { } } - if (config.commonMetrics) - stats->setCommonMetrics(config.commonMetrics); + if (commonMetrics) + stats->setCommonMetrics(commonMetrics); } if (!config.commandSpec.isEmpty()) { @@ -944,7 +947,9 @@ class Engine::Private { } }; -Engine::Engine(DomainMap *domainMap) { d = new Private(this, domainMap); } +Engine::Engine(DomainMap *domainMap, std::shared_ptr commonMetrics) { + d = new Private(this, domainMap, commonMetrics); +} Engine::~Engine() { delete d; } diff --git a/src/proxy/proxyengine.h b/src/proxy/proxyengine.h index b048b0a3..779413bb 100644 --- a/src/proxy/proxyengine.h +++ b/src/proxy/proxyengine.h @@ -129,7 +129,7 @@ class Engine { statsReportInterval(-1) {} }; - Engine(DomainMap *domainMap); + Engine(DomainMap *domainMap, std::shared_ptr commonMetrics = {}); ~Engine(); StatsManager *statsManager() const; From e5c8d461f1b8fd6e7ce5d5f8c4106890a27ccd7b Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Fri, 11 Sep 2026 17:43:35 -0700 Subject: [PATCH 4/4] nit --- src/proxy/proxyengine.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/proxy/proxyengine.h b/src/proxy/proxyengine.h index 779413bb..7537d934 100644 --- a/src/proxy/proxyengine.h +++ b/src/proxy/proxyengine.h @@ -107,7 +107,6 @@ class Engine { int statsConnectionTtl; int statsConnectionsMaxTtl; int statsReportInterval; - std::shared_ptr commonMetrics; Configuration() : id(0),