use recvmmsg() to receive multiple packets for each read operation; completed pollfd internal API
Costa Tsaousis (ktsaou) committed
Apr 29, 2017 at 01:43 UTC
256b329d0140803ddb137f7032102fcad9c138c0
4 files changed
+282
-33
configure.ac
+1
@@ -126,6 +126,7 @@ AC_CHECK_TYPES([struct timespec, clockid_t], [], [], [[#include <time.h>]])
126
AC_SEARCH_LIBS([clock_gettime], [rt posix4])
127
AC_CHECK_FUNCS([clock_gettime])
128
AC_CHECK_FUNCS([sched_setscheduler sched_get_priority_min sched_get_priority_max nice])
129
+AC_CHECK_FUNCS([recvmmsg])
130
131
AC_TYPE_INT8_T
132
AC_TYPE_INT16_T
src/socket.c
+62
-6
@@ -851,11 +851,62 @@ static inline void poll_close_fd(struct poll *p, struct pollinfo *pi) {
851
debug(D_POLLFD, "POLLFD: DEL: completed, slots = %zu, used = %zu, min = %zu, max = %zu, next free = %zd", p->slots, p->used, p->min, p->max, p->first_free?(ssize_t)p->first_free->slot:(ssize_t)-1);
852
}
853
854
+static void *add_callback_default(int fd, short int *events) {
855
+ (void)fd;
856
+ (void)events;
857
+
858
+ return NULL;
859
+}
860
+static void del_callback_default(int fd, void *data) {
861
+ (void)fd;
862
+ (void)data;
863
+
864
+ if(data)
865
+ error("POLLFD: internal error: del_callback_default() called with data pointer - possible memory leak");
866
+}
867
+
868
+static int rcv_callback_default(int fd, int socktype, void *data, short int *events) {
869
+ (void)socktype;
870
+ (void)data;
871
+ (void)events;
872
+
873
+ char buffer[1024 + 1];
874
+
875
+ ssize_t rc;
876
+ do {
877
+ rc = recv(fd, buffer, 1024, MSG_DONTWAIT);
878
+ if (rc < 0) {
879
+ // read failed
880
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
881
+ error("POLLFD: recv() failed.");
882
+ return -1;
883
+ }
884
+ } else if (rc) {
885
+ // data received
886
+ info("POLLFD: internal error: discarding %zd bytes received on socket %d", rc, fd);
887
+ }
888
+ } while (rc != -1);
889
+
890
+ return 0;
891
+}
892
+
893
+static int snd_callback_default(int fd, int socktype, void *data, short int *events) {
894
+ (void)socktype;
895
+ (void)data;
896
+ (void)events;
897
+
898
+ *events &= ~POLLOUT;
899
+
900
+ info("POLLFD: internal error: nothing to send on socket %d", fd);
901
+ return 0;
902
+}
903
+
904
void poll_events(LISTEN_SOCKETS *sockets
905
, void *(*add_callback)(int fd, short int *events)
906
, void (*del_callback)(int fd, void *data)
907
, int (*rcv_callback)(int fd, int socktype, void *data, short int *events)
908
, int (*snd_callback)(int fd, int socktype, void *data, short int *events)
909
+ , void *data
910
) {
911
int retval;
912
@@ -867,15 +918,16 @@ void poll_events(LISTEN_SOCKETS *sockets
918
.inf = NULL,
919
.first_free = NULL,
920
870
- .add_callback = add_callback,
871
- .del_callback = del_callback,
872
- .rcv_callback = rcv_callback,
873
- .snd_callback = snd_callback
921
+ .add_callback = add_callback?add_callback:add_callback_default,
922
+ .del_callback = del_callback?del_callback:del_callback_default,
923
+ .rcv_callback = rcv_callback?rcv_callback:rcv_callback_default,
924
+ .snd_callback = snd_callback?snd_callback:snd_callback_default
925
};
926
927
size_t i;
928
for(i = 0; i < sockets->opened ;i++) {
878
- poll_add_fd(&p, sockets->fds[i], sockets->fds_types[i], POLLIN, POLLINFO_FLAG_SERVER_SOCKET);
929
+ struct pollinfo *pi = poll_add_fd(&p, sockets->fds[i], sockets->fds_types[i], POLLIN, POLLINFO_FLAG_SERVER_SOCKET);
930
+ pi->data = data;
931
info("POLLFD: LISTENER: listening on '%s'", (sockets->fds_names[i])?sockets->fds_names[i]:"UNKNOWN");
932
}
933
@@ -1008,7 +1060,11 @@ void poll_events(LISTEN_SOCKETS *sockets
1060
}
1061
}
1062
1063
+ for(i = 0 ; i <= p.max ; i++) {
1064
+ struct pollinfo *pi = &p.inf[i];
1065
+ poll_close_fd(&p, pi);
1066
+ }
1067
+
1068
freez(p.fds);
1069
freez(p.inf);
1070
}
1014
-
src/socket.h
+1
@@ -48,6 +48,7 @@ extern void poll_events(LISTEN_SOCKETS *sockets
48
, void (*del_callback)(int fd, void *data)
49
, int (*rcv_callback)(int fd, int socktype, void *data, short int *events)
50
, int (*snd_callback)(int fd, int socktype, void *data, short int *events)
51
+ , void *data
52
);
53
54
#endif //NETDATA_SOCKET_H
src/statsd.c
+218
-27
@@ -5,6 +5,7 @@
5
// #define STATSD_MULTITHREADED 1
6
7
#ifdef STATSD_MULTITHREADED
8
+// DO NOT ENABLE MULTITHREADING - IT IS NOT WELL TESTED
9
#define STATSD_AVL_TREE avl_tree_lock
10
#define STATSD_AVL_INSERT avl_insert_lock
11
#define STATSD_AVL_SEARCH avl_search_lock
@@ -132,7 +133,14 @@ static struct statsd {
133
STATSD_INDEX histograms;
134
STATSD_INDEX meters;
135
STATSD_INDEX sets;
135
- size_t unknown;
136
+ size_t unknown_types;
137
+ size_t socket_errors;
138
+ size_t tcp_socket_reads;
139
+ size_t tcp_packets_received;
140
+ size_t tcp_bytes_read;
141
+ size_t udp_socket_reads;
142
+ size_t udp_packets_received;
143
+ size_t udp_bytes_read;
144
145
int enabled;
146
int update_every;
@@ -144,6 +152,7 @@ static struct statsd {
152
RRD_MEMORY_MODE private_charts_memory_mode;
153
int private_charts_history;
154
155
+ size_t recvmmsg_size;
156
size_t histogram_increase_step;
157
double histogram_percentile;
158
char *histogram_percentile_str;
@@ -151,10 +160,9 @@ static struct statsd {
160
LISTEN_SOCKETS sockets;
161
} statsd = {
162
.enabled = 1,
154
- .private_charts = 0,
163
.max_private_charts = 200,
164
.max_private_charts_hard = 1000,
157
- .unknown = 0,
165
+ .recvmmsg_size = 10,
166
167
.gauges = {
168
.name = "gauge",
@@ -450,7 +458,7 @@ static void statsd_process_metric(const char *name, const char *value, const cha
458
statsd_find_or_add_metric(&statsd.meters, name),
459
value, sampling);
460
else
453
- statsd.unknown++;
461
+ statsd.unknown_types++;
462
break;
463
464
case 'h':
@@ -466,7 +474,7 @@ static void statsd_process_metric(const char *name, const char *value, const cha
474
break;
475
476
default:
469
- statsd.unknown++;
477
+ statsd.unknown_types++;
478
break;
479
}
480
}
@@ -586,21 +594,42 @@ static inline size_t statsd_process(char *buffer, size_t size, int require_newli
594
// --------------------------------------------------------------------------------------------------------------------
595
// statsd pollfd interface
596
589
-#define STATSD_TCP_BUFFER_SIZE 16384 // minimize reads
590
-#define STATSD_UDP_BUFFER_SIZE 1500 // this should be up to MTU
597
+#define STATSD_TCP_BUFFER_SIZE 65536 // minimize tcp reads
598
+#define STATSD_UDP_BUFFER_SIZE 9000 // this should be up to MTU
599
+
600
+typedef enum {
601
+ STATSD_SOCKET_DATA_TYPE_TCP,
602
+ STATSD_SOCKET_DATA_TYPE_UDP
603
+} STATSD_SOCKET_DATA_TYPE;
604
605
struct statsd_tcp {
606
+ STATSD_SOCKET_DATA_TYPE type;
607
size_t size;
608
size_t len;
609
char buffer[];
610
};
611
612
+#ifdef HAVE_RECVMMSG
613
+struct statsd_udp {
614
+ STATSD_SOCKET_DATA_TYPE type;
615
+ size_t size;
616
+ struct iovec *iovecs;
617
+ struct mmsghdr *msgs;
618
+};
619
+#else
620
+struct statsd_udp {
621
+ STATSD_SOCKET_DATA_TYPE type;
622
+ char buffer[STATSD_UDP_BUFFER_SIZE];
623
+};
624
+#endif
625
+
626
// new TCP client connected
627
static void *statsd_add_callback(int fd, short int *events) {
628
(void)fd;
629
*events = POLLIN;
630
631
struct statsd_tcp *data = (struct statsd_tcp *)callocz(sizeof(struct statsd_tcp) + STATSD_TCP_BUFFER_SIZE, 1);
632
+ data->type = STATSD_SOCKET_DATA_TYPE_TCP;
633
data->size = STATSD_TCP_BUFFER_SIZE - 1;
634
635
return data;
@@ -610,29 +639,49 @@ static void *statsd_add_callback(int fd, short int *events) {
639
static void statsd_del_callback(int fd, void *data) {
640
(void)fd;
641
613
- freez(data);
642
+ if(data) {
643
+ 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);
646
+
647
+ freez(data);
648
+ }
649
650
return;
651
}
652
653
// Receive data
654
static int statsd_rcv_callback(int fd, int socktype, void *data, short int *events) {
655
+ *events = POLLIN;
656
+
657
switch(socktype) {
658
case SOCK_STREAM: {
659
struct statsd_tcp *d = (struct statsd_tcp *)data;
660
if(unlikely(!d)) {
624
- error("STATSD: internal error - tcp receive buffer is null");
661
+ error("STATSD: internal error: expected TCP data pointer is NULL");
662
+ statsd.socket_errors++;
663
return -1;
664
}
665
666
+#ifdef NETDATA_INTERNAL_CHECKS
667
+ if(unlikely(d->type != STATSD_SOCKET_DATA_TYPE_UDP)) {
668
+ error("STATSD: internal error: socket data should be %d, but it is %d", (int)d->type, (int)STATSD_SOCKET_DATA_TYPE_TCP);
669
+ statsd.socket_errors++;
670
+ return -1;
671
+ }
672
+#endif
673
+
674
int ret = 0;
675
ssize_t rc;
676
do {
677
rc = recv(fd, &d->buffer[d->len], d->size - d->len, MSG_DONTWAIT);
678
if (rc < 0) {
679
// read failed
634
- if (errno != EWOULDBLOCK && errno != EAGAIN)
680
+ if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) {
681
+ error("STATSD: recv() on TCP socket %d failed.", fd);
682
+ statsd.socket_errors++;
683
ret = -1;
684
+ }
685
}
686
else if (!rc) {
687
// connection closed
@@ -642,10 +691,14 @@ static int statsd_rcv_callback(int fd, int socktype, void *data, short int *even
691
else {
692
// data received
693
d->len += rc;
694
+ statsd.tcp_socket_reads++;
695
+ statsd.tcp_bytes_read += rc;
696
}
697
647
- if(likely(d->len > 0))
698
+ if(likely(d->len > 0)) {
699
+ statsd.tcp_packets_received++;
700
d->len = statsd_process(d->buffer, d->len, 1);
701
+ }
702
703
if(unlikely(ret == -1))
704
return -1;
@@ -655,33 +708,77 @@ static int statsd_rcv_callback(int fd, int socktype, void *data, short int *even
708
}
709
710
case SOCK_DGRAM: {
658
- char buffer[STATSD_UDP_BUFFER_SIZE + 1];
711
+ struct statsd_udp *d = (struct statsd_udp *)data;
712
+ if(unlikely(!d)) {
713
+ error("STATSD: internal error: expected UDP data pointer is NULL");
714
+ statsd.socket_errors++;
715
+ return -1;
716
+ }
717
718
+#ifdef NETDATA_INTERNAL_CHECKS
719
+ if(unlikely(d->type != STATSD_SOCKET_DATA_TYPE_UDP)) {
720
+ error("STATSD: internal error: socket data should be %d, but it is %d", (int)d->type, (int)STATSD_SOCKET_DATA_TYPE_UDP);
721
+ statsd.socket_errors++;
722
+ return -1;
723
+ }
724
+#endif
725
+
726
+#ifdef HAVE_RECVMMSG
727
+ ssize_t rc;
728
+ do {
729
+ rc = recvmmsg(fd, d->msgs, (unsigned int)d->size, MSG_DONTWAIT, NULL);
730
+ if (rc < 0) {
731
+ // read failed
732
+ if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) {
733
+ error("STATSD: recvmmsg() on UDP socket %d failed.", fd);
734
+ statsd.socket_errors++;
735
+ return -1;
736
+ }
737
+ } else if (rc) {
738
+ // data received
739
+ statsd.udp_socket_reads++;
740
+ statsd.udp_packets_received += rc;
741
+
742
+ size_t i;
743
+ for (i = 0; i < (size_t)rc; ++i) {
744
+ size_t len = (size_t)d->msgs[i].msg_len;
745
+ statsd.udp_bytes_read += len;
746
+ statsd_process(d->msgs[i].msg_hdr.msg_iov->iov_base, len, 0);
747
+ }
748
+ }
749
+ } while (rc != -1);
750
+
751
+#else // !HAVE_RECVMMSG
752
ssize_t rc;
753
do {
662
- // FIXME: collect sender information
663
- rc = recvfrom(fd, buffer, STATSD_UDP_BUFFER_SIZE, MSG_DONTWAIT, NULL, NULL);
754
+ rc = recv(fd, d->buffer, STATSD_UDP_BUFFER_SIZE, MSG_DONTWAIT);
755
if (rc < 0) {
756
// read failed
666
- if (errno != EWOULDBLOCK && errno != EAGAIN) {
667
- error("STATSD: recvfrom() failed.");
757
+ if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) {
758
+ error("STATSD: recv() on UDP socket %d failed.", fd);
759
+ statsd.errors++;
760
return -1;
761
}
762
} else if (rc) {
763
// data received
672
- statsd_process(buffer, (size_t) rc, 0);
764
+ statsd.udp_socket_reads++;
765
+ statsd.udp_packets_received++;
766
+ statsd.udp_bytes_read += rc;
767
+ statsd_process(d->buffer, (size_t) rc, 0);
768
}
769
} while (rc != -1);
770
+#endif
771
+
772
break;
773
}
774
775
default: {
679
- error("STATSD: unknown socktype %d on socket %d", socktype, fd);
776
+ error("STATSD: internal error: unknown socktype %d on socket %d", socktype, fd);
777
+ statsd.socket_errors++;
778
return -1;
779
}
780
}
781
684
- *events = POLLIN;
782
return 0;
783
}
784
@@ -709,13 +806,41 @@ void *statsd_collector_thread(void *ptr) {
806
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
807
error("Cannot set pthread cancel state to ENABLE.");
808
809
+ struct statsd_udp *d = callocz(sizeof(struct statsd_udp), 1);
810
+
811
+#ifdef HAVE_RECVMMSG
812
+ d->type = STATSD_SOCKET_DATA_TYPE_UDP;
813
+ d->size = statsd.recvmmsg_size;
814
+ d->iovecs = callocz(sizeof(struct iovec), d->size);
815
+ d->msgs = callocz(sizeof(struct mmsghdr), d->size);
816
+
817
+ size_t i;
818
+ for (i = 0; i < d->size; i++) {
819
+ d->iovecs[i].iov_base = mallocz(STATSD_UDP_BUFFER_SIZE);
820
+ d->iovecs[i].iov_len = STATSD_UDP_BUFFER_SIZE - 1;
821
+ d->msgs[i].msg_hdr.msg_iov = &d->iovecs[i];
822
+ d->msgs[i].msg_hdr.msg_iovlen = 1;
823
+ }
824
+#endif
825
+
826
poll_events(&statsd.sockets
827
, statsd_add_callback
828
, statsd_del_callback
829
, statsd_rcv_callback
830
, statsd_snd_callback
831
+ , (void *)d
832
);
833
834
+#ifdef HAVE_RECVMMSG
835
+ for (i = 0; i < d->size; i++)
836
+ freez(d->iovecs[i].iov_base);
837
+
838
+ freez(d->iovecs);
839
+ freez(d->msgs);
840
+#endif
841
+
842
+ freez(d);
843
+
844
debug(D_WEB_CLIENT, "STATSD: exit!");
845
listen_sockets_close(&statsd.sockets);
846
@@ -1044,6 +1169,10 @@ void *statsd_main(void *ptr) {
1169
statsd.update_every = default_rrd_update_every;
1170
}
1171
1172
+#ifdef HAVE_RECVMMSG
1173
+ statsd.recvmmsg_size = (size_t)config_get_number(CONFIG_SECTION_STATSD, "udp messages to process at once", (long long)statsd.recvmmsg_size);
1174
+#endif
1175
+
1176
statsd.charts_for = simple_pattern_create(config_get(CONFIG_SECTION_STATSD, "create private charts for metrics matching", "*"), SIMPLE_PATTERN_EXACT);
1177
statsd.max_private_charts = (size_t)config_get_number(CONFIG_SECTION_STATSD, "max private charts allowed", (long long)statsd.max_private_charts);
1178
statsd.max_private_charts_hard = (size_t)config_get_number(CONFIG_SECTION_STATSD, "max private charts hard limit", (long long)statsd.max_private_charts * 5);
@@ -1154,6 +1283,52 @@ void *statsd_main(void *ptr) {
1283
RRDDIM *rd_events_histogram = rrddim_add(st_events, "histograms", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1284
RRDDIM *rd_events_set = rrddim_add(st_events, "sets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1285
RRDDIM *rd_events_unknown = rrddim_add(st_events, "unknown", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1286
+ RRDDIM *rd_events_errors = rrddim_add(st_events, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1287
+
1288
+ RRDSET *st_reads = rrdset_create_localhost(
1289
+ "netdata"
1290
+ , "statsd_reads"
1291
+ , NULL
1292
+ , "statsd"
1293
+ , NULL
1294
+ , "Read operations made by the netdata statsd server"
1295
+ , "reads/s"
1296
+ , 132002
1297
+ , statsd.update_every
1298
+ , RRDSET_TYPE_STACKED
1299
+ );
1300
+ RRDDIM *rd_reads_tcp = rrddim_add(st_reads, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1301
+ RRDDIM *rd_reads_udp = rrddim_add(st_reads, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1302
+
1303
+ RRDSET *st_bytes = rrdset_create_localhost(
1304
+ "netdata"
1305
+ , "statsd_bytes"
1306
+ , NULL
1307
+ , "statsd"
1308
+ , NULL
1309
+ , "Bytes read by the netdata statsd server"
1310
+ , "kbps"
1311
+ , 132003
1312
+ , statsd.update_every
1313
+ , RRDSET_TYPE_STACKED
1314
+ );
1315
+ RRDDIM *rd_bytes_tcp = rrddim_add(st_bytes, "tcp", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL);
1316
+ RRDDIM *rd_bytes_udp = rrddim_add(st_bytes, "udp", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL);
1317
+
1318
+ RRDSET *st_packets = rrdset_create_localhost(
1319
+ "netdata"
1320
+ , "statsd_packets"
1321
+ , NULL
1322
+ , "statsd"
1323
+ , NULL
1324
+ , "Network packets processed by the netdata statsd server"
1325
+ , "packets/s"
1326
+ , 132004
1327
+ , statsd.update_every
1328
+ , RRDSET_TYPE_STACKED
1329
+ );
1330
+ RRDDIM *rd_packets_tcp = rrddim_add(st_packets, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1331
+ RRDDIM *rd_packets_udp = rrddim_add(st_packets, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1332
1333
RRDSET *st_pcharts = rrdset_create_localhost(
1334
"netdata"
@@ -1163,7 +1338,7 @@ void *statsd_main(void *ptr) {
1338
, NULL
1339
, "Private metric charts created by the netdata statsd server"
1340
, "charts"
1166
- , 132002
1341
+ , 132010
1342
, statsd.update_every
1343
, RRDSET_TYPE_AREA
1344
);
@@ -1191,6 +1366,9 @@ void *statsd_main(void *ptr) {
1366
if(hb_dt) {
1367
rrdset_next(st_metrics);
1368
rrdset_next(st_events);
1369
+ rrdset_next(st_reads);
1370
+ rrdset_next(st_bytes);
1371
+ rrdset_next(st_packets);
1372
rrdset_next(st_pcharts);
1373
}
1374
@@ -1201,13 +1379,23 @@ void *statsd_main(void *ptr) {
1379
rrddim_set_by_pointer(st_metrics, rd_metrics_histogram, (collected_number)statsd.histograms.metrics);
1380
rrddim_set_by_pointer(st_metrics, rd_metrics_set, (collected_number)statsd.sets.metrics);
1381
1204
- rrddim_set_by_pointer(st_events, rd_events_gauge, (collected_number)statsd.gauges.events);
1205
- rrddim_set_by_pointer(st_events, rd_events_counter, (collected_number)statsd.counters.events);
1206
- rrddim_set_by_pointer(st_events, rd_events_timer, (collected_number)statsd.timers.events);
1207
- rrddim_set_by_pointer(st_events, rd_events_meter, (collected_number)statsd.meters.events);
1208
- rrddim_set_by_pointer(st_events, rd_events_histogram, (collected_number)statsd.histograms.events);
1209
- rrddim_set_by_pointer(st_events, rd_events_set, (collected_number)statsd.sets.events);
1210
- rrddim_set_by_pointer(st_events, rd_events_unknown, (collected_number)statsd.unknown);
1382
+ rrddim_set_by_pointer(st_events, rd_events_gauge, (collected_number)statsd.gauges.events);
1383
+ rrddim_set_by_pointer(st_events, rd_events_counter, (collected_number)statsd.counters.events);
1384
+ rrddim_set_by_pointer(st_events, rd_events_timer, (collected_number)statsd.timers.events);
1385
+ rrddim_set_by_pointer(st_events, rd_events_meter, (collected_number)statsd.meters.events);
1386
+ rrddim_set_by_pointer(st_events, rd_events_histogram, (collected_number)statsd.histograms.events);
1387
+ rrddim_set_by_pointer(st_events, rd_events_set, (collected_number)statsd.sets.events);
1388
+ rrddim_set_by_pointer(st_events, rd_events_unknown, (collected_number)statsd.unknown_types);
1389
+ rrddim_set_by_pointer(st_events, rd_events_errors, (collected_number)statsd.socket_errors);
1390
+
1391
+ rrddim_set_by_pointer(st_reads, rd_reads_tcp, (collected_number)statsd.tcp_socket_reads);
1392
+ rrddim_set_by_pointer(st_reads, rd_reads_udp, (collected_number)statsd.udp_socket_reads);
1393
+
1394
+ rrddim_set_by_pointer(st_bytes, rd_bytes_tcp, (collected_number)statsd.tcp_bytes_read);
1395
+ rrddim_set_by_pointer(st_bytes, rd_bytes_udp, (collected_number)statsd.udp_bytes_read);
1396
+
1397
+ rrddim_set_by_pointer(st_packets, rd_packets_tcp, (collected_number)statsd.tcp_packets_received);
1398
+ rrddim_set_by_pointer(st_packets, rd_packets_udp, (collected_number)statsd.udp_packets_received);
1399
1400
rrddim_set_by_pointer(st_pcharts, rd_pcharts, (collected_number)statsd.private_charts);
1401
@@ -1216,6 +1404,9 @@ void *statsd_main(void *ptr) {
1404
1405
rrdset_done(st_metrics);
1406
rrdset_done(st_events);
1407
+ rrdset_done(st_reads);
1408
+ rrdset_done(st_bytes);
1409
+ rrdset_done(st_packets);
1410
rrdset_done(st_pcharts);
1411
1412
if(unlikely(netdata_exit))