From c6479c22e1b0d5158f02d52e0e4629d33e74f15c Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:39:19 -0400 Subject: [PATCH 01/16] further threadsafety hardening --- include/cpp-statsd-client/StatsdClient.hpp | 35 ++++++++-------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index 37a5837..af5894e 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -66,7 +66,8 @@ class StatsdClient { const std::string& prefix, const uint64_t batchsize = 0, const uint64_t sendInterval = 1000, - const int gaugePrecision = 4) noexcept; + const int gaugePrecision = 4, + unsigned int seed = std::random_device()()) noexcept; StatsdClient(const StatsdClient&) = delete; StatsdClient& operator=(const StatsdClient&) = delete; @@ -76,14 +77,6 @@ class StatsdClient { //!@name Methods //!@{ - //! Sets a configuration - void setConfig(const std::string& host, - const uint16_t port, - const std::string& prefix, - const uint64_t batchsize = 0, - const uint64_t sendInterval = 1000, - const int gaugePrecision = 4) noexcept; - //! Returns the error message as an std::string const std::string& errorMessage() const noexcept; @@ -130,9 +123,6 @@ class StatsdClient { float frequency = 1.0f, const std::vector& tags = {}) const noexcept; - //! Seed the RNG that controls sampling - void seed(unsigned int seed = std::random_device()()) noexcept; - //! Flush any queued stats to the daemon void flush() noexcept; @@ -159,9 +149,6 @@ class StatsdClient { //! The UDP sender to be used for actual sending std::unique_ptr m_sender; - //! The random number generator for handling sampling - mutable std::mt19937 m_randomEngine; - //! Fixed floating point precision of gauges int m_gaugePrecision; }; @@ -175,6 +162,11 @@ inline std::string sanitizePrefix(std::string prefix) { return prefix; } +std::mt19937& rng(unsigned int seed = 0){ + static thread_local std::mt19937 twister(seed); + return twister; +} + // All supported metric types constexpr char METRIC_TYPE_COUNT[] = "c"; constexpr char METRIC_TYPE_GAUGE[] = "g"; @@ -187,12 +179,13 @@ inline StatsdClient::StatsdClient(const std::string& host, const std::string& prefix, const uint64_t batchsize, const uint64_t sendInterval, - const int gaugePrecision) noexcept + const int gaugePrecision + const unsigned int seed) noexcept : m_prefix(detail::sanitizePrefix(prefix)), m_sender(new UDPSender{host, port, batchsize, sendInterval}), m_gaugePrecision(gaugePrecision) { // Initialize the random generator to be used for sampling - seed(); + rng(seed); } inline void StatsdClient::setConfig(const std::string& host, @@ -278,7 +271,7 @@ inline void StatsdClient::send(const std::string& key, const bool isFrequencyOne = std::fabs(frequency - 1.0f) < epsilon; const bool isFrequencyZero = std::fabs(frequency) < epsilon; if (isFrequencyZero || - (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(m_randomEngine)))) { + (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(rng())))) { return; } @@ -321,11 +314,7 @@ inline void StatsdClient::send(const std::string& key, m_sender->send(buffer); } -inline void StatsdClient::seed(unsigned int seed) noexcept { - m_randomEngine.seed(seed); -} - -inline void StatsdClient::flush() noexcept { +inline void StatsdClient::flush() const noexcept { m_sender->flush(); } From fc75931e1e741db019dc8d7640d818c806553822 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:40:12 -0400 Subject: [PATCH 02/16] Update StatsdClient.hpp --- include/cpp-statsd-client/StatsdClient.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index af5894e..4a59944 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -124,7 +124,7 @@ class StatsdClient { const std::vector& tags = {}) const noexcept; //! Flush any queued stats to the daemon - void flush() noexcept; + void flush() const noexcept; //!@} From 4f57c4b03c2217d6523ea6eeba39b13ec5920bde Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:41:53 -0400 Subject: [PATCH 03/16] lint --- include/cpp-statsd-client/StatsdClient.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index 4a59944..d322233 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -162,7 +162,7 @@ inline std::string sanitizePrefix(std::string prefix) { return prefix; } -std::mt19937& rng(unsigned int seed = 0){ +std::mt19937& rng(unsigned int seed = 0) { static thread_local std::mt19937 twister(seed); return twister; } @@ -179,7 +179,7 @@ inline StatsdClient::StatsdClient(const std::string& host, const std::string& prefix, const uint64_t batchsize, const uint64_t sendInterval, - const int gaugePrecision + const int gaugePrecision, const unsigned int seed) noexcept : m_prefix(detail::sanitizePrefix(prefix)), m_sender(new UDPSender{host, port, batchsize, sendInterval}), @@ -270,8 +270,7 @@ inline void StatsdClient::send(const std::string& key, constexpr float epsilon{0.0001f}; const bool isFrequencyOne = std::fabs(frequency - 1.0f) < epsilon; const bool isFrequencyZero = std::fabs(frequency) < epsilon; - if (isFrequencyZero || - (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(rng())))) { + if (isFrequencyZero || (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(rng())))) { return; } From b1cc5a3fec09922727753e21cf60d287073cc9d0 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:44:03 -0400 Subject: [PATCH 04/16] Update testStatsdClient.cpp --- tests/testStatsdClient.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/tests/testStatsdClient.cpp b/tests/testStatsdClient.cpp index 22e0d6e..7eba3bf 100644 --- a/tests/testStatsdClient.cpp +++ b/tests/testStatsdClient.cpp @@ -53,29 +53,6 @@ void testErrorConditions() { throwOnError(client, false, "Should not be able to resolve a ridiculous ip"); } -void testReconfigure() { - StatsdServer server; - throwOnError(server); - - StatsdClient client("localhost", 8125, "first."); - client.increment("foo"); - throwOnWrongMessage(server, "first.foo:1|c"); - - client.setConfig("localhost", 8125, "second"); - client.increment("bar"); - throwOnWrongMessage(server, "second.bar:1|c"); - - client.setConfig("localhost", 8125, ""); - client.increment("third.baz"); - throwOnWrongMessage(server, "third.baz:1|c"); - - client.increment(""); - throwOnWrongMessage(server, ":1|c"); - - // TODO: test what happens with the batching after resolving the question about incomplete - // batches being dropped vs sent on reconfiguring -} - void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { StatsdServer mock_server; std::vector messages, expected; From 13f5e4f33579b17eef9312552e978eda9e878d83 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:44:23 -0400 Subject: [PATCH 05/16] Update StatsdClient.hpp --- include/cpp-statsd-client/StatsdClient.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index d322233..ce80745 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -270,7 +270,7 @@ inline void StatsdClient::send(const std::string& key, constexpr float epsilon{0.0001f}; const bool isFrequencyOne = std::fabs(frequency - 1.0f) < epsilon; const bool isFrequencyZero = std::fabs(frequency) < epsilon; - if (isFrequencyZero || (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(rng())))) { + if (isFrequencyZero || (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(detail::rng())))) { return; } From 616ea70219041192f8c6d5a028314e7a2c4dc82c Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:45:19 -0400 Subject: [PATCH 06/16] lint --- include/cpp-statsd-client/StatsdClient.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index ce80745..e46321a 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -270,7 +270,8 @@ inline void StatsdClient::send(const std::string& key, constexpr float epsilon{0.0001f}; const bool isFrequencyOne = std::fabs(frequency - 1.0f) < epsilon; const bool isFrequencyZero = std::fabs(frequency) < epsilon; - if (isFrequencyZero || (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(detail::rng())))) { + if (isFrequencyZero || + (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(detail::rng())))) { return; } From 066c1be5f7cb96745f67305c93d23335a020b2d9 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:48:03 -0400 Subject: [PATCH 07/16] Update StatsdClient.hpp --- include/cpp-statsd-client/StatsdClient.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index e46321a..1764292 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -185,7 +185,7 @@ inline StatsdClient::StatsdClient(const std::string& host, m_sender(new UDPSender{host, port, batchsize, sendInterval}), m_gaugePrecision(gaugePrecision) { // Initialize the random generator to be used for sampling - rng(seed); + detail::rng(seed); } inline void StatsdClient::setConfig(const std::string& host, From 6a3c656cc941232664c32b65e60ddbfb901bb9eb Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:49:04 -0400 Subject: [PATCH 08/16] Update StatsdClient.hpp --- include/cpp-statsd-client/StatsdClient.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index 1764292..5348e9a 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -162,7 +162,7 @@ inline std::string sanitizePrefix(std::string prefix) { return prefix; } -std::mt19937& rng(unsigned int seed = 0) { +inline std::mt19937& rng(unsigned int seed = 0) { static thread_local std::mt19937 twister(seed); return twister; } @@ -188,17 +188,6 @@ inline StatsdClient::StatsdClient(const std::string& host, detail::rng(seed); } -inline void StatsdClient::setConfig(const std::string& host, - const uint16_t port, - const std::string& prefix, - const uint64_t batchsize, - const uint64_t sendInterval, - const int gaugePrecision) noexcept { - m_prefix = detail::sanitizePrefix(prefix); - m_sender.reset(new UDPSender(host, port, batchsize, sendInterval)); - m_gaugePrecision = gaugePrecision; -} - inline const std::string& StatsdClient::errorMessage() const noexcept { return m_sender->errorMessage(); } From fae2259903d1259e89cb05f79dd061c59a024d8b Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:50:03 -0400 Subject: [PATCH 09/16] Update testStatsdClient.cpp --- tests/testStatsdClient.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/testStatsdClient.cpp b/tests/testStatsdClient.cpp index 7eba3bf..370b28c 100644 --- a/tests/testStatsdClient.cpp +++ b/tests/testStatsdClient.cpp @@ -153,8 +153,6 @@ int main() { // general things that should be errors testErrorConditions(); - // reconfiguring how you are sending - testReconfigure(); // no batching testSendRecv(0, 0); // background batching From e3696285993048072c4453d41502e8705ab9fe14 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Mon, 21 Apr 2025 11:51:20 -0400 Subject: [PATCH 10/16] Update testStatsdClient.cpp --- tests/testStatsdClient.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/testStatsdClient.cpp b/tests/testStatsdClient.cpp index 370b28c..c0dfc47 100644 --- a/tests/testStatsdClient.cpp +++ b/tests/testStatsdClient.cpp @@ -59,7 +59,7 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { std::thread server(mock, std::ref(mock_server), std::ref(messages)); // Set a new config that has the client send messages to a proper address that can be resolved - StatsdClient client("localhost", 8125, "sendRecv.", batchSize, sendInterval, 3); + StatsdClient client("localhost", 8125, "sendRecv.", batchSize, sendInterval, 3, 19); // this seed works for the testing below throwOnError(client); // TODO: I forget if we need to wait for the server to be ready here before sending the first stats @@ -77,7 +77,6 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { expected.emplace_back("sendRecv.kiki:-1|c"); // Adjusts "toto" by +2 - client.seed(19); // this seed gets a hit on the first call client.count("toto", 2, 0.1f); throwOnError(client); expected.emplace_back("sendRecv.toto:2|c|@0.10"); @@ -97,7 +96,6 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { expected.emplace_back("sendRecv.titifloat:-123.457|g"); // Record a timing of 2ms for "myTiming" - client.seed(19); client.timing("myTiming", 2, 0.1f); throwOnError(client); expected.emplace_back("sendRecv.myTiming:2|ms|@0.10"); From 9fde229a55ab838f7592cb42bc313c778818dd5e Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Thu, 15 May 2025 09:36:03 -0400 Subject: [PATCH 11/16] fix up test --- include/cpp-statsd-client/StatsdClient.hpp | 69 ++++++++++++---------- tests/testStatsdClient.cpp | 27 ++++++--- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index 5348e9a..eddcd5d 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -4,15 +4,39 @@ #include #include #include +#include #include #include #include #include #include +#include #include namespace Statsd { +namespace detail { +inline std::string sanitizePrefix(std::string prefix) { + // For convenience we provide the dot when generating the stat message + if (!prefix.empty() && prefix.back() == '.') { + prefix.pop_back(); + } + return prefix; +} + +inline float rand(unsigned int seed) { + static thread_local std::mt19937 twister(seed); + static thread_local std::uniform_real_distribution dist(0.f, 1.f); + return dist(twister); +} + +// All supported metric types +constexpr char METRIC_TYPE_COUNT[] = "c"; +constexpr char METRIC_TYPE_GAUGE[] = "g"; +constexpr char METRIC_TYPE_TIMING[] = "ms"; +constexpr char METRIC_TYPE_SET[] = "s"; +} // namespace detail + /*! * * Statsd client @@ -27,8 +51,8 @@ namespace Statsd { * nor prepend one to the key * * The sampling frequency is specified per call and uses a - * random number generator to determine whether or not the stat - * will be recorded this time or not. + * random number generator (optionally user-specified) to + * determine whether the stat will be recorded this time or not. * * The top level configuration includes 2 optional parameters * that determine how the stats are delivered to statsd. These @@ -57,6 +81,11 @@ namespace Statsd { */ class StatsdClient { public: + + //! A functor that returns a value between 0 and 1 used + //! to determine whether a given message is sampled. + using FrequencyFunc = std::function; + //!@name Constructor and destructor, non-copyable //!@{ @@ -67,7 +96,8 @@ class StatsdClient { const uint64_t batchsize = 0, const uint64_t sendInterval = 1000, const int gaugePrecision = 4, - unsigned int seed = std::random_device()()) noexcept; + FrequencyFunc frequencyFunc = + std::bind(detail::rand, std::random_device()())) noexcept; StatsdClient(const StatsdClient&) = delete; StatsdClient& operator=(const StatsdClient&) = delete; @@ -142,7 +172,6 @@ class StatsdClient { //!@} -private: //! The prefix to be used for metrics std::string m_prefix; @@ -151,28 +180,10 @@ class StatsdClient { //! Fixed floating point precision of gauges int m_gaugePrecision; -}; - -namespace detail { -inline std::string sanitizePrefix(std::string prefix) { - // For convenience we provide the dot when generating the stat message - if (!prefix.empty() && prefix.back() == '.') { - prefix.pop_back(); - } - return prefix; -} -inline std::mt19937& rng(unsigned int seed = 0) { - static thread_local std::mt19937 twister(seed); - return twister; -} - -// All supported metric types -constexpr char METRIC_TYPE_COUNT[] = "c"; -constexpr char METRIC_TYPE_GAUGE[] = "g"; -constexpr char METRIC_TYPE_TIMING[] = "ms"; -constexpr char METRIC_TYPE_SET[] = "s"; -} // namespace detail + //! The function used to determine whether a message is sampled + FrequencyFunc m_frequencyFunc; +}; inline StatsdClient::StatsdClient(const std::string& host, const uint16_t port, @@ -180,12 +191,10 @@ inline StatsdClient::StatsdClient(const std::string& host, const uint64_t batchsize, const uint64_t sendInterval, const int gaugePrecision, - const unsigned int seed) noexcept + FrequencyFunc frequencyFunc) noexcept : m_prefix(detail::sanitizePrefix(prefix)), m_sender(new UDPSender{host, port, batchsize, sendInterval}), - m_gaugePrecision(gaugePrecision) { - // Initialize the random generator to be used for sampling - detail::rng(seed); + m_gaugePrecision(gaugePrecision), m_frequencyFunc(std::move(frequencyFunc)) { } inline const std::string& StatsdClient::errorMessage() const noexcept { @@ -260,7 +269,7 @@ inline void StatsdClient::send(const std::string& key, const bool isFrequencyOne = std::fabs(frequency - 1.0f) < epsilon; const bool isFrequencyZero = std::fabs(frequency) < epsilon; if (isFrequencyZero || - (!isFrequencyOne && (frequency < std::uniform_real_distribution(0.f, 1.f)(detail::rng())))) { + (!isFrequencyOne && (frequency < m_frequencyFunc()))) { return; } diff --git a/tests/testStatsdClient.cpp b/tests/testStatsdClient.cpp index c0dfc47..b27b0dc 100644 --- a/tests/testStatsdClient.cpp +++ b/tests/testStatsdClient.cpp @@ -58,15 +58,19 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { std::vector messages, expected; std::thread server(mock, std::ref(mock_server), std::ref(messages)); + std::mt19937 twister(std::random_device{}()); + std::uniform_real_distribution dist(0.f, 1.f); + auto rand = [&]()->float{return dist(twister);}; + // Set a new config that has the client send messages to a proper address that can be resolved - StatsdClient client("localhost", 8125, "sendRecv.", batchSize, sendInterval, 3, 19); // this seed works for the testing below + StatsdClient client("localhost", 8125, "sendRecv.", batchSize, sendInterval, 3, rand); throwOnError(client); // TODO: I forget if we need to wait for the server to be ready here before sending the first stats // is there a race condition where the client sending before the server binds would drop that clients message for (int i = 0; i < 3; ++i) { - // Increment "coco" + // Increment "coco" client.increment("coco"); throwOnError(client); expected.emplace_back("sendRecv.coco:1|c"); @@ -77,6 +81,7 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { expected.emplace_back("sendRecv.kiki:-1|c"); // Adjusts "toto" by +2 + twister.seed(19); // this seed gets a hit on the first call client.count("toto", 2, 0.1f); throwOnError(client); expected.emplace_back("sendRecv.toto:2|c|@0.10"); @@ -96,6 +101,7 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { expected.emplace_back("sendRecv.titifloat:-123.457|g"); // Record a timing of 2ms for "myTiming" + twister.seed(19); client.timing("myTiming", 2, 0.1f); throwOnError(client); expected.emplace_back("sendRecv.myTiming:2|ms|@0.10"); @@ -134,13 +140,18 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { // Make sure we get the exactly correct output if (messages != expected) { - std::cerr << "Unexpected stats received by server, got:" << std::endl; - for (const auto& message : messages) { - std::cerr << message << std::endl; + for (size_t i = 0; i < expected.size(); ++i) { + if (i >= messages.size()) { + std::cerr << "Missing messages at index " << i << ": expected '" << expected[i] << "'" << std::endl; + break; + } + if (messages[i] != expected[i]) { + std::cerr << "Mismatch at index " << i << ": expected '" << expected[i] << "', got '" << messages[i] << "'" << std::endl; + break; + } } - std::cerr << std::endl << "But we expected:" << std::endl; - for (const auto& message : expected) { - std::cerr << message << std::endl; + if (messages.size() > expected.size()) { + std::cerr << "Got more messages than expected, got " << messages.size() << ", expected " << expected.size() << std::endl; } throw std::runtime_error("Unexpected stats"); } From 3f3cae9ef8ca9e976e0ccb488558fa8f5f68ae78 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Thu, 15 May 2025 09:37:38 -0400 Subject: [PATCH 12/16] whitespace --- include/cpp-statsd-client/StatsdClient.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index eddcd5d..80f895c 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -96,7 +96,7 @@ class StatsdClient { const uint64_t batchsize = 0, const uint64_t sendInterval = 1000, const int gaugePrecision = 4, - FrequencyFunc frequencyFunc = + FrequencyFunc frequencyFunc = std::bind(detail::rand, std::random_device()())) noexcept; StatsdClient(const StatsdClient&) = delete; From 0906fc02388a6263057562cd50716ff31a92f271 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Thu, 15 May 2025 09:42:54 -0400 Subject: [PATCH 13/16] whitespace --- tests/testStatsdClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testStatsdClient.cpp b/tests/testStatsdClient.cpp index b27b0dc..6429480 100644 --- a/tests/testStatsdClient.cpp +++ b/tests/testStatsdClient.cpp @@ -70,7 +70,7 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { // is there a race condition where the client sending before the server binds would drop that clients message for (int i = 0; i < 3; ++i) { - // Increment "coco" + // Increment "coco" client.increment("coco"); throwOnError(client); expected.emplace_back("sendRecv.coco:1|c"); From 668677e707490e359d751b44e9886cf59e21a40a Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Thu, 15 May 2025 09:46:37 -0400 Subject: [PATCH 14/16] lint --- include/cpp-statsd-client/StatsdClient.hpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/include/cpp-statsd-client/StatsdClient.hpp b/include/cpp-statsd-client/StatsdClient.hpp index 80f895c..d19d6ba 100644 --- a/include/cpp-statsd-client/StatsdClient.hpp +++ b/include/cpp-statsd-client/StatsdClient.hpp @@ -81,7 +81,6 @@ constexpr char METRIC_TYPE_SET[] = "s"; */ class StatsdClient { public: - //! A functor that returns a value between 0 and 1 used //! to determine whether a given message is sampled. using FrequencyFunc = std::function; @@ -96,8 +95,7 @@ class StatsdClient { const uint64_t batchsize = 0, const uint64_t sendInterval = 1000, const int gaugePrecision = 4, - FrequencyFunc frequencyFunc = - std::bind(detail::rand, std::random_device()())) noexcept; + FrequencyFunc frequencyFunc = std::bind(detail::rand, std::random_device()())) noexcept; StatsdClient(const StatsdClient&) = delete; StatsdClient& operator=(const StatsdClient&) = delete; @@ -191,11 +189,11 @@ inline StatsdClient::StatsdClient(const std::string& host, const uint64_t batchsize, const uint64_t sendInterval, const int gaugePrecision, - FrequencyFunc frequencyFunc) noexcept + FrequencyFunc frequencyFunc) noexcept : m_prefix(detail::sanitizePrefix(prefix)), m_sender(new UDPSender{host, port, batchsize, sendInterval}), - m_gaugePrecision(gaugePrecision), m_frequencyFunc(std::move(frequencyFunc)) { -} + m_gaugePrecision(gaugePrecision), + m_frequencyFunc(std::move(frequencyFunc)) {} inline const std::string& StatsdClient::errorMessage() const noexcept { return m_sender->errorMessage(); @@ -268,8 +266,7 @@ inline void StatsdClient::send(const std::string& key, constexpr float epsilon{0.0001f}; const bool isFrequencyOne = std::fabs(frequency - 1.0f) < epsilon; const bool isFrequencyZero = std::fabs(frequency) < epsilon; - if (isFrequencyZero || - (!isFrequencyOne && (frequency < m_frequencyFunc()))) { + if (isFrequencyZero || (!isFrequencyOne && (frequency < m_frequencyFunc()))) { return; } From fbf9f41e149d5bc024d068fdee53e0c16cb761b4 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Thu, 15 May 2025 09:47:25 -0400 Subject: [PATCH 15/16] lint --- tests/testStatsdClient.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/testStatsdClient.cpp b/tests/testStatsdClient.cpp index 6429480..767ae47 100644 --- a/tests/testStatsdClient.cpp +++ b/tests/testStatsdClient.cpp @@ -60,7 +60,7 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { std::mt19937 twister(std::random_device{}()); std::uniform_real_distribution dist(0.f, 1.f); - auto rand = [&]()->float{return dist(twister);}; + auto rand = [&]() -> float { return dist(twister); }; // Set a new config that has the client send messages to a proper address that can be resolved StatsdClient client("localhost", 8125, "sendRecv.", batchSize, sendInterval, 3, rand); @@ -146,12 +146,14 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) { break; } if (messages[i] != expected[i]) { - std::cerr << "Mismatch at index " << i << ": expected '" << expected[i] << "', got '" << messages[i] << "'" << std::endl; + std::cerr << "Mismatch at index " << i << ": expected '" << expected[i] << "', got '" << messages[i] + << "'" << std::endl; break; } } if (messages.size() > expected.size()) { - std::cerr << "Got more messages than expected, got " << messages.size() << ", expected " << expected.size() << std::endl; + std::cerr << "Got more messages than expected, got " << messages.size() << ", expected " << expected.size() + << std::endl; } throw std::runtime_error("Unexpected stats"); } From 32770615d6128c64cc445100e6f128dc42586419 Mon Sep 17 00:00:00 2001 From: Kevin Kreiser Date: Thu, 15 May 2025 13:19:32 -0400 Subject: [PATCH 16/16] Update README.md docs updates --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df629e0..4f6c616 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Linux status](https://img.shields.io/github/workflow/status/vthiery/cpp-statsd-client/Linux?label=Linux&style=for-the-badge)](https://github.com/vthiery/cpp-statsd-client/actions/workflows/linux.yml?query=branch%3Amaster++) [![Windows status](https://img.shields.io/github/workflow/status/vthiery/cpp-statsd-client/Windows?label=Windows&style=for-the-badge)](https://github.com/vthiery/cpp-statsd-client/actions/workflows/windows.yml?query=branch%3Amaster++) -A header-only StatsD client implemented in C++. +A thread-safe header-only StatsD client implemented in C++. The client allows: - batching,