Skip to content

Commit a06a5b9

Browse files
authored
feat: allow float gauges (#39)
1 parent ad34828 commit a06a5b9

File tree

3 files changed

+53
-23
lines changed

3 files changed

+53
-23
lines changed

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ A simple example of how to use the client:
4545
using namespace Statsd;
4646

4747
int main() {
48-
// Define the client on localhost, with port 8080, using a prefix and a batching size of 20 bytes
49-
StatsdClient client{ "127.0.0.1", 8080, "myPrefix", 20 };
48+
// Define the client on localhost, with port 8080,
49+
// using a prefix,
50+
// a batching size of 20 bytes,
51+
// and three points of precision for floating point gauge values
52+
StatsdClient client{ "127.0.0.1", 8080, "myPrefix", 20, 3 };
5053

5154
// Increment the metric "coco"
5255
client.increment("coco");
@@ -110,13 +113,16 @@ using namespace Statsd;
110113
111114
int main()
112115
{
113-
// Define the client on localhost, with port 8080, using a prefix and a batching size of 20 bytes
114-
StatsdClient client{ "127.0.0.1", 8080, "myPrefix", 20 };
116+
// Define the client on localhost, with port 8080,
117+
// using a prefix,
118+
// a batching size of 20 bytes,
119+
// and three points of precision for floating point gauge values
120+
StatsdClient client{ "127.0.0.1", 8080, "myPrefix", 20, 3 };
115121
116122
client.increment("coco");
117123
118-
// Set a new configuration, using a different port and a different prefix
119-
client.setConfig("127.0.0.1", 8000, "anotherPrefix");
124+
// Set a new configuration, using a different port, a different prefix, and more gauge precision
125+
client.setConfig("127.0.0.1", 8000, "anotherPrefix", 6);
120126
121127
client.decrement("kiki");
122128
}

include/cpp-statsd-client/StatsdClient.hpp

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
#include <cpp-statsd-client/UDPSender.hpp>
55
#include <cstdint>
66
#include <cstdio>
7+
#include <iomanip>
78
#include <memory>
89
#include <random>
10+
#include <sstream>
911
#include <string>
1012
#include <vector>
1113

@@ -63,7 +65,8 @@ class StatsdClient {
6365
const uint16_t port,
6466
const std::string& prefix,
6567
const uint64_t batchsize = 0,
66-
const uint64_t sendInterval = 1000) noexcept;
68+
const uint64_t sendInterval = 1000,
69+
const unsigned int gaugePrecision = 4) noexcept;
6770

6871
StatsdClient(const StatsdClient&) = delete;
6972
StatsdClient& operator=(const StatsdClient&) = delete;
@@ -78,7 +81,8 @@ class StatsdClient {
7881
const uint16_t port,
7982
const std::string& prefix,
8083
const uint64_t batchsize = 0,
81-
const uint64_t sendInterval = 1000) noexcept;
84+
const uint64_t sendInterval = 1000,
85+
const unsigned int gaugePrecision = 4) noexcept;
8286

8387
//! Returns the error message as an std::string
8488
const std::string& errorMessage() const noexcept;
@@ -100,8 +104,9 @@ class StatsdClient {
100104
const std::vector<std::string>& tags = {}) const noexcept;
101105

102106
//! Records a gauge for the key, with a given value, at a given frequency rate
107+
template <typename T>
103108
void gauge(const std::string& key,
104-
const unsigned int value,
109+
const T value,
105110
float frequency = 1.0f,
106111
const std::vector<std::string>& tags = {}) const noexcept;
107112

@@ -130,8 +135,9 @@ class StatsdClient {
130135
// @{
131136

132137
//! Send a value for a key, according to its type, at a given frequency
138+
template <typename T>
133139
void send(const std::string& key,
134-
const int value,
140+
const T value,
135141
const char* type,
136142
float frequency,
137143
const std::vector<std::string>& tags) const noexcept;
@@ -150,6 +156,9 @@ class StatsdClient {
150156

151157
//! The buffer string format our stats before sending them
152158
mutable std::string m_buffer;
159+
160+
//! Fixed floating point precision of gauges
161+
unsigned int m_gaugePrecision;
153162
};
154163

155164
namespace detail {
@@ -172,8 +181,11 @@ inline StatsdClient::StatsdClient(const std::string& host,
172181
const uint16_t port,
173182
const std::string& prefix,
174183
const uint64_t batchsize,
175-
const uint64_t sendInterval) noexcept
176-
: m_prefix(detail::sanitizePrefix(prefix)), m_sender(new UDPSender{host, port, batchsize, sendInterval}) {
184+
const uint64_t sendInterval,
185+
const unsigned int gaugePrecision) noexcept
186+
: m_prefix(detail::sanitizePrefix(prefix)),
187+
m_sender(new UDPSender{host, port, batchsize, sendInterval}),
188+
m_gaugePrecision(gaugePrecision) {
177189
// Initialize the random generator to be used for sampling
178190
seed();
179191
// Avoid re-allocations by reserving a generous buffer
@@ -184,9 +196,11 @@ inline void StatsdClient::setConfig(const std::string& host,
184196
const uint16_t port,
185197
const std::string& prefix,
186198
const uint64_t batchsize,
187-
const uint64_t sendInterval) noexcept {
199+
const uint64_t sendInterval,
200+
const unsigned int gaugePrecision) noexcept {
188201
m_prefix = detail::sanitizePrefix(prefix);
189202
m_sender.reset(new UDPSender(host, port, batchsize, sendInterval));
203+
m_gaugePrecision = gaugePrecision;
190204
}
191205

192206
inline const std::string& StatsdClient::errorMessage() const noexcept {
@@ -196,45 +210,47 @@ inline const std::string& StatsdClient::errorMessage() const noexcept {
196210
inline void StatsdClient::decrement(const std::string& key,
197211
float frequency,
198212
const std::vector<std::string>& tags) const noexcept {
199-
return count(key, -1, frequency, tags);
213+
count(key, -1, frequency, tags);
200214
}
201215

202216
inline void StatsdClient::increment(const std::string& key,
203217
float frequency,
204218
const std::vector<std::string>& tags) const noexcept {
205-
return count(key, 1, frequency, tags);
219+
count(key, 1, frequency, tags);
206220
}
207221

208222
inline void StatsdClient::count(const std::string& key,
209223
const int delta,
210224
float frequency,
211225
const std::vector<std::string>& tags) const noexcept {
212-
return send(key, delta, detail::METRIC_TYPE_COUNT, frequency, tags);
226+
send(key, delta, detail::METRIC_TYPE_COUNT, frequency, tags);
213227
}
214228

229+
template <typename T>
215230
inline void StatsdClient::gauge(const std::string& key,
216-
const unsigned int value,
231+
const T value,
217232
const float frequency,
218233
const std::vector<std::string>& tags) const noexcept {
219-
return send(key, value, detail::METRIC_TYPE_GAUGE, frequency, tags);
234+
send(key, value, detail::METRIC_TYPE_GAUGE, frequency, tags);
220235
}
221236

222237
inline void StatsdClient::timing(const std::string& key,
223238
const unsigned int ms,
224239
float frequency,
225240
const std::vector<std::string>& tags) const noexcept {
226-
return send(key, ms, detail::METRIC_TYPE_TIMING, frequency, tags);
241+
send(key, ms, detail::METRIC_TYPE_TIMING, frequency, tags);
227242
}
228243

229244
inline void StatsdClient::set(const std::string& key,
230245
const unsigned int sum,
231246
float frequency,
232247
const std::vector<std::string>& tags) const noexcept {
233-
return send(key, sum, detail::METRIC_TYPE_SET, frequency, tags);
248+
send(key, sum, detail::METRIC_TYPE_SET, frequency, tags);
234249
}
235250

251+
template <typename T>
236252
inline void StatsdClient::send(const std::string& key,
237-
const int value,
253+
const T value,
238254
const char* type,
239255
float frequency,
240256
const std::vector<std::string>& tags) const noexcept {
@@ -255,6 +271,9 @@ inline void StatsdClient::send(const std::string& key,
255271
}
256272

257273
// Format the stat message
274+
std::stringstream valueStream;
275+
valueStream << std::fixed << std::setprecision(m_gaugePrecision) << value;
276+
258277
m_buffer.clear();
259278

260279
m_buffer.append(m_prefix);
@@ -264,7 +283,7 @@ inline void StatsdClient::send(const std::string& key,
264283

265284
m_buffer.append(key);
266285
m_buffer.push_back(':');
267-
m_buffer.append(std::to_string(value));
286+
m_buffer.append(valueStream.str());
268287
m_buffer.push_back('|');
269288
m_buffer.append(type);
270289

tests/testStatsdClient.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) {
8282
std::thread server(mock, std::ref(mock_server), std::ref(messages));
8383

8484
// Set a new config that has the client send messages to a proper address that can be resolved
85-
StatsdClient client("localhost", 8125, "sendRecv.", batchSize, sendInterval);
85+
StatsdClient client("localhost", 8125, "sendRecv.", batchSize, sendInterval, 3);
8686
throwOnError(client);
8787

8888
// TODO: I forget if we need to wait for the server to be ready here before sending the first stats
@@ -114,6 +114,11 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) {
114114
throwOnError(client);
115115
expected.emplace_back("sendRecv.titi:3|g");
116116

117+
// Record a gauge "titifloat" to -123.456789 with precision 3
118+
client.gauge("titifloat", -123.456789);
119+
throwOnError(client);
120+
expected.emplace_back("sendRecv.titifloat:-123.457|g");
121+
117122
// Record a timing of 2ms for "myTiming"
118123
client.seed(19);
119124
client.timing("myTiming", 2, 0.1f);

0 commit comments

Comments
 (0)