added histogram metrics for stddev, median; statsd binds by default to localhost; statsd detects unterminated TCP packets; high speed statsd-stress
Costa Tsaousis (ktsaou) committed
Apr 30, 2017 at 13:38 UTC
0e15992523ec4c7d218fd3c7fc3a1bd8a64b514c
5 files changed
+48
-27
Makefile.am
+1
@@ -60,6 +60,7 @@ dist_noinst_DATA= \
60
diagrams/registry.puml \
61
diagrams/netdata-for-ephemeral-nodes.xml \
62
diagrams/netdata-proxies-example.xml \
63
+ diagrams/netdata-overview.xml \
64
configs.signatures \
65
Dockerfile \
66
netdata.spec \
profile/statsd-stress.c
+12
-12
@@ -15,15 +15,15 @@ void diep(char *s)
15
exit(1);
16
}
17
18
-int run_threads = 1;
19
-int metrics = 1024;
18
+size_t run_threads = 1;
19
+size_t metrics = 1024;
20
21
#define SERVER_IP "127.0.0.1"
22
#define PORT 8125
23
24
size_t myrand(size_t max) {
25
- int loops = max / RAND_MAX;
26
- int i;
25
+ size_t loops = max / RAND_MAX;
26
+ size_t i;
27
28
size_t ret = rand();
29
for(i = 0; i < loops ;i++)
@@ -33,7 +33,7 @@ size_t myrand(size_t max) {
33
}
34
35
struct thread_data {
36
- int id;
36
+ size_t id;
37
struct sockaddr_in *si_other;
38
int slen;
39
size_t counter;
@@ -44,7 +44,7 @@ static void *report_thread(void *__data) {
44
45
size_t last = 0;
46
for (;;) {
47
- int i;
47
+ size_t i;
48
size_t total = 0;
49
for(i = 0; i < run_threads ;i++)
50
total += data[i].counter;
@@ -65,17 +65,17 @@ char *types[STATSD_METRIC_TYPES] = {"g", "c", "m", "ms", "h", "s"};
65
static void *spam_thread(void *__data) {
66
struct thread_data *data = (struct thread_data *)__data;
67
68
- int s, i;
68
+ int s;
69
char packet[1024];
70
71
if ((s = socket(AF_INET, SOCK_DGRAM, 0))==-1)
72
diep("socket");
73
74
char **packets = malloc(sizeof(char *) * metrics);
75
- size_t *lengths = malloc(sizeof(size_t) * metrics);
75
+ size_t i, *lengths = malloc(sizeof(size_t) * metrics);
76
77
for(i = 0; i < metrics ;i++) {
78
- lengths[i] = sprintf(packet, "github.test.packet.%zu:%zu.%zu|%s", myrand(metrics), myrand(metrics), myrand(metrics), types[myrand(STATSD_METRIC_TYPES)]);
78
+ lengths[i] = sprintf(packet, "github.test.packet.%zu.%zu:%zu.%zu|%s", data->id, i, myrand(metrics), myrand(metrics), types[myrand(STATSD_METRIC_TYPES)]);
79
packets[i] = strdup(packet);
80
// printf("packet %d, of length %zu: '%s'\n", i, lengths[i], packets[i]);
81
}
@@ -111,7 +111,7 @@ int main(int argc, char *argv[])
111
struct thread_data data[run_threads];
112
struct sockaddr_in si_other;
113
pthread_t threads[run_threads], report;
114
- int i;
114
+ size_t i;
115
116
srand(time(NULL));
117
@@ -132,8 +132,8 @@ int main(int argc, char *argv[])
132
}
133
134
printf("\n");
135
- printf("THREADS : %d\n", run_threads);
136
- printf("METRICS : %d\n", metrics);
135
+ printf("THREADS : %zu\n", run_threads);
136
+ printf("METRICS : %zu\n", metrics);
137
printf("DESTINATION : %s:%d\n", ip, port);
138
printf("\n");
139
pthread_create(&report, NULL, report_thread, &data);
src/socket.c
+3
-4
@@ -256,6 +256,7 @@ static inline int bind_to_one(LISTEN_SOCKETS *sockets, const char *definition, i
256
struct sockaddr_in *sin = (struct sockaddr_in *) rp->ai_addr;
257
inet_ntop(AF_INET, &sin->sin_addr, rip, INET_ADDRSTRLEN);
258
rport = ntohs(sin->sin_port);
259
+ // info("Attempting to listen on IPv4 '%s' ('%s'), port %d ('%s'), socktype %d", rip, ip, rport, port, socktype);
260
fd = create_listen_socket4(socktype, rip, rport, listen_backlog);
261
break;
262
}
@@ -264,6 +265,7 @@ static inline int bind_to_one(LISTEN_SOCKETS *sockets, const char *definition, i
265
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) rp->ai_addr;
266
inet_ntop(AF_INET6, &sin6->sin6_addr, rip, INET6_ADDRSTRLEN);
267
rport = ntohs(sin6->sin6_port);
268
+ // info("Attempting to listen on IPv6 '%s' ('%s'), port %d ('%s'), socktype %d", rip, ip, rport, port, socktype);
269
fd = create_listen_socket6(socktype, scope_id, rip, rport, listen_backlog);
270
break;
271
}
@@ -321,10 +323,7 @@ int listen_sockets_setup(LISTEN_SOCKETS *sockets) {
323
s = e;
324
}
325
324
- if(!sockets->opened)
325
- fatal("LISTENER: Cannot listen on any socket. Exiting...");
326
-
327
- else if(sockets->failed) {
326
+ if(sockets->failed) {
327
size_t i;
328
for(i = 0; i < sockets->opened ;i++)
329
info("LISTENER: Listen socket %s opened successfully.", sockets->fds_names[i]);
src/statsd.c
+26
-10
@@ -44,10 +44,14 @@ typedef struct statsd_histogram_extensions {
44
size_t used;
45
collected_number last_min;
46
collected_number last_max;
47
- collected_number last_pct;
47
+ collected_number last_percentile;
48
+ collected_number last_median;
49
+ collected_number last_stddev;
50
RRDDIM *rd_min;
51
RRDDIM *rd_max;
50
- RRDDIM *rd_pct;
52
+ RRDDIM *rd_percentile;
53
+ RRDDIM *rd_median;
54
+ RRDDIM *rd_stddev;
55
long double values[]; // dynamic array of values collected
56
} STATSD_METRIC_HISTOGRAM_EXTENSIONS;
57
@@ -224,7 +228,7 @@ static struct statsd {
228
.threads = 0,
229
.sockets = {
230
.config_section = CONFIG_SECTION_STATSD,
227
- .default_bind_to = "udp:* tcp:*",
231
+ .default_bind_to = "udp:localhost:8125 tcp:localhost:8125",
232
.default_port = STATSD_LISTEN_PORT,
233
.backlog = STATSD_LISTEN_BACKLOG
234
},
@@ -641,8 +645,14 @@ static void statsd_del_callback(int fd, void *data) {
645
646
if(data) {
647
struct statsd_tcp *t = data;
644
- if(t->type != STATSD_SOCKET_DATA_TYPE_TCP)
645
- error("STATSD: received socket data type is %d, but expected %d", (int)t->type, (int)STATSD_SOCKET_DATA_TYPE_TCP);
648
+ if(t->type == STATSD_SOCKET_DATA_TYPE_TCP) {
649
+ if(t->len != 0) {
650
+ statsd.socket_errors++;
651
+ error("STATSD: client is probably sending unterminated metrics. Closed socket left with '%s'", &t->buffer[t->len]);
652
+ }
653
+ }
654
+ else
655
+ error("STATSD: internal error: received socket data type is %d, but expected %d", (int)t->type, (int)STATSD_SOCKET_DATA_TYPE_TCP);
656
657
freez(data);
658
}
@@ -1060,8 +1070,10 @@ static inline void statsd_chart_from_timer_or_histogram(STATSD_METRIC *m, char *
1070
1071
m->histogram.ext->rd_min = rrddim_add(m->st, "min", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1072
m->histogram.ext->rd_max = rrddim_add(m->st, "max", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1063
- m->rd_value = rrddim_add(m->st, "avg", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1064
- m->histogram.ext->rd_pct = rrddim_add(m->st, statsd.histogram_percentile_str, NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1073
+ m->rd_value = rrddim_add(m->st, "average", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1074
+ m->histogram.ext->rd_percentile = rrddim_add(m->st, statsd.histogram_percentile_str, NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1075
+ m->histogram.ext->rd_median = rrddim_add(m->st, "median", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1076
+ m->histogram.ext->rd_stddev = rrddim_add(m->st, "stddev", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1077
1078
if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
1079
m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
@@ -1076,13 +1088,17 @@ static inline void statsd_chart_from_timer_or_histogram(STATSD_METRIC *m, char *
1088
m->histogram.ext->last_min = (collected_number)roundl(series[0] * 1000.0);
1089
m->histogram.ext->last_max = (collected_number)roundl(series[len - 1] * 1000.0);
1090
m->last = (collected_number)roundl(average(series, len) * 1000);
1079
- m->histogram.ext->last_pct = (collected_number)roundl(average(series, (size_t)floor((double)len * statsd.histogram_percentile / 100.0)) * 1000);
1091
+ m->histogram.ext->last_percentile = (collected_number)roundl(average(series, (size_t)floor((double)len * statsd.histogram_percentile / 100.0)) * 1000);
1092
+ m->histogram.ext->last_median = (collected_number)roundl(median_on_sorted_series(series, len) * 1000);
1093
+ m->histogram.ext->last_stddev = (collected_number)roundl(standard_deviation(series, len) * 1000);
1094
}
1095
1096
m->reset = 1;
1097
rrddim_set_by_pointer(m->st, m->histogram.ext->rd_min, m->histogram.ext->last_min);
1098
rrddim_set_by_pointer(m->st, m->histogram.ext->rd_max, m->histogram.ext->last_max);
1085
- rrddim_set_by_pointer(m->st, m->histogram.ext->rd_pct, m->histogram.ext->last_pct);
1099
+ rrddim_set_by_pointer(m->st, m->histogram.ext->rd_percentile, m->histogram.ext->last_percentile);
1100
+ rrddim_set_by_pointer(m->st, m->histogram.ext->rd_median, m->histogram.ext->last_median);
1101
+ rrddim_set_by_pointer(m->st, m->histogram.ext->rd_stddev, m->histogram.ext->last_stddev);
1102
rrddim_set_by_pointer(m->st, m->rd_value, m->last);
1103
1104
if(m->rd_count)
@@ -1219,7 +1235,7 @@ void *statsd_main(void *ptr) {
1235
1236
statsd_listen_sockets_setup();
1237
if(!statsd.sockets.opened) {
1222
- error("STATSD: No statsd sockets to listen to.");
1238
+ error("STATSD: No statsd sockets to listen to. statsd will be disabled.");
1239
pthread_exit(NULL);
1240
}
1241
src/web_server.c
+6
-1
@@ -74,7 +74,12 @@ const char *web_server_mode_name(WEB_SERVER_MODE id) {
74
// --------------------------------------------------------------------------------------
75
76
int api_listen_sockets_setup(void) {
77
- return listen_sockets_setup(&api_sockets);
77
+ int socks = listen_sockets_setup(&api_sockets);
78
+
79
+ if(!socks)
80
+ fatal("LISTENER: Cannot listen on any API socket. Exiting...");
81
+
82
+ return socks;
83
}
84
85
// --------------------------------------------------------------------------------------