Skip to content

Commit 438ac41

Browse files
author
Vincent Thiery
committed
Merge branch 'release/0.0.3'
2 parents 46b24d8 + 0206686 commit 438ac41

File tree

8 files changed

+139
-53
lines changed

8 files changed

+139
-53
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
build/
1+
bin

.travis.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
language: cpp
2+
3+
matrix:
4+
include:
5+
- os: linux
6+
addons:
7+
apt:
8+
sources:
9+
- ubuntu-toolchain-r-test
10+
packages:
11+
- g++-7
12+
env:
13+
- MATRIX_EVAL="BUILD_MODE=Debug && CC=gcc-7 && CXX=g++-7 && CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -std=c++17"
14+
15+
- os: linux
16+
addons:
17+
apt:
18+
sources:
19+
- ubuntu-toolchain-r-test
20+
packages:
21+
- g++-7
22+
env:
23+
- MATRIX_EVAL="BUILD_MODE=Release && CC=gcc-7 && CXX=g++-7 && CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -std=c++17"
24+
25+
- os: linux
26+
addons:
27+
apt:
28+
sources:
29+
- ubuntu-toolchain-r-test
30+
packages:
31+
- g++-7
32+
env:
33+
- MATRIX_EVAL="BUILD_MODE=Debug && CC=gcc-7 && CXX=g++-7 && CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -std=c++14"
34+
35+
- os: linux
36+
addons:
37+
apt:
38+
sources:
39+
- ubuntu-toolchain-r-test
40+
packages:
41+
- g++-7
42+
env:
43+
- MATRIX_EVAL="BUILD_MODE=Release && CC=gcc-7 && CXX=g++-7 && CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -std=c++14"
44+
45+
before_install:
46+
- eval "${MATRIX_EVAL}"
47+
48+
script: make test

CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cmake_minimum_required(VERSION 3.2)
2+
3+
project(StatsdClient)
4+
5+
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
6+
7+
install(FILES src/* DESTINATION include)
8+
9+
find_package (Threads)
10+
add_executable(testStatsdClient ${CMAKE_CURRENT_SOURCE_DIR}/tests/testStatsdClient.cpp)
11+
target_link_libraries(testStatsdClient ${CMAKE_THREAD_LIBS_INIT})
12+
13+
enable_testing()
14+
add_test(testSuite testStatsdClient)

Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# simple makefile to build, test and clean
2+
3+
BUILD_MODE ?= Release
4+
5+
build: clean
6+
@echo "Build in ${BUILD_MODE} mode"
7+
mkdir -p bin/${BUILD_MODE}
8+
@cd bin/${BUILD_MODE}; cmake ../../ -DCMAKE_BUILD_TYPE=${BUILD_MODE}
9+
@cd bin/${BUILD_MODE}; make
10+
11+
test: build
12+
@cd bin/${BUILD_MODE}; make test
13+
14+
install: build
15+
@cd bin/${BUILD_MODE}; make install
16+
17+
clean:
18+
@rm -rf bin

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# C++ StatsD Client
22

3+
[ ![Download](https://api.bintray.com/packages/vthiery/conan-packages/statsdclient%3Avthiery/images/download.svg) ](https://bintray.com/vthiery/conan-packages/statsdclient%3Avthiery/_latestVersion)
4+
[![Build Status](https://travis-ci.org/vthiery/cpp-statsd-client.svg?branch=develop)](https://travis-ci.org/vthiery/cpp-statsd-client)
5+
[![Github Issues](https://img.shields.io/github/issues/vthiery/cpp-statsd-client.svg)](https://github.com/vthiery/cpp-statsd-client/issues)
6+
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/vthiery/cpp-statsd-client.svg)](http://isitmaintained.com/project/vthiery/cpp-statsd-client "Average time to resolve an issue")
7+
38
A header-only StatsD client implemented in C++.
49
The client allows:
510
- batching,
@@ -16,7 +21,7 @@ using namespace Statsd;
1621
int main()
1722
{
1823
// Define the client
19-
StatsdClient client{ "127.0.0.1", 5005, "myPrefix_", true };
24+
StatsdClient client{ "127.0.0.1", 5005, "myPrefix.", 3 };
2025

2126
// Increment "coco"
2227
client.increment("coco");

src/StatsdClient.hpp

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef STATSD_CLIENT_HPP
22
#define STATSD_CLIENT_HPP
33

4+
#include <cstdlib>
45
#include <experimental/optional>
56
#include <string>
67
#include "UDPSender.hpp"
@@ -33,9 +34,6 @@ class StatsdClient
3334
const std::string& prefix,
3435
const std::experimental::optional<uint64_t> batchsize = std::experimental::nullopt) noexcept;
3536

36-
//! Default destructor
37-
~StatsdClient() = default;
38-
3937
//!@}
4038

4139
//!@name Methods
@@ -67,16 +65,6 @@ class StatsdClient
6765

6866
//!@}
6967

70-
private:
71-
72-
// @name Private methods
73-
// @{
74-
75-
//! Returns a cleaned key
76-
inline std::string clean(const std::string& key) const noexcept;
77-
78-
// @}
79-
8068
private:
8169

8270
//! The prefix to be used for metrics
@@ -96,7 +84,7 @@ StatsdClient(
9684
, m_sender(host, port, batchsize)
9785
{
9886
// Initialize the randorm generator to be used for sampling
99-
srandom(time(NULL));
87+
std::srand(time(nullptr));
10088
}
10189

10290
void
@@ -162,48 +150,29 @@ send(const std::string& key, const int value, const std::string& type, const flo
162150
// Test if one should send or not, according to the frequency rate
163151
if (!isFrequencyOne(frequency))
164152
{
165-
if (frequency < (float)random() / RAND_MAX)
153+
if (frequency < static_cast<float>(std::rand()) / RAND_MAX)
166154
{
167155
return;
168156
}
169157
}
170158

171-
// Clean the key
172-
clean(key);
173-
174159
// Prepare the buffer, with a sampling rate if specified different from 1.0f
175160
char buffer[256];
176161
if (isFrequencyOne(frequency))
177162
{
178163
// Sampling rate is 1.0f, no need to specify it
179-
snprintf(buffer, sizeof(buffer), "%s%s:%zd|%s", m_prefix.c_str(), key.c_str(), static_cast<signed size_t>(value), type.c_str());
164+
snprintf(buffer, sizeof(buffer), "%s%s:%zd|%s", m_prefix.c_str(), key.c_str(), static_cast<int64_t>(value), type.c_str());
180165
}
181166
else
182167
{
183168
// Sampling rate is different from 1.0f, hence specify it
184-
snprintf(buffer, sizeof(buffer), "%s%s:%zd|%s|@%.2f", m_prefix.c_str(), key.c_str(), static_cast<signed size_t>(value), type.c_str(), frequency);
169+
snprintf(buffer, sizeof(buffer), "%s%s:%zd|%s|@%.2f", m_prefix.c_str(), key.c_str(), static_cast<int64_t>(value), type.c_str(), frequency);
185170
}
186171

187172
// Send the message via the UDP sender
188173
m_sender.send(buffer);
189174
}
190175

191-
std::string
192-
StatsdClient::
193-
clean(const std::string& key) const noexcept
194-
{
195-
std::string cleanKey = key;
196-
size_t pos = key.find_first_of(":|@");
197-
198-
// Add the '_' appropriately to the key
199-
while (pos != std::string::npos)
200-
{
201-
cleanKey[pos] = '_';
202-
pos = cleanKey.find_first_of(":|@");
203-
}
204-
return cleanKey;
205-
}
206-
207176
}
208177

209178
#endif

src/UDPSender.hpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ UDPSender(
143143
m_batchsize = batchsize.value();
144144

145145
// Define the batching thread
146-
m_batchingThread = std::thread([this] {
146+
m_batchingThread = std::thread([this, batchingWait] {
147147
while (!m_mustExit)
148148
{
149149
std::deque<std::string> stagedMessageQueue;
@@ -232,6 +232,8 @@ bool
232232
UDPSender::
233233
initialize() noexcept
234234
{
235+
using namespace std::string_literals;
236+
235237
if (m_isInitialized)
236238
{
237239
return true;
@@ -241,9 +243,7 @@ initialize() noexcept
241243
m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
242244
if (m_socket == -1)
243245
{
244-
char buffer[256];
245-
snprintf(buffer, sizeof(buffer), "Could not create socket, err=%m");
246-
m_errorMessage = std::string(buffer);
246+
m_errorMessage = "Could not create socket, err="s + std::strerror(errno);
247247
return false;
248248
}
249249

@@ -263,17 +263,13 @@ initialize() noexcept
263263

264264
// Get the address info using the hints
265265
struct addrinfo* results = nullptr;
266-
const int ret = getaddrinfo(m_host.c_str(), nullptr, &hints, &results);
266+
const int ret{ getaddrinfo(m_host.c_str(), nullptr, &hints, &results) };
267267
if (ret != 0)
268268
{
269269
// An error code has been returned by getaddrinfo
270270
close(m_socket);
271271
m_socket = -1;
272-
273-
char buffer[256];
274-
snprintf(buffer, sizeof(buffer), "getaddrinfo failed: error=%d, msg=%s", ret, gai_strerror(ret));
275-
m_errorMessage = std::string(buffer);
276-
272+
m_errorMessage = "getaddrinfo failed: error="s + std::to_string(ret) + ", msg=" + gai_strerror(ret);
277273
return false;
278274
}
279275

@@ -286,7 +282,6 @@ initialize() noexcept
286282
}
287283

288284
m_isInitialized = true;
289-
290285
return true;
291286
}
292287

@@ -301,12 +296,11 @@ sendToDaemon(const std::string& message) noexcept
301296
}
302297

303298
// Try sending the message
304-
const int ret = sendto(m_socket, message.data(), message.size(), 0, (struct sockaddr *)&m_server, sizeof(m_server));
299+
const long int ret{ sendto(m_socket, message.data(), message.size(), 0, (struct sockaddr *)&m_server, sizeof(m_server)) };
305300
if (ret == -1)
306301
{
307-
char buffer[256];
308-
snprintf(buffer, sizeof(buffer), "sendto server failed: host=%s:%d, err=%m", m_host.c_str(), m_port);
309-
m_errorMessage = std::string(buffer);
302+
using namespace std::string_literals;
303+
m_errorMessage = "sendto server failed: host="s + m_host + ":" + std::to_string(m_port) + ", err=" + std::strerror(errno);
310304
}
311305
}
312306

tests/testStatsdClient.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <StatsdClient.hpp>
2+
#include <cassert>
3+
4+
using namespace Statsd;
5+
6+
int main()
7+
{
8+
StatsdClient client{ "localhost", 8080, "myPrefix.", 1 };
9+
10+
// set a new config with a different port
11+
client.setConfig("localhost", 80, "myPrefix.");
12+
13+
// Increment "coco"
14+
client.increment("coco");
15+
assert(!client.errorMessage());
16+
17+
// Decrement "kiki"
18+
client.decrement("kiki");
19+
assert(!client.errorMessage());
20+
21+
// Adjusts "toto" by +3
22+
client.count("toto", 2, 0.1f);
23+
assert(!client.errorMessage());
24+
25+
// Record a gauge "titi" to 3
26+
client.gauge("titi", 3);
27+
assert(!client.errorMessage());
28+
29+
// Record a timing of 2ms for "myTiming"
30+
client.timing("myTiming", 2, 0.1f);
31+
assert(!client.errorMessage());
32+
33+
// Send a metric explicitly
34+
client.send("tutu", 4, "c", 2.0f);
35+
assert(!client.errorMessage());
36+
37+
return EXIT_SUCCESS;
38+
}

0 commit comments

Comments
 (0)