Skip to content

Commit fdc9bf4

Browse files
authored
feat: support custom metric types (#45)
Add a `custom()` method where the metric type is passed in by the caller, to allow using statsd backends that support metric types beyond those supported by the original Etsy statsd daemon.
1 parent 54856de commit fdc9bf4

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,20 @@ One may also attach tags to a metrics, e.g.
134134
client.gauge("titi", 3.2, 0.1f, {"foo", "bar"});
135135
```
136136
137+
### Custom metric types
138+
139+
Some statsd backends (e.g. Datadog, netdata) support metric types beyond those supported by the original Etsy statsd daemon, e.g.
140+
141+
* Histograms (type "h"), which are like Timers, but with different units
142+
* Dictionaries (type "d"), which are like Sets but also record a count for each unique value
143+
144+
Non-standard metrics can be sent using the `custom()` method, where the metric type is passed in by the caller. The client performs no validation, under the assumption that the caller will only pass in types, values, and other optional parameters (e.g. frequency, tags) that are supported by their backend. The templated `value` parameter must support serialization to a `std::basic_ostream` using `operator<<`.
145+
146+
```cpp
147+
// Record a histogram of packet sizes
148+
client.custom("packet_size", 1500, "h");
149+
```
150+
137151
## Advanced Testing
138152

139153
A simple mock StatsD server can be found at `tests/StatsdServer.hpp`. This can be used to do simple validation of your application's metrics, typically in the form of unit tests. In fact this is the primary means by which this library is tested. The mock server itself is not distributed with the library so to use it you'd need to vendor this project into your project. Once you have though, you can test your application's use of the client like so:

include/cpp-statsd-client/StatsdClient.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ class StatsdClient {
122122
float frequency = 1.0f,
123123
const std::vector<std::string>& tags = {}) const noexcept;
124124

125+
//! Records a custom metric type for the key, with a given value, at a given frequency
126+
template <typename T>
127+
void custom(const std::string& key,
128+
const T value,
129+
const char* type,
130+
float frequency = 1.0f,
131+
const std::vector<std::string>& tags = {}) const noexcept;
132+
125133
//! Seed the RNG that controls sampling
126134
void seed(unsigned int seed = std::random_device()()) noexcept;
127135

@@ -248,6 +256,15 @@ inline void StatsdClient::set(const std::string& key,
248256
send(key, sum, detail::METRIC_TYPE_SET, frequency, tags);
249257
}
250258

259+
template <typename T>
260+
inline void StatsdClient::custom(const std::string& key,
261+
const T value,
262+
const char* type,
263+
const float frequency,
264+
const std::vector<std::string>& tags) const noexcept {
265+
send(key, value, type, frequency, tags);
266+
}
267+
251268
template <typename T>
252269
inline void StatsdClient::send(const std::string& key,
253270
const T value,

tests/testStatsdClient.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ void testSendRecv(uint64_t batchSize, uint64_t sendInterval) {
139139
client.count("foo", -42, .9f, {"bar", "baz"});
140140
throwOnError(client);
141141
expected.emplace_back("sendRecv.foo:-42|c|@0.90|#bar,baz");
142+
143+
// Custom metric type should pass through all params
144+
client.custom("custom_metric_type", 5678, "cust", .95f, {"tag1", "tag2"});
145+
throwOnError(client);
146+
expected.emplace_back("sendRecv.custom_metric_type:5678|cust|@0.95|#tag1,tag2");
142147
}
143148

144149
// Signal the mock server we are done

0 commit comments

Comments
 (0)