@cryptotaxi247 / netdata-1 / commits / 0e1599252

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 // --------------------------------------------------------------------------------------