diff options
author | Federico Ceratto <federico.ceratto@gmail.com> | 2017-12-19 23:39:27 +0000 |
---|---|---|
committer | Federico Ceratto <federico.ceratto@gmail.com> | 2017-12-19 23:39:27 +0000 |
commit | 6abdfdead1326ccca98dc4cf415c216f1bf25400 (patch) | |
tree | 70b803bd499fd45e89627c1b45b90ddf20e8e959 /src | |
parent | Release v. 1.8.0+dfsg-1 to Unstable (diff) | |
parent | New upstream version 1.9.0+dfsg (diff) | |
download | netdata-6abdfdead1326ccca98dc4cf415c216f1bf25400.tar.xz netdata-6abdfdead1326ccca98dc4cf415c216f1bf25400.zip |
Update upstream source from tag 'upstream/1.9.0+dfsg'
Update to upstream version '1.9.0+dfsg'
with Debian dir 28b8242a05f9ad26cd1cdbcf078be754fc7d6251
Diffstat (limited to 'src')
103 files changed, 9269 insertions, 3786 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index feddc326..1a1d3748 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -137,7 +137,8 @@ netdata_SOURCES = \ sys_devices_system_node.c \ unit_test.c \ unit_test.h \ - url.c url.h \ + url.c \ + url.h \ web_api_old.c \ web_api_old.h \ web_api_v1.c \ @@ -176,7 +177,8 @@ netdata_SOURCES += \ $(NULL) else netdata_SOURCES += \ - ipc.c ipc.h \ + ipc.c \ + ipc.h \ plugin_proc.c \ plugin_proc.h \ plugin_proc_diskspace.c \ @@ -193,6 +195,8 @@ netdata_SOURCES += \ proc_net_rpc_nfsd.c \ proc_net_snmp.c \ proc_net_snmp6.c \ + proc_net_sockstat.c \ + proc_net_sockstat6.c \ proc_net_softnet_stat.c \ proc_net_stat_conntrack.c \ proc_net_stat_synproxy.c \ @@ -258,6 +262,8 @@ cgroup_network_SOURCES = \ inlined.h \ log.c log.h \ procfile.c procfile.h \ + popen.c popen.h \ + signals.c signals.h \ $(NULL) cgroup_network_LDADD = \ diff --git a/src/Makefile.in b/src/Makefile.in index bc73c712..bf902c21 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -106,7 +106,8 @@ plugins_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) @FREEBSD_FALSE@@MACOS_TRUE@ $(NULL) @FREEBSD_FALSE@@MACOS_FALSE@am__append_6 = \ -@FREEBSD_FALSE@@MACOS_FALSE@ ipc.c ipc.h \ +@FREEBSD_FALSE@@MACOS_FALSE@ ipc.c \ +@FREEBSD_FALSE@@MACOS_FALSE@ ipc.h \ @FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.c \ @FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.h \ @FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc_diskspace.c \ @@ -123,6 +124,8 @@ plugins_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfsd.c \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp.c \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp6.c \ +@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat.c \ +@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat6.c \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_softnet_stat.c \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_conntrack.c \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_synproxy.c \ @@ -179,7 +182,8 @@ apps_plugin_OBJECTS = $(am_apps_plugin_OBJECTS) am__DEPENDENCIES_1 = apps_plugin_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cgroup_network_OBJECTS = cgroup-network.$(OBJEXT) clocks.$(OBJEXT) \ - common.$(OBJEXT) log.$(OBJEXT) procfile.$(OBJEXT) + common.$(OBJEXT) log.$(OBJEXT) procfile.$(OBJEXT) \ + popen.$(OBJEXT) signals.$(OBJEXT) cgroup_network_OBJECTS = $(am_cgroup_network_OBJECTS) cgroup_network_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) @@ -224,6 +228,7 @@ am__netdata_SOURCES_DIST = adaptive_resortable_list.c \ proc_loadavg.c proc_meminfo.c proc_net_dev.c \ proc_net_ip_vs_stats.c proc_net_netstat.c proc_net_rpc_nfs.c \ proc_net_rpc_nfsd.c proc_net_snmp.c proc_net_snmp6.c \ + proc_net_sockstat.c proc_net_sockstat6.c \ proc_net_softnet_stat.c proc_net_stat_conntrack.c \ proc_net_stat_synproxy.c proc_spl_kstat_zfs.c proc_stat.c \ proc_sys_kernel_random_entropy_avail.c proc_vmstat.c \ @@ -254,6 +259,8 @@ am__netdata_SOURCES_DIST = adaptive_resortable_list.c \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfsd.$(OBJEXT) \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp.$(OBJEXT) \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp6.$(OBJEXT) \ +@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat.$(OBJEXT) \ +@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat6.$(OBJEXT) \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_softnet_stat.$(OBJEXT) \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_conntrack.$(OBJEXT) \ @FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_synproxy.$(OBJEXT) \ @@ -616,6 +623,8 @@ cgroup_network_SOURCES = \ inlined.h \ log.c log.h \ procfile.c procfile.h \ + popen.c popen.h \ + signals.c signals.h \ $(NULL) cgroup_network_LDADD = \ @@ -815,6 +824,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_rpc_nfsd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_snmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_snmp6.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_sockstat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_sockstat6.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_softnet_stat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_stat_conntrack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_stat_synproxy.Po@am__quote@ diff --git a/src/adaptive_resortable_list.c b/src/adaptive_resortable_list.c index f74c53ea..add1d8c9 100644 --- a/src/adaptive_resortable_list.c +++ b/src/adaptive_resortable_list.c @@ -2,7 +2,7 @@ // the default processor() of the ARL // can be overwritten at arl_create() -static inline void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst) { +inline void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst) { (void)name; (void)hash; @@ -11,6 +11,15 @@ static inline void arl_callback_str2ull(const char *name, uint32_t hash, const c // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, *d); } +inline void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; + (void)hash; + + register kernel_uint_t *d = dst; + *d = str2kernel_uint_t(value); + // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, (unsigned long long)*d); +} + // create a new ARL ARL_BASE *arl_create(const char *name, void (*processor)(const char *, uint32_t, const char *, void *), size_t rechecks) { ARL_BASE *base = callocz(1, sizeof(ARL_BASE)); diff --git a/src/adaptive_resortable_list.h b/src/adaptive_resortable_list.h index 609cd0c4..c007fa31 100644 --- a/src/adaptive_resortable_list.h +++ b/src/adaptive_resortable_list.h @@ -110,6 +110,9 @@ extern int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const ch // begin an ARL iteration extern void arl_begin(ARL_BASE *base); +extern void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst); +extern void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, const char *value, void *dst); + // check a keyword against the ARL // this is to be called for each keyword read from source data // s = the keyword, as collected diff --git a/src/appconfig.c b/src/appconfig.c index 2c7721b8..40cade81 100644 --- a/src/appconfig.c +++ b/src/appconfig.c @@ -567,6 +567,7 @@ void appconfig_generate(struct config *root, BUFFER *wb, int only_changed) else pri = 2; if(i == pri) { + int loaded = 0; int used = 0; int changed = 0; int count = 0; @@ -574,13 +575,14 @@ void appconfig_generate(struct config *root, BUFFER *wb, int only_changed) config_section_wrlock(co); for(cv = co->values; cv ; cv = cv->next) { used += (cv->flags & CONFIG_VALUE_USED)?1:0; + loaded += (cv->flags & CONFIG_VALUE_LOADED)?1:0; changed += (cv->flags & CONFIG_VALUE_CHANGED)?1:0; count++; } config_section_unlock(co); if(!count) continue; - if(only_changed && !changed) continue; + if(only_changed && !changed && !loaded) continue; if(!used) { buffer_sprintf(wb, "\n# section '%s' is not used.", co->name); @@ -594,7 +596,7 @@ void appconfig_generate(struct config *root, BUFFER *wb, int only_changed) if(used && !(cv->flags & CONFIG_VALUE_USED)) { buffer_sprintf(wb, "\n\t# option '%s' is not used.\n", cv->name); } - buffer_sprintf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value); + buffer_sprintf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_LOADED)) && (!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value); } config_section_unlock(co); } diff --git a/src/apps_plugin.c b/src/apps_plugin.c index c0eb5c08..3ac79777 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -1572,14 +1572,22 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) { break; default: /* print protocol number and socket address */ +#if __FreeBSD_version < 1200031 sprintf(fdsname, "socket: other: %d %s %s", fds->kf_sock_protocol, fds->kf_sa_local.__ss_pad1, fds->kf_sa_local.__ss_pad2); +#else + sprintf(fdsname, "socket: other: %d %s %s", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sa_local.__ss_pad1, fds->kf_un.kf_sock.kf_sa_local.__ss_pad2); +#endif } break; case KF_TYPE_PIPE: sprintf(fdsname, "pipe: %lu %lu", fds->kf_un.kf_pipe.kf_pipe_addr, fds->kf_un.kf_pipe.kf_pipe_peer); break; case KF_TYPE_PTS: +#if __FreeBSD_version < 1200031 sprintf(fdsname, "other: pts: %u", fds->kf_un.kf_pts.kf_pts_dev); +#else + sprintf(fdsname, "other: pts: %lu", fds->kf_un.kf_pts.kf_pts_dev); +#endif break; case KF_TYPE_SHM: sprintf(fdsname, "other: shm: %s size: %lu", fds->kf_path, fds->kf_un.kf_file.kf_file_size); @@ -306,7 +306,10 @@ int avl_walker(avl *node, int (*callback)(void *entry, void *data), void *data) } int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *data) { - return avl_walker(t->root, callback, data); + if(t->root) + return avl_walker(t->root, callback, data); + else + return 0; } // --------------------------- diff --git a/src/backends.c b/src/backends.c index eed4ab40..df9a1ccb 100644 --- a/src/backends.c +++ b/src/backends.c @@ -615,18 +615,18 @@ void *backends_main(void *ptr) { chart_backend_reconnects = 0, chart_backend_latency = 0; - RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", 130600, backend_update_every, RRDSET_TYPE_LINE); + RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, backend_update_every, RRDSET_TYPE_LINE); rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", 130610, backend_update_every, RRDSET_TYPE_AREA); + RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, backend_update_every, RRDSET_TYPE_AREA); rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); - RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", 130630, backend_update_every, RRDSET_TYPE_LINE); + RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_LINE); rrddim_add(chart_ops, "write", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "discard", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -640,11 +640,11 @@ void *backends_main(void *ptr) { * * issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html * - RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", 130620, backend_update_every, RRDSET_TYPE_AREA); + RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, backend_update_every, RRDSET_TYPE_AREA); rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); */ - RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", 130630, backend_update_every, RRDSET_TYPE_STACKED); + RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_STACKED); rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); diff --git a/src/cgroup-network.c b/src/cgroup-network.c index 8894d60e..7b1a0234 100644 --- a/src/cgroup-network.c +++ b/src/cgroup-network.c @@ -1,4 +1,5 @@ #include "common.h" +#include <libgen.h> #ifdef HAVE_SETNS #ifndef _GNU_SOURCE @@ -14,6 +15,10 @@ void netdata_cleanup_and_exit(int ret) { exit(ret); } +void health_reload(void) {}; +void rrdhost_save_all(void) {}; + + struct iface { const char *device; uint32_t hash; @@ -269,38 +274,62 @@ pid_t read_pid_from_cgroup(const char *path) { return pid; } -void usage(void) { - fprintf(stderr, "%s [ -p PID | --pid PID | --cgroup /path/to/cgroup ]\n", program_name); - exit(1); -} -int main(int argc, char **argv) { - pid_t pid = 0; +// ---------------------------------------------------------------------------- +// send the result to netdata - program_name = argv[0]; - program_version = VERSION; - error_log_syslog = 0; +struct found_device { + const char *host_device; + const char *guest_device; - if(argc == 2 && (!strcmp(argv[1], "version") || !strcmp(argv[1], "-version") || !strcmp(argv[1], "--version") || !strcmp(argv[1], "-v") || !strcmp(argv[1], "-V"))) { - fprintf(stderr, "cgroup-network %s\n", VERSION); - exit(0); - } + uint32_t host_device_hash; - if(argc != 3) - usage(); + struct found_device *next; +} *detected_devices = NULL; - if(!strcmp(argv[1], "-p") || !strcmp(argv[1], "--pid")) { - pid = atoi(argv[2]); +void add_device(const char *host, const char *guest) { + uint32_t hash = simple_hash(host); + + if(guest && (!*guest || strcmp(host, guest) == 0)) + guest = NULL; + + struct found_device *f; + for(f = detected_devices; f ; f = f->next) { + if(f->host_device_hash == hash && strcmp(host, f->host_device) == 0) { + + if(guest && !f->guest_device) + f->guest_device = strdup(guest); + + return; + } } - else if(!strcmp(argv[1], "--cgroup")) { - pid = read_pid_from_cgroup(argv[2]); + + f = mallocz(sizeof(struct found_device)); + f->host_device = strdupz(host); + f->host_device_hash = hash; + f->guest_device = (guest)?strdupz(guest):NULL; + f->next = detected_devices; + detected_devices = f; +} + +int send_devices(void) { + int found = 0; + + struct found_device *f; + for(f = detected_devices; f ; f = f->next) { + found++; + printf("%s %s\n", f->host_device, (f->guest_device)?f->guest_device:f->host_device); } - else - usage(); - if(pid <= 0) - fatal("Invalid pid %d", (int)pid); + return found; +} + +// ---------------------------------------------------------------------------- +// this function should be called only **ONCE** +// also it has to be the **LAST** to be called +// since it switches namespaces, so after this call, everything is different! +void detect_veth_interfaces(pid_t pid) { struct iface *host, *cgroup, *h, *c; const char *prefix = getenv("NETDATA_HOST_PREFIX"); @@ -321,20 +350,117 @@ int main(int argc, char **argv) { if(!eligible_ifaces(cgroup)) fatal("there are not double-linked cgroup interfaces available."); - int found = 0; for(h = host; h ; h = h->next) { if(iface_is_eligible(h)) { for (c = cgroup; c; c = c->next) { if(iface_is_eligible(c) && h->ifindex == c->iflink && h->iflink == c->ifindex) { - printf("%s %s\n", h->device, c->device); - found++; + add_device(h->device, c->device); } } } } +} - if(!found) - return 1; +// ---------------------------------------------------------------------------- +// call the external helper - return 0; +#define CGROUP_NETWORK_INTERFACE_MAX_LINE 2048 +void call_the_helper(const char *me, pid_t pid, const char *cgroup) { + const char *pluginsdir = getenv("NETDATA_PLUGINS_DIR"); + char *m = NULL; + + if(!pluginsdir || !*pluginsdir) { + m = strdupz(me); + pluginsdir = dirname(m); + } + + if(setresuid(0, 0, 0) == -1) + error("setresuid(0, 0, 0) failed."); + + char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; + if(cgroup) + snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec %s/cgroup-network-helper.sh --cgroup '%s'", pluginsdir, cgroup); + else + snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec %s/cgroup-network-helper.sh --pid %d", pluginsdir, pid); + + info("running: %s", buffer); + + pid_t cgroup_pid; + FILE *fp = mypopen(buffer, &cgroup_pid); + if(fp) { + char *s; + while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) { + trim(s); + + if(*s && *s != '\n') { + char *t = s; + while(*t && *t != ' ') t++; + if(*t == ' ') { + *t = '\0'; + t++; + } + + if(!*s || !*t) continue; + add_device(s, t); + } + } + + mypclose(fp, cgroup_pid); + } + else + error("cannot execute cgroup-network helper script: %s", buffer); + + freez(m); +} + + +// ---------------------------------------------------------------------------- +// main + +void usage(void) { + fprintf(stderr, "%s [ -p PID | --pid PID | --cgroup /path/to/cgroup ]\n", program_name); + exit(1); +} + +int main(int argc, char **argv) { + pid_t pid = 0; + + program_name = argv[0]; + program_version = VERSION; + error_log_syslog = 0; + + if(argc == 2 && (!strcmp(argv[1], "version") || !strcmp(argv[1], "-version") || !strcmp(argv[1], "--version") || !strcmp(argv[1], "-v") || !strcmp(argv[1], "-V"))) { + fprintf(stderr, "cgroup-network %s\n", VERSION); + exit(0); + } + + if(argc != 3) + usage(); + + if(!strcmp(argv[1], "-p") || !strcmp(argv[1], "--pid")) { + pid = atoi(argv[2]); + + if(pid <= 0) { + errno = 0; + fatal("Invalid pid %d given", (int) pid); + } + + call_the_helper(argv[0], pid, NULL); + } + else if(!strcmp(argv[1], "--cgroup")) { + pid = read_pid_from_cgroup(argv[2]); + call_the_helper(argv[0], pid, argv[2]); + + if(pid <= 0 && !detected_devices) { + errno = 0; + fatal("Invalid pid %d read from cgroup '%s'", (int) pid, argv[2]); + } + } + else + usage(); + + if(pid > 0) + detect_veth_interfaces(pid); + + return send_devices(); } diff --git a/src/clocks.c b/src/clocks.c index 8f2aa740..2b1c36e3 100644 --- a/src/clocks.c +++ b/src/clocks.c @@ -115,8 +115,12 @@ usec_t heartbeat_next(heartbeat_t *hb, usec_t tick) if(likely(*hb != 0ULL)) { usec_t dt = now - *hb; *hb = now; - if(unlikely(dt >= tick + tick / 2)) + + if(unlikely(dt >= tick + tick / 2)) { + errno = 0; error("heartbeat missed %llu microseconds", dt - tick); + } + return dt; } else { diff --git a/src/common.c b/src/common.c index 5a953672..a976e96e 100644 --- a/src/common.c +++ b/src/common.c @@ -17,6 +17,7 @@ char *netdata_configured_cache_dir = NULL; char *netdata_configured_varlib_dir = NULL; char *netdata_configured_home_dir = NULL; char *netdata_configured_host_prefix = NULL; +char *netdata_configured_timezone = NULL; int enable_ksm = 1; @@ -1119,10 +1120,14 @@ pid_t gettid(void) { #ifdef __FreeBSD__ return (pid_t)pthread_getthreadid_np(); #elif defined(__APPLE__) +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) uint64_t curthreadid; pthread_threadid_np(NULL, &curthreadid); return (pid_t)curthreadid; -#else +#else /* __MAC_OS_X_VERSION_MIN_REQUIRED */ + return (pid_t)pthread_self; +#endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */ +#else /* __APPLE__*/ return (pid_t)syscall(SYS_gettid); #endif /* __FreeBSD__, __APPLE__*/ } diff --git a/src/common.h b/src/common.h index 51d2bba5..667fe9d7 100644 --- a/src/common.h +++ b/src/common.h @@ -203,10 +203,21 @@ #define NETDATA_OS_TYPE "linux" #endif /* __FreeBSD__, __APPLE__*/ -#include "statistical.h" -#include "socket.h" +typedef enum rrdcalc_status { + RRDCALC_STATUS_REMOVED = -2, + RRDCALC_STATUS_UNDEFINED = -1, + RRDCALC_STATUS_UNINITIALIZED = 0, + RRDCALC_STATUS_CLEAR = 1, + RRDCALC_STATUS_RAISED = 2, + RRDCALC_STATUS_WARNING = 3, + RRDCALC_STATUS_CRITICAL = 4 +} RRDCALC_STATUS; + #include "eval.h" #include "health.h" + +#include "statistical.h" +#include "socket.h" #include "rrd.h" #include "plugin_tc.h" #include "plugins_d.h" @@ -232,12 +243,14 @@ extern char *netdata_configured_hostname; extern char *netdata_configured_config_dir; extern char *netdata_configured_log_dir; +extern char *netdata_configured_plugins_dir_base; extern char *netdata_configured_plugins_dir; extern char *netdata_configured_web_dir; extern char *netdata_configured_cache_dir; extern char *netdata_configured_varlib_dir; extern char *netdata_configured_home_dir; extern char *netdata_configured_host_prefix; +extern char *netdata_configured_timezone; extern void netdata_fix_chart_id(char *s); extern void netdata_fix_chart_name(char *s); @@ -166,7 +166,7 @@ static inline calculated_number eval_variable(EVAL_EXPRESSION *exp, EVAL_VARIABL } if(exp->rrdcalc && health_variable_lookup(v->name, v->hash, exp->rrdcalc, &n)) { - buffer_sprintf(exp->error_msg, "[ $%s = ", v->name); + buffer_sprintf(exp->error_msg, "[ ${%s} = ", v->name); print_parsed_as_constant(exp->error_msg, n); buffer_strcat(exp->error_msg, " ] "); return n; @@ -232,7 +232,7 @@ calculated_number eval_equal(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) { if(isinf(n1) && isinf(n2)) return 1; if(isnan(n1) || isnan(n2)) return 0; if(isinf(n1) || isinf(n2)) return 0; - return n1 == n2; + return calculated_number_equal(n1, n2); } calculated_number eval_not_equal(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) { return !eval_equal(exp, op, error); @@ -355,7 +355,7 @@ static inline calculated_number eval_node(EVAL_EXPRESSION *exp, EVAL_NODE *op, i static inline void print_parsed_as_variable(BUFFER *out, EVAL_VARIABLE *v, int *error) { (void)error; - buffer_sprintf(out, "$%s", v->name); + buffer_sprintf(out, "${%s}", v->name); } static inline void print_parsed_as_constant(BUFFER *out, calculated_number n) { @@ -703,17 +703,31 @@ static inline int parse_variable(const char **string, char *buffer, size_t len) const char *s = *string; // $ - if(s[0] == '$') { + if(*s == '$') { size_t i = 0; s++; - while(*s && !isvariableterm(*s) && i < len) - buffer[i++] = *s++; + if(*s == '{') { + // ${variable_name} + + s++; + while (*s && *s != '}' && i < len) + buffer[i++] = *s++; + + if(*s == '}') + s++; + } + else { + // $variable_name + + while (*s && !isvariableterm(*s) && i < len) + buffer[i++] = *s++; + } buffer[i] = '\0'; - if(buffer[0]) { - *string = &s[0]; + if (buffer[0]) { + *string = s; return 1; } } @@ -14,7 +14,7 @@ typedef struct eval_expression { const char *source; const char *parsed_as; - int *status; + RRDCALC_STATUS *status; calculated_number *this; time_t *after; time_t *before; diff --git a/src/freebsd_devstat.c b/src/freebsd_devstat.c index 5b0687d5..2ed64ad4 100644 --- a/src/freebsd_devstat.c +++ b/src/freebsd_devstat.c @@ -27,10 +27,15 @@ struct disk { struct prev_dstat { collected_number bytes_read; collected_number bytes_write; + collected_number bytes_free; collected_number operations_read; collected_number operations_write; + collected_number operations_other; + collected_number operations_free; collected_number duration_read_ms; collected_number duration_write_ms; + collected_number duration_other_ms; + collected_number duration_free_ms; collected_number busy_time_ms; } prev_dstat; @@ -39,10 +44,13 @@ struct disk { RRDSET *st_io; RRDDIM *rd_io_in; RRDDIM *rd_io_out; + RRDDIM *rd_io_free; RRDSET *st_ops; RRDDIM *rd_ops_in; RRDDIM *rd_ops_out; + RRDDIM *rd_ops_other; + RRDDIM *rd_ops_free; RRDSET *st_qops; RRDDIM *rd_qops; @@ -53,14 +61,19 @@ struct disk { RRDSET *st_iotime; RRDDIM *rd_iotime_in; RRDDIM *rd_iotime_out; + RRDDIM *rd_iotime_other; + RRDDIM *rd_iotime_free; RRDSET *st_await; RRDDIM *rd_await_in; RRDDIM *rd_await_out; + RRDDIM *rd_await_other; + RRDDIM *rd_await_free; RRDSET *st_avagsz; RRDDIM *rd_avagsz_in; RRDDIM *rd_avagsz_out; + RRDDIM *rd_avagsz_free; RRDSET *st_svctm; RRDDIM *rd_svctm; @@ -244,7 +257,8 @@ int do_kern_devstat(int update_every, usec_t dt) { for (i = 0; i < numdevs; i++) { if (likely(do_system_io)) { - if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) { + if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || + ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) { total_disk_kbytes_read += dstat[i].bytes[DEVSTAT_READ] / KILO_FACTOR; total_disk_kbytes_write += dstat[i].bytes[DEVSTAT_WRITE] / KILO_FACTOR; } @@ -254,11 +268,14 @@ int do_kern_devstat(int update_every, usec_t dt) { if ((dstat[i].device_type & DEVSTAT_TYPE_PASS) == DEVSTAT_TYPE_PASS) continue; - if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) { + if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || + ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) { char disk[DEVSTAT_NAME_LEN + MAX_INT_DIGITS + 1]; struct cur_dstat { collected_number duration_read_ms; collected_number duration_write_ms; + collected_number duration_other_ms; + collected_number duration_free_ms; collected_number busy_time_ms; } cur_dstat; @@ -299,12 +316,19 @@ int do_kern_devstat(int update_every, usec_t dt) { dm->prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ]; dm->prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE]; + dm->prev_dstat.bytes_free = dstat[i].bytes[DEVSTAT_FREE]; dm->prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ]; dm->prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE]; + dm->prev_dstat.operations_other = dstat[i].operations[DEVSTAT_NO_DATA]; + dm->prev_dstat.operations_free = dstat[i].operations[DEVSTAT_FREE]; dm->prev_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE; dm->prev_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000 - + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE; + + dstat[i].duration[DEVSTAT_WRITE].frac * BINTIME_SCALE; + dm->prev_dstat.duration_other_ms = dstat[i].duration[DEVSTAT_NO_DATA].sec * 1000 + + dstat[i].duration[DEVSTAT_NO_DATA].frac * BINTIME_SCALE; + dm->prev_dstat.duration_free_ms = dstat[i].duration[DEVSTAT_FREE].sec * 1000 + + dstat[i].duration[DEVSTAT_FREE].frac * BINTIME_SCALE; dm->prev_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE; } @@ -312,13 +336,20 @@ int do_kern_devstat(int update_every, usec_t dt) { cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE; cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000 - + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE; + + dstat[i].duration[DEVSTAT_WRITE].frac * BINTIME_SCALE; + cur_dstat.duration_other_ms = dstat[i].duration[DEVSTAT_NO_DATA].sec * 1000 + + dstat[i].duration[DEVSTAT_NO_DATA].frac * BINTIME_SCALE; + cur_dstat.duration_free_ms = dstat[i].duration[DEVSTAT_FREE].sec * 1000 + + dstat[i].duration[DEVSTAT_FREE].frac * BINTIME_SCALE; + cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE; // -------------------------------------------------------------------- if(dm->do_io == CONFIG_BOOLEAN_YES || (dm->do_io == CONFIG_BOOLEAN_AUTO && - (dstat[i].bytes[DEVSTAT_READ] || dstat[i].bytes[DEVSTAT_WRITE]))) { + (dstat[i].bytes[DEVSTAT_READ] || + dstat[i].bytes[DEVSTAT_WRITE] || + dstat[i].bytes[DEVSTAT_FREE]))) { if (unlikely(!dm->st_io)) { dm->st_io = rrdset_create_localhost("disk", disk, @@ -327,6 +358,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.io", "Disk I/O Bandwidth", "kilobytes/s", + "freebsd", + "devstat", 2000, update_every, RRDSET_TYPE_AREA @@ -336,18 +369,24 @@ int do_kern_devstat(int update_every, usec_t dt) { RRD_ALGORITHM_INCREMENTAL); dm->rd_io_out = rrddim_add(dm->st_io, "writes", NULL, -1, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL); + dm->rd_io_free = rrddim_add(dm->st_io, "frees", NULL, -1, KILO_FACTOR, + RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(dm->st_io); - rrddim_set_by_pointer(dm->st_io, dm->rd_io_in, dstat[i].bytes[DEVSTAT_READ]); - rrddim_set_by_pointer(dm->st_io, dm->rd_io_out, dstat[i].bytes[DEVSTAT_WRITE]); + rrddim_set_by_pointer(dm->st_io, dm->rd_io_in, dstat[i].bytes[DEVSTAT_READ]); + rrddim_set_by_pointer(dm->st_io, dm->rd_io_out, dstat[i].bytes[DEVSTAT_WRITE]); + rrddim_set_by_pointer(dm->st_io, dm->rd_io_free, dstat[i].bytes[DEVSTAT_FREE]); rrdset_done(dm->st_io); } // -------------------------------------------------------------------- if(dm->do_ops == CONFIG_BOOLEAN_YES || (dm->do_ops == CONFIG_BOOLEAN_AUTO && - (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) { + (dstat[i].operations[DEVSTAT_READ] || + dstat[i].operations[DEVSTAT_WRITE] || + dstat[i].operations[DEVSTAT_NO_DATA] || + dstat[i].operations[DEVSTAT_FREE]))) { if (unlikely(!dm->st_ops)) { dm->st_ops = rrdset_create_localhost("disk_ops", disk, @@ -356,6 +395,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.ops", "Disk Completed I/O Operations", "operations/s", + "freebsd", + "devstat", 2001, update_every, RRDSET_TYPE_LINE @@ -363,14 +404,21 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_flag_set(dm->st_ops, RRDSET_FLAG_DETAIL); - dm->rd_ops_in = rrddim_add(dm->st_ops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - dm->rd_ops_out = rrddim_add(dm->st_ops, "writes", NULL, -1, 1, - RRD_ALGORITHM_INCREMENTAL); + dm->rd_ops_in = rrddim_add(dm->st_ops, "reads", NULL, 1, 1, + RRD_ALGORITHM_INCREMENTAL); + dm->rd_ops_out = rrddim_add(dm->st_ops, "writes", NULL, -1, 1, + RRD_ALGORITHM_INCREMENTAL); + dm->rd_ops_other = rrddim_add(dm->st_ops, "other", NULL, 1, 1, + RRD_ALGORITHM_INCREMENTAL); + dm->rd_ops_free = rrddim_add(dm->st_ops, "frees", NULL, -1, 1, + RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(dm->st_ops); - rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_in, dstat[i].operations[DEVSTAT_READ]); - rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_out, dstat[i].operations[DEVSTAT_WRITE]); + rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_in, dstat[i].operations[DEVSTAT_READ]); + rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_out, dstat[i].operations[DEVSTAT_WRITE]); + rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_other, dstat[i].operations[DEVSTAT_NO_DATA]); + rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_free, dstat[i].operations[DEVSTAT_FREE]); rrdset_done(dm->st_ops); } @@ -386,6 +434,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.qops", "Disk Current I/O Operations", "operations", + "freebsd", + "devstat", 2002, update_every, RRDSET_TYPE_LINE @@ -413,6 +463,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.util", "Disk Utilization Time", "% of time working", + "freebsd", + "devstat", 2004, update_every, RRDSET_TYPE_AREA @@ -432,7 +484,10 @@ int do_kern_devstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(dm->do_iotime == CONFIG_BOOLEAN_YES || (dm->do_iotime == CONFIG_BOOLEAN_AUTO && - (cur_dstat.duration_read_ms || cur_dstat.duration_write_ms))) { + (cur_dstat.duration_read_ms || + cur_dstat.duration_write_ms || + cur_dstat.duration_other_ms || + cur_dstat.duration_free_ms))) { if (unlikely(!dm->st_iotime)) { dm->st_iotime = rrdset_create_localhost("disk_iotime", disk, @@ -441,6 +496,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.iotime", "Disk Total I/O Time", "milliseconds/s", + "freebsd", + "devstat", 2022, update_every, RRDSET_TYPE_LINE @@ -448,15 +505,21 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_flag_set(dm->st_iotime, RRDSET_FLAG_DETAIL); - dm->rd_iotime_in = rrddim_add(dm->st_iotime, "reads", NULL, 1, 1, - RRD_ALGORITHM_INCREMENTAL); - dm->rd_iotime_out = rrddim_add(dm->st_iotime, "writes", NULL, -1, 1, - RRD_ALGORITHM_INCREMENTAL); + dm->rd_iotime_in = rrddim_add(dm->st_iotime, "reads", NULL, 1, 1, + RRD_ALGORITHM_INCREMENTAL); + dm->rd_iotime_out = rrddim_add(dm->st_iotime, "writes", NULL, -1, 1, + RRD_ALGORITHM_INCREMENTAL); + dm->rd_iotime_other = rrddim_add(dm->st_iotime, "other", NULL, 1, 1, + RRD_ALGORITHM_INCREMENTAL); + dm->rd_iotime_free = rrddim_add(dm->st_iotime, "frees", NULL, -1, 1, + RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(dm->st_iotime); - rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_in, cur_dstat.duration_read_ms); - rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_out, cur_dstat.duration_write_ms); + rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_in, cur_dstat.duration_read_ms); + rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_out, cur_dstat.duration_write_ms); + rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_other, cur_dstat.duration_other_ms); + rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_free, cur_dstat.duration_free_ms); rrdset_done(dm->st_iotime); } @@ -469,7 +532,10 @@ int do_kern_devstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(dm->do_await == CONFIG_BOOLEAN_YES || (dm->do_await == CONFIG_BOOLEAN_AUTO && - (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) { + (dstat[i].operations[DEVSTAT_READ] || + dstat[i].operations[DEVSTAT_WRITE] || + dstat[i].operations[DEVSTAT_NO_DATA] || + dstat[i].operations[DEVSTAT_FREE]))) { if (unlikely(!dm->st_await)) { dm->st_await = rrdset_create_localhost("disk_await", disk, @@ -478,6 +544,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.await", "Average Completed I/O Operation Time", "ms per operation", + "freebsd", + "devstat", 2005, update_every, RRDSET_TYPE_LINE @@ -485,9 +553,13 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_flag_set(dm->st_await, RRDSET_FLAG_DETAIL); - dm->rd_await_in = rrddim_add(dm->st_await, "reads", NULL, 1, 1, + dm->rd_await_in = rrddim_add(dm->st_await, "reads", NULL, 1, 1, + RRD_ALGORITHM_ABSOLUTE); + dm->rd_await_out = rrddim_add(dm->st_await, "writes", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); - dm->rd_await_out = rrddim_add(dm->st_await, "writes", NULL, -1, 1, + dm->rd_await_other = rrddim_add(dm->st_await, "other", NULL, 1, 1, + RRD_ALGORITHM_ABSOLUTE); + dm->rd_await_free = rrddim_add(dm->st_await, "frees", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(dm->st_await); @@ -506,13 +578,29 @@ int do_kern_devstat(int update_every, usec_t dt) { (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write) : 0); + rrddim_set_by_pointer(dm->st_await, dm->rd_await_other, + (dstat[i].operations[DEVSTAT_NO_DATA] - + dm->prev_dstat.operations_other) ? + (cur_dstat.duration_other_ms - dm->prev_dstat.duration_other_ms) / + (dstat[i].operations[DEVSTAT_NO_DATA] - + dm->prev_dstat.operations_other) : + 0); + rrddim_set_by_pointer(dm->st_await, dm->rd_await_free, + (dstat[i].operations[DEVSTAT_FREE] - + dm->prev_dstat.operations_free) ? + (cur_dstat.duration_free_ms - dm->prev_dstat.duration_free_ms) / + (dstat[i].operations[DEVSTAT_FREE] - + dm->prev_dstat.operations_free) : + 0); rrdset_done(dm->st_await); } // -------------------------------------------------------------------- if(dm->do_avagsz == CONFIG_BOOLEAN_YES || (dm->do_avagsz == CONFIG_BOOLEAN_AUTO && - (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) { + (dstat[i].operations[DEVSTAT_READ] || + dstat[i].operations[DEVSTAT_WRITE] || + dstat[i].operations[DEVSTAT_FREE]))) { if (unlikely(!dm->st_avagsz)) { dm->st_avagsz = rrdset_create_localhost("disk_avgsz", disk, @@ -521,6 +609,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", + "freebsd", + "devstat", 2006, update_every, RRDSET_TYPE_AREA @@ -528,10 +618,12 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_flag_set(dm->st_avagsz, RRDSET_FLAG_DETAIL); - dm->rd_avagsz_in = rrddim_add(dm->st_avagsz, "reads", NULL, 1, KILO_FACTOR, - RRD_ALGORITHM_ABSOLUTE); - dm->rd_avagsz_out = rrddim_add(dm->st_avagsz, "writes", NULL, -1, KILO_FACTOR, - RRD_ALGORITHM_ABSOLUTE); + dm->rd_avagsz_in = rrddim_add(dm->st_avagsz, "reads", NULL, 1, KILO_FACTOR, + RRD_ALGORITHM_ABSOLUTE); + dm->rd_avagsz_out = rrddim_add(dm->st_avagsz, "writes", NULL, -1, KILO_FACTOR, + RRD_ALGORITHM_ABSOLUTE); + dm->rd_avagsz_free = rrddim_add(dm->st_avagsz, "frees", NULL, -1, KILO_FACTOR, + RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(dm->st_avagsz); @@ -549,13 +641,23 @@ int do_kern_devstat(int update_every, usec_t dt) { (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write) : 0); + rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_free, + (dstat[i].operations[DEVSTAT_FREE] - + dm->prev_dstat.operations_free) ? + (dstat[i].bytes[DEVSTAT_FREE] - dm->prev_dstat.bytes_free) / + (dstat[i].operations[DEVSTAT_FREE] - + dm->prev_dstat.operations_free) : + 0); rrdset_done(dm->st_avagsz); } // -------------------------------------------------------------------- if(dm->do_svctm == CONFIG_BOOLEAN_YES || (dm->do_svctm == CONFIG_BOOLEAN_AUTO && - (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) { + (dstat[i].operations[DEVSTAT_READ] || + dstat[i].operations[DEVSTAT_WRITE] || + dstat[i].operations[DEVSTAT_NO_DATA] || + dstat[i].operations[DEVSTAT_FREE]))) { if (unlikely(!dm->st_svctm)) { dm->st_svctm = rrdset_create_localhost("disk_svctm", disk, @@ -564,6 +666,8 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.svctm", "Average Service Time", "ms per operation", + "freebsd", + "devstat", 2007, update_every, RRDSET_TYPE_LINE @@ -578,10 +682,14 @@ int do_kern_devstat(int update_every, usec_t dt) { rrddim_set_by_pointer(dm->st_svctm, dm->rd_svctm, ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) + - (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) ? + (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write) + + (dstat[i].operations[DEVSTAT_NO_DATA] - dm->prev_dstat.operations_other) + + (dstat[i].operations[DEVSTAT_FREE] - dm->prev_dstat.operations_free)) ? (cur_dstat.busy_time_ms - dm->prev_dstat.busy_time_ms) / ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) + - (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) : + (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write) + + (dstat[i].operations[DEVSTAT_NO_DATA] - dm->prev_dstat.operations_other) + + (dstat[i].operations[DEVSTAT_FREE] - dm->prev_dstat.operations_free)) : 0); rrdset_done(dm->st_svctm); } @@ -590,10 +698,15 @@ int do_kern_devstat(int update_every, usec_t dt) { dm->prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ]; dm->prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE]; + dm->prev_dstat.bytes_free = dstat[i].bytes[DEVSTAT_FREE]; dm->prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ]; dm->prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE]; + dm->prev_dstat.operations_other = dstat[i].operations[DEVSTAT_NO_DATA]; + dm->prev_dstat.operations_free = dstat[i].operations[DEVSTAT_FREE]; dm->prev_dstat.duration_read_ms = cur_dstat.duration_read_ms; dm->prev_dstat.duration_write_ms = cur_dstat.duration_write_ms; + dm->prev_dstat.duration_other_ms = cur_dstat.duration_other_ms; + dm->prev_dstat.duration_free_ms = cur_dstat.duration_free_ms; dm->prev_dstat.busy_time_ms = cur_dstat.busy_time_ms; } } @@ -613,6 +726,8 @@ int do_kern_devstat(int update_every, usec_t dt) { NULL, "Disk I/O", "kilobytes/s", + "freebsd", + "devstat", 150, update_every, RRDSET_TYPE_AREA diff --git a/src/freebsd_getifaddrs.c b/src/freebsd_getifaddrs.c index 1a4448bd..94c0a6a4 100644 --- a/src/freebsd_getifaddrs.c +++ b/src/freebsd_getifaddrs.c @@ -228,6 +228,8 @@ int do_getifaddrs(int update_every, usec_t dt) { NULL, "IPv4 Bandwidth", "kilobits/s", + "freebsd", + "getifaddrs", 500, update_every, RRDSET_TYPE_AREA @@ -265,6 +267,8 @@ int do_getifaddrs(int update_every, usec_t dt) { NULL, "IPv6 Bandwidth", "kilobits/s", + "freebsd", + "getifaddrs", 500, update_every, RRDSET_TYPE_AREA @@ -333,6 +337,8 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.net", "Bandwidth", "kilobits/s", + "freebsd", + "getifaddrs", 7000, update_every, RRDSET_TYPE_AREA @@ -360,6 +366,8 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.packets", "Packets", "packets/s", + "freebsd", + "getifaddrs", 7001, update_every, RRDSET_TYPE_LINE @@ -397,6 +405,8 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.errors", "Interface Errors", "errors/s", + "freebsd", + "getifaddrs", 7002, update_every, RRDSET_TYPE_LINE @@ -429,6 +439,8 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.drops", "Interface Drops", "drops/s", + "freebsd", + "getifaddrs", 7003, update_every, RRDSET_TYPE_LINE @@ -462,6 +474,8 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.events", "Network Interface Events", "events/s", + "freebsd", + "getifaddrs", 7006, update_every, RRDSET_TYPE_LINE diff --git a/src/freebsd_getmntinfo.c b/src/freebsd_getmntinfo.c index e7ca56b5..66be5331 100644 --- a/src/freebsd_getmntinfo.c +++ b/src/freebsd_getmntinfo.c @@ -223,6 +223,8 @@ int do_getmntinfo(int update_every, usec_t dt) { "disk.space", title, "GB", + "freebsd", + "getmntinfo", 2023, update_every, RRDSET_TYPE_STACKED @@ -260,6 +262,8 @@ int do_getmntinfo(int update_every, usec_t dt) { "disk.inodes", title, "Inodes", + "freebsd", + "getmntinfo", 2024, update_every, RRDSET_TYPE_STACKED diff --git a/src/freebsd_ipfw.c b/src/freebsd_ipfw.c index b89650a0..81264b3f 100644 --- a/src/freebsd_ipfw.c +++ b/src/freebsd_ipfw.c @@ -162,6 +162,8 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Memory allocated by rules", "bytes", + "freebsd", + "ipfw", 3005, update_every, RRDSET_TYPE_STACKED @@ -193,6 +195,8 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Packets", "packets/s", + "freebsd", + "ipfw", 3001, update_every, RRDSET_TYPE_STACKED @@ -208,6 +212,8 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Bytes", "bytes/s", + "freebsd", + "ipfw", 3002, update_every, RRDSET_TYPE_STACKED @@ -310,6 +316,8 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Active rules", "rules", + "freebsd", + "ipfw", 3003, update_every, RRDSET_TYPE_STACKED @@ -325,6 +333,8 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Expired rules", "rules", + "freebsd", + "ipfw", 3004, update_every, RRDSET_TYPE_STACKED diff --git a/src/freebsd_kstat_zfs.c b/src/freebsd_kstat_zfs.c index 17642994..1bd48d4b 100644 --- a/src/freebsd_kstat_zfs.c +++ b/src/freebsd_kstat_zfs.c @@ -1,9 +1,11 @@ #include "common.h" #include "zfs_common.h" -struct arcstats arcstats = { 0 }; +extern struct arcstats arcstats; +// -------------------------------------------------------------------------------------------------------------------- // kstat.zfs.misc.arcstats + int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt) { (void)dt; @@ -103,15 +105,15 @@ int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt) { int arc_sys_free[5]; } mibs; - l2exist = -1; + arcstats.l2exist = -1; if(unlikely(sysctlbyname("kstat.zfs.misc.arcstats.l2_size", &l2_size, &uint64_t_size, NULL, 0))) return 0; if(likely(l2_size)) - l2exist = 1; + arcstats.l2exist = 1; else - l2exist = 0; + arcstats.l2exist = 0; GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hits", mibs.hits, arcstats.hits); GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.misses", mibs.misses, arcstats.misses); @@ -205,8 +207,92 @@ int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt) { // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_need_free", mibs.arc_need_free, arcstats.arc_need_free); // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_sys_free", mibs.arc_sys_free, arcstats.arc_sys_free); - generate_charts_arcstats(update_every); - generate_charts_arc_summary(update_every); + generate_charts_arcstats("freebsd", update_every); + generate_charts_arc_summary("freebsd", update_every); + + return 0; +} + +// -------------------------------------------------------------------------------------------------------------------- +// kstat.zfs.misc.zio_trim + +int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt) { + (void)dt; + static int mib_bytes[5] = {0, 0, 0, 0, 0}, mib_success[5] = {0, 0, 0, 0, 0}, + mib_failed[5] = {0, 0, 0, 0, 0}, mib_unsupported[5] = {0, 0, 0, 0, 0}; + uint64_t bytes, success, failed, unsupported; + + if (unlikely(GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.bytes", mib_bytes, bytes) || + GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.success", mib_success, success) || + GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.failed", mib_failed, failed) || + GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.unsupported", mib_unsupported, unsupported))) { + error("DISABLED: zfs.trim_bytes chart"); + error("DISABLED: zfs.trim_success chart"); + error("DISABLED: kstat.zfs.misc.zio_trim module"); + return 1; + } else { + + // -------------------------------------------------------------------- + + static RRDSET *st_bytes = NULL; + static RRDDIM *rd_bytes = NULL; + + if (unlikely(!st_bytes)) { + st_bytes = rrdset_create_localhost( + "zfs", + "trim_bytes", + NULL, + "trim", + NULL, + "Successfully TRIMmed bytes", + "bytes", + "freebsd", + "zfs", + 2320, + update_every, + RRDSET_TYPE_LINE + ); + + rd_bytes = rrddim_add(st_bytes, "TRIMmed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st_bytes); + + rrddim_set_by_pointer(st_bytes, rd_bytes, bytes); + rrdset_done(st_bytes); + + // -------------------------------------------------------------------- + + static RRDSET *st_requests = NULL; + static RRDDIM *rd_successful = NULL, *rd_failed = NULL, *rd_unsupported = NULL; + + if (unlikely(!st_requests)) { + st_requests = rrdset_create_localhost( + "zfs", + "trim_requests", + NULL, + "trim", + NULL, + "TRIM requests", + "requests", + "freebsd", + "zfs", + 2321, + update_every, + RRDSET_TYPE_STACKED + ); + + rd_successful = rrddim_add(st_requests, "successful", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_failed = rrddim_add(st_requests, "failed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_unsupported = rrddim_add(st_requests, "unsupported", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st_requests); + + rrddim_set_by_pointer(st_requests, rd_successful, success); + rrddim_set_by_pointer(st_requests, rd_failed, failed); + rrddim_set_by_pointer(st_requests, rd_unsupported, unsupported); + rrdset_done(st_requests); + + } return 0; }
\ No newline at end of file diff --git a/src/freebsd_sysctl.c b/src/freebsd_sysctl.c index a87b872d..9f5615df 100644 --- a/src/freebsd_sysctl.c +++ b/src/freebsd_sysctl.c @@ -27,6 +27,62 @@ int system_pagesize = PAGE_SIZE; int number_of_cpus = 1; +#if __FreeBSD_version >= 1200029 +struct __vmmeter { + uint64_t v_swtch; + uint64_t v_trap; + uint64_t v_syscall; + uint64_t v_intr; + uint64_t v_soft; + uint64_t v_vm_faults; + uint64_t v_io_faults; + uint64_t v_cow_faults; + uint64_t v_cow_optim; + uint64_t v_zfod; + uint64_t v_ozfod; + uint64_t v_swapin; + uint64_t v_swapout; + uint64_t v_swappgsin; + uint64_t v_swappgsout; + uint64_t v_vnodein; + uint64_t v_vnodeout; + uint64_t v_vnodepgsin; + uint64_t v_vnodepgsout; + uint64_t v_intrans; + uint64_t v_reactivated; + uint64_t v_pdwakeups; + uint64_t v_pdpages; + uint64_t v_pdshortfalls; + uint64_t v_dfree; + uint64_t v_pfree; + uint64_t v_tfree; + uint64_t v_forks; + uint64_t v_vforks; + uint64_t v_rforks; + uint64_t v_kthreads; + uint64_t v_forkpages; + uint64_t v_vforkpages; + uint64_t v_rforkpages; + uint64_t v_kthreadpages; + u_int v_page_size; + u_int v_page_count; + u_int v_free_reserved; + u_int v_free_target; + u_int v_free_min; + u_int v_free_count; + u_int v_wire_count; + u_int v_active_count; + u_int v_inactive_target; + u_int v_inactive_count; + u_int v_laundry_count; + u_int v_pageout_free_min; + u_int v_interrupt_free_min; + u_int v_free_severe; +}; +typedef struct __vmmeter vmmeter_t; +#else +typedef struct vmmeter vmmeter_t; +#endif // -------------------------------------------------------------------------------------------------------------------- // FreeBSD plugin initialization @@ -77,16 +133,19 @@ int do_vm_loadavg(int update_every, usec_t dt){ static RRDDIM *rd_load1 = NULL, *rd_load2 = NULL, *rd_load3 = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "load", - NULL, - "load", - NULL, - "System Load Average", - "load", - 100, - (update_every < MIN_LOADAVG_UPDATE_EVERY) ? - MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "load", + NULL, + "load", + NULL, + "System Load Average", + "load", + "freebsd", + "vm.loadavg", + 100, + (update_every < MIN_LOADAVG_UPDATE_EVERY) ? + MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE ); rd_load1 = rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rd_load2 = rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); @@ -143,16 +202,19 @@ int do_vm_vmtotal(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "active_processes", - NULL, - "processes", - NULL, - "System Active Processes", - "processes", - 750, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "active_processes", + NULL, + "processes", + NULL, + "System Active Processes", + "processes", + "freebsd", + "vm.vmtotal", + 750, + update_every, + RRDSET_TYPE_LINE ); rd = rrddim_add(st, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } @@ -169,16 +231,19 @@ int do_vm_vmtotal(int update_every, usec_t dt) { static RRDDIM *rd_running = NULL, *rd_blocked = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "processes", - NULL, - "processes", - NULL, - "System Processes", - "processes", - 600, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "processes", + NULL, + "processes", + NULL, + "System Processes", + "processes", + "freebsd", + "vm.vmtotal", + 600, + update_every, + RRDSET_TYPE_LINE ); rd_running = rrddim_add(st, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -198,16 +263,19 @@ int do_vm_vmtotal(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("mem", - "committed", - NULL, - "system", - NULL, - "Committed (Allocated) Memory", - "MB", - 5000, - update_every, - RRDSET_TYPE_AREA + st = rrdset_create_localhost( + "mem", + "committed", + NULL, + "system", + NULL, + "Committed (Allocated) Memory", + "MB", + "freebsd", + "vm.vmtotal", + 5000, + update_every, + RRDSET_TYPE_AREA ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -254,15 +322,18 @@ int do_kern_cp_time(int update_every, usec_t dt) { static RRDDIM *rd_nice = NULL, *rd_system = NULL, *rd_user = NULL, *rd_interrupt = NULL, *rd_idle = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "cpu", - NULL, - "cpu", - "system.cpu", - "Total CPU utilization", - "percentage", - 100, update_every, - RRDSET_TYPE_STACKED + st = rrdset_create_localhost( + "system", + "cpu", + NULL, + "cpu", + "system.cpu", + "Total CPU utilization", + "percentage", + "freebsd", + "kern.cp_time", + 100, update_every, + RRDSET_TYPE_STACKED ); rd_nice = rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); @@ -332,16 +403,19 @@ int do_kern_cp_times(int update_every, usec_t dt) { for (i = 0; i < number_of_cpus; i++) { if (unlikely(!all_cpu_charts[i].st)) { snprintfz(all_cpu_charts[i].cpuid, MAX_INT_DIGITS, "cpu%d", i); - all_cpu_charts[i].st = rrdset_create_localhost("cpu", - all_cpu_charts[i].cpuid, - NULL, - "utilization", - "cpu.cpu", - "Core utilization", - "percentage", - 1000, - update_every, - RRDSET_TYPE_STACKED + all_cpu_charts[i].st = rrdset_create_localhost( + "cpu", + all_cpu_charts[i].cpuid, + NULL, + "utilization", + "cpu.cpu", + "Core utilization", + "percentage", + "freebsd", + "kern.cp_times", + 1000, + update_every, + RRDSET_TYPE_STACKED ); all_cpu_charts[i].rd_nice = rrddim_add(all_cpu_charts[i].st, "nice", NULL, 1, 1, @@ -413,18 +487,22 @@ int do_dev_cpu_temperature(int update_every, usec_t dt) { } if (unlikely(!st)) { - st = rrdset_create_localhost("cpu", - "temperature", - NULL, - "temperature", - "cpu.temperatute", - "Core temperature", - "degree", - 1050, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "cpu", + "temperature", + NULL, + "temperature", + "cpu.temperatute", + "Core temperature", + "Celsius", + "freebsd", + "dev.cpu.temperature", + 1050, + update_every, + RRDSET_TYPE_LINE ); - } else rrdset_next(st); + } + else rrdset_next(st); for (i = 0; i < number_of_cpus; i++) { if (unlikely(!rd_pcpu_temperature[i])) { @@ -443,6 +521,52 @@ int do_dev_cpu_temperature(int update_every, usec_t dt) { } // -------------------------------------------------------------------------------------------------------------------- +// dev.cpu.0.freq + +int do_dev_cpu_0_freq(int update_every, usec_t dt) { + (void)dt; + static int mib[4] = {0, 0, 0, 0}; + int cpufreq; + + if (unlikely(GETSYSCTL_SIMPLE("dev.cpu.0.freq", mib, cpufreq))) { + error("DISABLED: cpu.scaling_cur_freq chart"); + error("DISABLED: dev.cpu.0.freq module"); + return 1; + } else { + + // -------------------------------------------------------------------- + + static RRDSET *st = NULL; + static RRDDIM *rd = NULL; + + if (unlikely(!st)) { + st = rrdset_create_localhost( + "cpu", + "scaling_cur_freq", + NULL, + "cpufreq", + NULL, + "Current CPU Scaling Frequency", + "MHz", + "freebsd", + "dev.cpu.0.freq", + 5003, + update_every, + RRDSET_TYPE_LINE + ); + + rd = rrddim_add(st, "frequency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd, cpufreq); + rrdset_done(st); + } + + return 0; +} + +// -------------------------------------------------------------------------------------------------------------------- // hw.intrcnt int do_hw_intcnt(int update_every, usec_t dt) { @@ -480,16 +604,19 @@ int do_hw_intcnt(int update_every, usec_t dt) { static RRDDIM *rd_intr = NULL; if (unlikely(!st_intr)) { - st_intr = rrdset_create_localhost("system", - "intr", - NULL, - "interrupts", - NULL, - "Total Hardware Interrupts", - "interrupts/s", - 900, - update_every, - RRDSET_TYPE_LINE + st_intr = rrdset_create_localhost( + "system", + "intr", + NULL, + "interrupts", + NULL, + "Total Hardware Interrupts", + "interrupts/s", + "freebsd", + "hw.intrcnt", + 900, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL); @@ -519,20 +646,22 @@ int do_hw_intcnt(int update_every, usec_t dt) { // -------------------------------------------------------------------- static RRDSET *st_interrupts = NULL; - RRDDIM *rd_interrupts = NULL; void *p; if (unlikely(!st_interrupts)) - st_interrupts = rrdset_create_localhost("system", - "interrupts", - NULL, - "interrupts", - NULL, - "System interrupts", - "interrupts/s", - 1000, - update_every, - RRDSET_TYPE_STACKED + st_interrupts = rrdset_create_localhost( + "system", + "interrupts", + NULL, + "interrupts", + NULL, + "System interrupts", + "interrupts/s", + "freebsd", + "hw.intrcnt", + 1000, + update_every, + RRDSET_TYPE_STACKED ); else rrdset_next(st_interrupts); @@ -540,9 +669,11 @@ int do_hw_intcnt(int update_every, usec_t dt) { for (i = 0; i < nintr; i++) { p = intrnames + i * (MAXCOMLEN + 1); if (unlikely((intrcnt[i] != 0) && (*(char *) p != 0))) { - rd_interrupts = rrddim_find(st_interrupts, p); + RRDDIM *rd_interrupts = rrddim_find(st_interrupts, p); + if (unlikely(!rd_interrupts)) rd_interrupts = rrddim_add(st_interrupts, p, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_set_by_pointer(st_interrupts, rd_interrupts, intrcnt[i]); } } @@ -576,16 +707,19 @@ int do_vm_stats_sys_v_intr(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "dev_intr", - NULL, - "interrupts", - NULL, - "Device Interrupts", - "interrupts/s", - 1000, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "dev_intr", + NULL, + "interrupts", + NULL, + "Device Interrupts", + "interrupts/s", + "freebsd", + "vm.stats.sys.v_intr", + 1000, + update_every, + RRDSET_TYPE_LINE ); rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -619,16 +753,19 @@ int do_vm_stats_sys_v_soft(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "soft_intr", - NULL, - "interrupts", - NULL, - "Software Interrupts", - "interrupts/s", - 1100, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "soft_intr", + NULL, + "interrupts", + NULL, + "Software Interrupts", + "interrupts/s", + "freebsd", + "vm.stats.sys.v_soft", + 1100, + update_every, + RRDSET_TYPE_LINE ); rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -662,16 +799,19 @@ int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "ctxt", - NULL, - "processes", - NULL, - "CPU Context Switches", - "context switches/s", - 800, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "ctxt", + NULL, + "processes", + NULL, + "CPU Context Switches", + "context switches/s", + "freebsd", + "vm.stats.sys.v_swtch", + 800, + update_every, + RRDSET_TYPE_LINE ); rd = rrddim_add(st, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -705,16 +845,19 @@ int do_vm_stats_sys_v_forks(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "forks", - NULL, - "processes", - NULL, - "Started Processes", - "processes/s", - 700, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "forks", + NULL, + "processes", + NULL, + "Started Processes", + "processes/s", + "freebsd", + "vm.stats.sys.v_swtch", + 700, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -779,16 +922,19 @@ int do_vm_swap_info(int update_every, usec_t dt) { static RRDDIM *rd_free = NULL, *rd_used = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "swap", - NULL, - "swap", - NULL, - "System Swap", - "MB", - 201, - update_every, - RRDSET_TYPE_STACKED + st = rrdset_create_localhost( + "system", + "swap", + NULL, + "swap", + NULL, + "System Swap", + "MB", + "freebsd", + "vm.swap_info", + 201, + update_every, + RRDSET_TYPE_STACKED ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -813,7 +959,7 @@ int do_system_ram(int update_every, usec_t dt) { (void)dt; static int mib_active_count[4] = {0, 0, 0, 0}, mib_inactive_count[4] = {0, 0, 0, 0}, mib_wire_count[4] = {0, 0, 0, 0}, mib_cache_count[4] = {0, 0, 0, 0}, mib_vfs_bufspace[2] = {0, 0}, mib_free_count[4] = {0, 0, 0, 0}; - struct vmmeter vmmeter_data; + vmmeter_t vmmeter_data; int vfs_bufspace_count; if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_active_count", mib_active_count, vmmeter_data.v_active_count) || @@ -825,7 +971,7 @@ int do_system_ram(int update_every, usec_t dt) { GETSYSCTL_SIMPLE("vfs.bufspace", mib_vfs_bufspace, vfs_bufspace_count) || GETSYSCTL_SIMPLE("vm.stats.vm.v_free_count", mib_free_count, vmmeter_data.v_free_count))) { error("DISABLED: system.ram chart"); - error("DISABLED: System.ram module"); + error("DISABLED: system.ram module"); return 1; } else { @@ -835,18 +981,20 @@ int do_system_ram(int update_every, usec_t dt) { static RRDDIM *rd_free = NULL, *rd_active = NULL, *rd_inactive = NULL, *rd_wired = NULL, *rd_cache = NULL, *rd_buffers = NULL; - st = rrdset_find_localhost("system.ram"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "ram", - NULL, - "ram", - NULL, - "System RAM", - "MB", - 200, - update_every, - RRDSET_TYPE_STACKED + st = rrdset_create_localhost( + "system", + "ram", + NULL, + "ram", + NULL, + "System RAM", + "MB", + "freebsd", + "system.ram", + 200, + update_every, + RRDSET_TYPE_STACKED ); rd_free = rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); @@ -880,7 +1028,7 @@ int do_system_ram(int update_every, usec_t dt) { int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) { (void)dt; static int mib_swappgsin[4] = {0, 0, 0, 0}, mib_swappgsout[4] = {0, 0, 0, 0}; - struct vmmeter vmmeter_data; + vmmeter_t vmmeter_data; if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_swappgsin", mib_swappgsin, vmmeter_data.v_swappgsin) || GETSYSCTL_SIMPLE("vm.stats.vm.v_swappgsout", mib_swappgsout, vmmeter_data.v_swappgsout))) { @@ -895,16 +1043,19 @@ int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) { static RRDDIM *rd_in = NULL, *rd_out = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "swapio", - NULL, - "swap", - NULL, - "Swap I/O", - "kilobytes/s", - 250, - update_every, - RRDSET_TYPE_AREA + st = rrdset_create_localhost( + "system", + "swapio", + NULL, + "swap", + NULL, + "Swap I/O", + "kilobytes/s", + "freebsd", + "vm.stats.vm.v_swappgs", + 250, + update_every, + RRDSET_TYPE_AREA ); rd_in = rrddim_add(st, "in", NULL, system_pagesize, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL); @@ -927,7 +1078,7 @@ int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) { (void)dt; static int mib_vm_faults[4] = {0, 0, 0, 0}, mib_io_faults[4] = {0, 0, 0, 0}, mib_cow_faults[4] = {0, 0, 0, 0}, mib_cow_optim[4] = {0, 0, 0, 0}, mib_intrans[4] = {0, 0, 0, 0}; - struct vmmeter vmmeter_data; + vmmeter_t vmmeter_data; if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_vm_faults", mib_vm_faults, vmmeter_data.v_vm_faults) || GETSYSCTL_SIMPLE("vm.stats.vm.v_io_faults", mib_io_faults, vmmeter_data.v_io_faults) || @@ -946,16 +1097,19 @@ int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) { *rd_cow_optimized = NULL, *rd_in_transit = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("mem", - "pgfaults", - NULL, - "system", - NULL, - "Memory Page Faults", - "page faults/s", - 500, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "mem", + "pgfaults", + NULL, + "system", + NULL, + "Memory Page Faults", + "page faults/s", + "freebsd", + "vm.stats.vm.v_pgfaults", + 500, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -1025,16 +1179,19 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { static RRDDIM *rd_semaphores = NULL, *rd_semaphore_arrays = NULL; if (unlikely(!st_semaphores)) { - st_semaphores = rrdset_create_localhost("system", - "ipc_semaphores", - NULL, - "ipc semaphores", - NULL, - "IPC Semaphores", - "semaphores", - 1000, - update_every, - RRDSET_TYPE_AREA + st_semaphores = rrdset_create_localhost( + "system", + "ipc_semaphores", + NULL, + "ipc semaphores", + NULL, + "IPC Semaphores", + "semaphores", + "freebsd", + "kern.ipc.sem", + 1000, + update_every, + RRDSET_TYPE_AREA ); rd_semaphores = rrddim_add(st_semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1047,16 +1204,19 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (unlikely(!st_semaphore_arrays)) { - st_semaphore_arrays = rrdset_create_localhost("system", - "ipc_semaphore_arrays", - NULL, - "ipc semaphores", - NULL, - "IPC Semaphore Arrays", - "arrays", - 1000, - update_every, - RRDSET_TYPE_AREA + st_semaphore_arrays = rrdset_create_localhost( + "system", + "ipc_semaphore_arrays", + NULL, + "ipc semaphores", + NULL, + "IPC Semaphore Arrays", + "arrays", + "freebsd", + "kern.ipc.sem", + 1000, + update_every, + RRDSET_TYPE_AREA ); rd_semaphore_arrays = rrddim_add(st_semaphore_arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1118,16 +1278,19 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { static RRDDIM *rd_segments = NULL, *rd_allocated = NULL; if (unlikely(!st_segs)) { - st_segs = rrdset_create_localhost("system", - "ipc_shared_mem_segs", - NULL, - "ipc shared memory", - NULL, - "IPC Shared Memory Segments", - "segments", - 1000, - update_every, - RRDSET_TYPE_AREA + st_segs = rrdset_create_localhost( + "system", + "ipc_shared_mem_segs", + NULL, + "ipc shared memory", + NULL, + "IPC Shared Memory Segments", + "segments", + "freebsd", + "kern.ipc.shm", + 1000, + update_every, + RRDSET_TYPE_AREA ); rd_segments = rrddim_add(st_segs, "segments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1140,16 +1303,19 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (unlikely(!st_size)) { - st_size = rrdset_create_localhost("system", - "ipc_shared_mem_size", - NULL, - "ipc shared memory", - NULL, - "IPC Shared Memory Segments Size", - "kilobytes", - 1000, - update_every, - RRDSET_TYPE_AREA + st_size = rrdset_create_localhost( + "system", + "ipc_shared_mem_size", + NULL, + "ipc shared memory", + NULL, + "IPC Shared Memory Segments Size", + "kilobytes", + "freebsd", + "kern.ipc.shm", + 1000, + update_every, + RRDSET_TYPE_AREA ); rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, KILO_FACTOR, RRD_ALGORITHM_ABSOLUTE); @@ -1217,16 +1383,19 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { static RRDDIM *rd_queues = NULL, *rd_messages = NULL, *rd_allocated = NULL, *rd_used = NULL; if (unlikely(!st_queues)) { - st_queues = rrdset_create_localhost("system", - "ipc_msq_queues", - NULL, - "ipc message queues", - NULL, - "Number of IPC Message Queues", - "queues", - 990, - update_every, - RRDSET_TYPE_AREA + st_queues = rrdset_create_localhost( + "system", + "ipc_msq_queues", + NULL, + "ipc message queues", + NULL, + "Number of IPC Message Queues", + "queues", + "freebsd", + "kern.ipc.msq", + 990, + update_every, + RRDSET_TYPE_AREA ); rd_queues = rrddim_add(st_queues, "queues", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1239,16 +1408,19 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (unlikely(!st_messages)) { - st_messages = rrdset_create_localhost("system", - "ipc_msq_messages", - NULL, - "ipc message queues", - NULL, - "Number of Messages in IPC Message Queues", - "messages", - 1000, - update_every, - RRDSET_TYPE_AREA + st_messages = rrdset_create_localhost( + "system", + "ipc_msq_messages", + NULL, + "ipc message queues", + NULL, + "Number of Messages in IPC Message Queues", + "messages", + "freebsd", + "kern.ipc.msq", + 1000, + update_every, + RRDSET_TYPE_AREA ); rd_messages = rrddim_add(st_messages, "messages", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1261,16 +1433,19 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (unlikely(!st_size)) { - st_size = rrdset_create_localhost("system", - "ipc_msq_size", - NULL, - "ipc message queues", - NULL, - "Size of IPC Message Queues", - "bytes", - 1100, - update_every, - RRDSET_TYPE_LINE + st_size = rrdset_create_localhost( + "system", + "ipc_msq_size", + NULL, + "ipc message queues", + NULL, + "Size of IPC Message Queues", + "bytes", + "freebsd", + "kern.ipc.msq", + 1100, + update_every, + RRDSET_TYPE_LINE ); rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1302,16 +1477,19 @@ int do_uptime(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if(unlikely(!st)) { - st = rrdset_create_localhost("system", - "uptime", - NULL, - "uptime", - NULL, - "System Uptime", - "seconds", - 1000, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "uptime", + NULL, + "uptime", + NULL, + "System Uptime", + "seconds", + "freebsd", + "uptime", + 1000, + update_every, + RRDSET_TYPE_LINE ); rd = rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1427,16 +1605,19 @@ int do_net_isr(int update_every, usec_t dt) { static RRDDIM *rd_dispatched = NULL, *rd_hybrid_dispatched = NULL, *rd_qdrops = NULL, *rd_queued = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("system", - "softnet_stat", - NULL, - "softnet_stat", - NULL, - "System softnet_stat", - "events/s", - 955, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "system", + "softnet_stat", + NULL, + "softnet_stat", + NULL, + "System softnet_stat", + "events/s", + "freebsd", + "net.isr", + 955, + update_every, + RRDSET_TYPE_LINE ); rd_dispatched = rrddim_add(st, "dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1477,16 +1658,19 @@ int do_net_isr(int update_every, usec_t dt) { snprintfz(all_softnet_charts[i].netisr_cpuid, MAX_INT_DIGITS + 17, "cpu%d_softnet_stat", i); if (unlikely(!all_softnet_charts[i].st)) { - all_softnet_charts[i].st = rrdset_create_localhost("cpu", - all_softnet_charts[i].netisr_cpuid, - NULL, - "softnet_stat", - NULL, - "Per CPU netisr statistics", - "events/s", - 1101 + i, - update_every, - RRDSET_TYPE_LINE + all_softnet_charts[i].st = rrdset_create_localhost( + "cpu", + all_softnet_charts[i].netisr_cpuid, + NULL, + "softnet_stat", + NULL, + "Per CPU netisr statistics", + "events/s", + "freebsd", + "net.isr", + 1101 + i, + update_every, + RRDSET_TYPE_LINE ); all_softnet_charts[i].rd_dispatched = rrddim_add(all_softnet_charts[i].st, "dispatched", @@ -1536,16 +1720,19 @@ int do_net_inet_tcp_states(int update_every, usec_t dt) { static RRDDIM *rd = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "tcpsock", - NULL, - "tcp", - NULL, - "IPv4 TCP Connections", - "active connections", - 2500, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "tcpsock", + NULL, + "tcp", + NULL, + "IPv4 TCP Connections", + "active connections", + "freebsd", + "net.inet.tcp.states", + 2500, + update_every, + RRDSET_TYPE_LINE ); rd = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -1564,7 +1751,8 @@ int do_net_inet_tcp_states(int update_every, usec_t dt) { int do_net_inet_tcp_stats(int update_every, usec_t dt) { (void)dt; - static int do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_tcpext_connaborts = -1, do_tcpext_ofo = -1, do_tcpext_syncookies = -1, do_ecn = -1; + static int do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_tcpext_connaborts = -1, do_tcpext_ofo = -1, + do_tcpext_syncookies = -1, do_tcpext_listen = -1, do_ecn = -1; if (unlikely(do_tcp_packets == -1)) { do_tcp_packets = config_get_boolean("plugin:freebsd:net.inet.tcp.stats", "ipv4 TCP packets", 1); @@ -1576,12 +1764,15 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { CONFIG_BOOLEAN_AUTO); do_tcpext_syncookies = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO); + do_tcpext_listen = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP listen issues", + CONFIG_BOOLEAN_AUTO); do_ecn = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "ECN packets", CONFIG_BOOLEAN_AUTO); } // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html - if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syncookies || do_ecn)) { + if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || + do_tcpext_syncookies || do_tcpext_listen || do_ecn)) { static int mib[4] = {0, 0, 0, 0}; struct tcpstat tcpstat; @@ -1598,6 +1789,8 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { error("DISABLED: ipv4.tcpofo chart"); do_tcpext_syncookies = 0; error("DISABLED: ipv4.tcpsyncookies chart"); + do_tcpext_listen = 0; + error("DISABLED: ipv4.tcplistenissues chart"); do_ecn = 0; error("DISABLED: ipv4.ecnpkts chart"); error("DISABLED: net.inet.tcp.stats module"); @@ -1611,16 +1804,19 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { static RRDDIM *rd_in_segs = NULL, *rd_out_segs = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "tcppackets", - NULL, - "tcp", - NULL, - "IPv4 TCP Packets", - "packets/s", - 2600, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "tcppackets", + NULL, + "tcp", + NULL, + "IPv4 TCP Packets", + "packets/s", + "freebsd", + "net.inet.tcp.stats", + 2600, + update_every, + RRDSET_TYPE_LINE ); rd_in_segs = rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1640,16 +1836,19 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { static RRDDIM *rd_in_errs = NULL, *rd_in_csum_errs = NULL, *rd_retrans_segs = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "tcperrors", - NULL, - "tcp", - NULL, - "IPv4 TCP Errors", - "packets/s", - 2700, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "tcperrors", + NULL, + "tcp", + NULL, + "IPv4 TCP Errors", + "packets/s", + "freebsd", + "net.inet.tcp.stats", + 2700, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -1679,16 +1878,19 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { *rd_attempt_fails = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "tcphandshake", - NULL, - "tcp", - NULL, - "IPv4 TCP Handshake Issues", - "events/s", - 2900, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "tcphandshake", + NULL, + "tcp", + NULL, + "IPv4 TCP Handshake Issues", + "events/s", + "freebsd", + "net.inet.tcp.stats", + 2900, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -1717,16 +1919,19 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { *rd_on_timeout = NULL, *rd_on_linger = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "tcpconnaborts", - NULL, - "tcp", - NULL, - "TCP Connection Aborts", - "connections/s", - 3010, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "tcpconnaborts", + NULL, + "tcp", + NULL, + "TCP Connection Aborts", + "connections/s", + "freebsd", + "net.inet.tcp.stats", + 3010, + update_every, + RRDSET_TYPE_LINE ); rd_on_data = rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1754,16 +1959,19 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { static RRDDIM *rd_ofo_queue = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "tcpofo", - NULL, - "tcp", - NULL, - "TCP Out-Of-Order Queue", - "packets/s", - 3050, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "tcpofo", + NULL, + "tcp", + NULL, + "TCP Out-Of-Order Queue", + "packets/s", + "freebsd", + "net.inet.tcp.stats", + 3050, + update_every, + RRDSET_TYPE_LINE ); rd_ofo_queue = rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1783,16 +1991,19 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { static RRDDIM *rd_recv = NULL, *rd_send = NULL, *rd_failed = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "tcpsyncookies", - NULL, - "tcp", - NULL, - "TCP SYN Cookies", - "packets/s", - 3100, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "tcpsyncookies", + NULL, + "tcp", + NULL, + "TCP SYN Cookies", + "packets/s", + "freebsd", + "net.inet.tcp.stats", + 3100, + update_every, + RRDSET_TYPE_LINE ); rd_recv = rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1806,6 +2017,41 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rrddim_set_by_pointer(st, rd_failed, tcpstat.tcps_sc_zonefail); rrdset_done(st); } + + // -------------------------------------------------------------------- + + if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && tcpstat.tcps_listendrop)) { + do_tcpext_listen = CONFIG_BOOLEAN_YES; + + static RRDSET *st_listen = NULL; + static RRDDIM *rd_overflows = NULL; + + if(unlikely(!st_listen)) { + + st_listen = rrdset_create_localhost( + "ipv4", + "tcplistenissues", + NULL, + "tcp", + NULL, + "TCP Listen Socket Issues", + "packets/s", + "freebsd", + "net.inet.tcp.stats", + 3015, + update_every, + RRDSET_TYPE_LINE + ); + + rd_overflows = rrddim_add(st_listen, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_listen); + + rrddim_set_by_pointer(st_listen, rd_overflows, tcpstat.tcps_listendrop); + + rrdset_done(st_listen); + } // -------------------------------------------------------------------- @@ -1816,16 +2062,19 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { static RRDDIM *rd_ce = NULL, *rd_no_ect = NULL, *rd_ect0 = NULL, *rd_ect1 = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "ecnpkts", - NULL, - "ecn", - NULL, - "IPv4 ECN Statistics", - "packets/s", - 8700, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "ecnpkts", + NULL, + "ecn", + NULL, + "IPv4 ECN Statistics", + "packets/s", + "freebsd", + "net.inet.tcp.stats", + 8700, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -1887,16 +2136,19 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { static RRDDIM *rd_in = NULL, *rd_out = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "udppackets", - NULL, - "udp", - NULL, - "IPv4 UDP Packets", - "packets/s", - 2601, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "udppackets", + NULL, + "udp", + NULL, + "IPv4 UDP Packets", + "packets/s", + "freebsd", + "net.inet.udp.stats", + 2601, + update_every, + RRDSET_TYPE_LINE ); rd_in = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1917,16 +2169,19 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { *rd_in_csum_errors = NULL, *rd_ignored_multi = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "udperrors", - NULL, - "udp", - NULL, - "IPv4 UDP Errors", - "events/s", - 2701, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "udperrors", + NULL, + "udp", + NULL, + "IPv4 UDP Errors", + "events/s", + "freebsd", + "net.inet.udp.stats", + 2701, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -2000,16 +2255,19 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { static RRDDIM *rd_in = NULL, *rd_out = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "icmp", - NULL, - "icmp", - NULL, - "IPv4 ICMP Packets", - "packets/s", - 2602, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4" + , "icmp" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Packets" + , "packets/s" + , "freebsd" + , "net.inet.icmp.stats" + , 2602 + , update_every + , RRDSET_TYPE_LINE ); rd_in = rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2030,9 +2288,20 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_csum = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors", - "packets/s", - 2603, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "icmp_errors" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Errors" + , "packets/s" + , "freebsd" + , "net.inet.icmp.stats" + , 2603 + , update_every + , RRDSET_TYPE_LINE + ); rd_in = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2055,8 +2324,20 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { static RRDDIM *rd_in_reps = NULL, *rd_out_reps = NULL, *rd_in = NULL, *rd_out = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messages", - "packets/s", 2604, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "icmpmsg" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Messages" + , "packets/s" + , "freebsd" + , "net.inet.icmp.stats" + , 2604 + , update_every + , RRDSET_TYPE_LINE + ); rd_in_reps = rrddim_add(st, "InEchoReps", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_reps = rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2121,16 +2402,19 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { *rd_in_delivers = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "packets", - NULL, - "packets", - NULL, - "IPv4 Packets", - "packets/s", - 3000, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "packets", + NULL, + "packets", + NULL, + "IPv4 Packets", + "packets/s", + "freebsd", + "net.inet.ip.stats", + 3000, + update_every, + RRDSET_TYPE_LINE ); rd_in_receives = rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2154,16 +2438,19 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { static RRDDIM *rd_ok = NULL, *rd_fails = NULL, *rd_created = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "fragsout", - NULL, - "fragments", - NULL, - "IPv4 Fragments Sent", - "packets/s", - 3010, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "fragsout", + NULL, + "fragments", + NULL, + "IPv4 Fragments Sent", + "packets/s", + "freebsd", + "net.inet.ip.stats", + 3010, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -2187,16 +2474,19 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "fragsin", - NULL, - "fragments", - NULL, - "IPv4 Fragments Reassembly", - "packets/s", - 3011, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "fragsin", + NULL, + "fragments", + NULL, + "IPv4 Fragments Reassembly", + "packets/s", + "freebsd", + "net.inet.ip.stats", + 3011, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -2222,16 +2512,19 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { *rd_in_addr_errors = NULL, *rd_in_unknown_protos = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", - "errors", - NULL, - "errors", - NULL, - "IPv4 Errors", - "packets/s", - 3002, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv4", + "errors", + NULL, + "errors", + NULL, + "IPv4 Errors", + "packets/s", + "freebsd", + "net.inet.ip.stats", + 3002, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -2310,16 +2603,19 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_forwarded = NULL, *rd_delivers = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "packets", - NULL, - "packets", - NULL, - "IPv6 Packets", - "packets/s", - 3000, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "packets", + NULL, + "packets", + NULL, + "IPv6 Packets", + "packets/s", + "freebsd", + "net.inet6.ip6.stats", + 3000, + update_every, + RRDSET_TYPE_LINE ); rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2347,16 +2643,19 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "fragsout", - NULL, - "fragments", - NULL, - "IPv6 Fragments Sent", - "packets/s", - 3010, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "fragsout", + NULL, + "fragments", + NULL, + "IPv6 Fragments Sent", + "packets/s", + "freebsd", + "net.inet6.ip6.stats", + 3010, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -2384,16 +2683,19 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_timeout = NULL, *rd_all = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "fragsin", - NULL, - "fragments", - NULL, - "IPv6 Fragments Reassembly", - "packets/s", - 3011, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "fragsin", + NULL, + "fragments", + NULL, + "IPv6 Fragments Reassembly", + "packets/s", + "freebsd", + "net.inet6.ip6.stats", + 3011, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -2432,16 +2734,19 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { *rd_in_no_routes = NULL, *rd_out_no_routes = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "errors", - NULL, - "errors", - NULL, - "IPv6 Errors", - "packets/s", - 3002, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "errors", + NULL, + "errors", + NULL, + "IPv6 Errors", + "packets/s", + "freebsd", + "net.inet6.ip6.stats", + 3002, + update_every, + RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); @@ -2543,16 +2848,19 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { static RRDDIM *rd_received = NULL, *rd_sent = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "icmp", - NULL, - "icmp", - NULL, - "IPv6 ICMP Messages", - "messages/s", - 10000, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "icmp", + NULL, + "icmp", + NULL, + "IPv6 ICMP Messages", + "messages/s", + "freebsd", + "net.inet6.icmp6.stats", + 10000, + update_every, + RRDSET_TYPE_LINE ); rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2575,16 +2883,19 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { static RRDDIM *rd_received = NULL, *rd_sent = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "icmpredir", - NULL, - "icmp", - NULL, - "IPv6 ICMP Redirects", - "redirects/s", - 10050, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "icmpredir", + NULL, + "icmp", + NULL, + "IPv6 ICMP Redirects", + "redirects/s", + "freebsd", + "net.inet6.icmp6.stats", + 10050, + update_every, + RRDSET_TYPE_LINE ); rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2620,15 +2931,18 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { *rd_out_parm_problems = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "icmperrors", - NULL, "icmp", - NULL, - "IPv6 ICMP Errors", - "errors/s", - 10100, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "icmperrors", + NULL, "icmp", + NULL, + "IPv6 ICMP Errors", + "errors/s", + "freebsd", + "net.inet6.icmp6.stats", + 10100, + update_every, + RRDSET_TYPE_LINE ); rd_in_errors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2671,16 +2985,19 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_replies = NULL, *rd_out_replies = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "icmpechos", - NULL, - "icmp", - NULL, - "IPv6 ICMP Echo", - "messages/s", - 10200, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "icmpechos", + NULL, + "icmp", + NULL, + "IPv6 ICMP Echo", + "messages/s", + "freebsd", + "net.inet6.icmp6.stats", + 10200, + update_every, + RRDSET_TYPE_LINE ); rd_in = rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2711,16 +3028,19 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { *rd_in_advertisements = NULL, *rd_out_advertisements = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "icmprouter", - NULL, - "icmp", - NULL, - "IPv6 Router Messages", - "messages/s", - 10400, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "icmprouter", + NULL, + "icmp", + NULL, + "IPv6 Router Messages", + "messages/s", + "freebsd", + "net.inet6.icmp6.stats", + 10400, + update_every, + RRDSET_TYPE_LINE ); rd_in_solicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2751,16 +3071,19 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { *rd_in_advertisements = NULL, *rd_out_advertisements = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "icmpneighbor", - NULL, - "icmp", - NULL, - "IPv6 Neighbor Messages", - "messages/s", - 10500, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "icmpneighbor", + NULL, + "icmp", + NULL, + "IPv6 Neighbor Messages", + "messages/s", + "freebsd", + "net.inet6.icmp6.stats", + 10500, + update_every, + RRDSET_TYPE_LINE ); rd_in_solicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -2798,16 +3121,19 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { *rd_out_135 = NULL, *rd_out_143 = NULL; if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", - "icmptypes", - NULL, - "icmp", - NULL, - "IPv6 ICMP Types", - "messages/s", - 10700, - update_every, - RRDSET_TYPE_LINE + st = rrdset_create_localhost( + "ipv6", + "icmptypes", + NULL, + "icmp", + NULL, + "IPv6 ICMP Types", + "messages/s", + "freebsd", + "net.inet6.icmp6.stats", + 10700, + update_every, + RRDSET_TYPE_LINE ); rd_in_1 = rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); diff --git a/src/freeipmi_plugin.c b/src/freeipmi_plugin.c index 42a1ac01..9cd736bb 100644 --- a/src/freeipmi_plugin.c +++ b/src/freeipmi_plugin.c @@ -522,6 +522,49 @@ static void send_metrics_to_netdata() { } +static int *excluded_record_ids = NULL; +size_t excluded_record_ids_length = 0; + +static void excluded_record_ids_parse(const char *s) { + if(!s) return; + + while(*s) { + while(*s && !isdigit(*s)) s++; + + if(isdigit(*s)) { + char *e; + unsigned long n = strtoul(s, &e, 10); + s = e; + + if(n != 0) { + excluded_record_ids = realloc(excluded_record_ids, (excluded_record_ids_length + 1) * sizeof(int)); + excluded_record_ids[excluded_record_ids_length++] = (int)n; + } + } + } + + if(debug) { + fprintf(stderr, "freeipmi.plugin: excluded record ids:"); + size_t i; + for(i = 0; i < excluded_record_ids_length; i++) { + fprintf(stderr, " %d", excluded_record_ids[i]); + } + fprintf(stderr, "\n"); + } +} + + +static int excluded_record_ids_check(int record_id) { + size_t i; + + for(i = 0; i < excluded_record_ids_length; i++) { + if(excluded_record_ids[i] == record_id) + return 1; + } + + return 0; +} + static void netdata_get_sensor( int record_id , int sensor_number @@ -546,6 +589,10 @@ static void netdata_get_sensor( if(!sn) { // not found, create it + // check if it is excluded + if(excluded_record_ids_check(record_id)) + return; + sn = calloc(1, sizeof(struct sensor)); if(!sn) { fatal("cannot allocate %zu bytes of memory.", sizeof(struct sensor)); @@ -1482,6 +1529,9 @@ int main (int argc, char **argv) { " sensor-config-file FILE filename to read sensor configuration\n" " default: %s\n" "\n" + " ignore N1,N2,N3,... sensor IDs to ignore\n" + " default: none\n" + "\n" " -v\n" " -V\n" " version print version and exit\n" @@ -1538,10 +1588,16 @@ int main (int argc, char **argv) { if(debug) fprintf(stderr, "freeipmi.plugin: sensor config file set to '%s'\n", sensor_config_file); continue; } + else if(i < argc && strcmp("ignore", argv[i]) == 0) { + excluded_record_ids_parse(argv[++i]); + continue; + } error("freeipmi.plugin: ignoring parameter '%s'", argv[i]); } + errno = 0; + if(freq > netdata_update_every) netdata_update_every = freq; diff --git a/src/global_statistics.c b/src/global_statistics.c index 88688908..c184b6d6 100644 --- a/src/global_statistics.c +++ b/src/global_statistics.c @@ -114,13 +114,13 @@ inline void global_statistics_copy(struct global_statistics *gs, uint8_t options } void global_statistics_charts(void) { - static unsigned long long old_web_requests = 0, old_web_usec = 0, - old_content_size = 0, old_compressed_content_size = 0; + static unsigned long long old_web_requests = 0, + old_web_usec = 0, + old_content_size = 0, + old_compressed_content_size = 0; - static collected_number compression_ratio = -1, average_response_time = -1; - - static RRDSET *stcpu = NULL, *stcpu_thread = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL, *stduration = NULL, - *stcompression = NULL; + static collected_number compression_ratio = -1, + average_response_time = -1; struct global_statistics gs; struct rusage me, thread; @@ -129,143 +129,280 @@ void global_statistics_charts(void) { getrusage(RUSAGE_THREAD, &thread); getrusage(RUSAGE_SELF, &me); + { + static RRDSET *st_cpu_thread = NULL; + static RRDDIM *rd_cpu_thread_user = NULL, + *rd_cpu_thread_system = NULL; + #ifdef __FreeBSD__ - if (!stcpu_thread) stcpu_thread = rrdset_find_localhost("netdata.plugin_freebsd_cpu"); - if (!stcpu_thread) { - stcpu_thread = rrdset_create_localhost("netdata", "plugin_freebsd_cpu", NULL, "freebsd", NULL - , "NetData FreeBSD Plugin CPU usage", "milliseconds/s", 132000 - , localhost->rrd_update_every, RRDSET_TYPE_STACKED); + if (unlikely(!st_cpu_thread)) { + st_cpu_thread = rrdset_create_localhost( + "netdata" + , "plugin_freebsd_cpu" + , NULL + , "freebsd" + , NULL + , "NetData FreeBSD Plugin CPU usage" + , "milliseconds/s" + , "netdata" + , "stats" + , 132000 + , localhost->rrd_update_every + , RRDSET_TYPE_STACKED + ); #else - if (!stcpu_thread) stcpu_thread = rrdset_find_localhost("netdata.plugin_proc_cpu"); - if (!stcpu_thread) { - stcpu_thread = rrdset_create_localhost("netdata", "plugin_proc_cpu", NULL, "proc", NULL - , "NetData Proc Plugin CPU usage", "milliseconds/s", 132000 - , localhost->rrd_update_every, RRDSET_TYPE_STACKED); + if (unlikely(!st_cpu_thread)) { + st_cpu_thread = rrdset_create_localhost( + "netdata" + , "plugin_proc_cpu" + , NULL + , "proc" + , NULL + , "NetData Proc Plugin CPU usage" + , "milliseconds/s" + , "netdata" + , "stats" + , 132000 + , localhost->rrd_update_every + , RRDSET_TYPE_STACKED + ); #endif - rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - } else rrdset_next(stcpu_thread); + rd_cpu_thread_user = rrddim_add(st_cpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rd_cpu_thread_system = rrddim_add(st_cpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_cpu_thread); - rrddim_set(stcpu_thread, "user", thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); - rrddim_set(stcpu_thread, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); - rrdset_done(stcpu_thread); + rrddim_set_by_pointer(st_cpu_thread, rd_cpu_thread_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); + rrddim_set_by_pointer(st_cpu_thread, rd_cpu_thread_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); + rrdset_done(st_cpu_thread); + } // ---------------------------------------------------------------- - if (!stcpu) stcpu = rrdset_find_localhost("netdata.server_cpu"); - if (!stcpu) { - stcpu = rrdset_create_localhost("netdata", "server_cpu", NULL, "netdata", NULL, "NetData CPU usage" - , "milliseconds/s", 130000, localhost->rrd_update_every, RRDSET_TYPE_STACKED); - - rrddim_add(stcpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(stcpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - } else rrdset_next(stcpu); - - rrddim_set(stcpu, "user", me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec); - rrddim_set(stcpu, "system", me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec); - rrdset_done(stcpu); + { + static RRDSET *st_cpu = NULL; + static RRDDIM *rd_cpu_user = NULL, + *rd_cpu_system = NULL; + + if (unlikely(!st_cpu)) { + st_cpu = rrdset_create_localhost( + "netdata" + , "server_cpu" + , NULL + , "netdata" + , NULL + , "NetData CPU usage" + , "milliseconds/s" + , "netdata" + , "stats" + , 130000 + , localhost->rrd_update_every + , RRDSET_TYPE_STACKED + ); + + rd_cpu_user = rrddim_add(st_cpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rd_cpu_system = rrddim_add(st_cpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_cpu); + + rrddim_set_by_pointer(st_cpu, rd_cpu_user, me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec); + rrddim_set_by_pointer(st_cpu, rd_cpu_system, me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec); + rrdset_done(st_cpu); + } // ---------------------------------------------------------------- - if (!stclients) stclients = rrdset_find_localhost("netdata.clients"); - if (!stclients) { - stclients = rrdset_create_localhost("netdata", "clients", NULL, "netdata", NULL, "NetData Web Clients" - , "connected clients", 130200, localhost->rrd_update_every, RRDSET_TYPE_LINE); - - rrddim_add(stclients, "clients", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else rrdset_next(stclients); - - rrddim_set(stclients, "clients", gs.connected_clients); - rrdset_done(stclients); + { + static RRDSET *st_clients = NULL; + static RRDDIM *rd_clients = NULL; + + if (unlikely(!st_clients)) { + st_clients = rrdset_create_localhost( + "netdata" + , "clients" + , NULL + , "netdata" + , NULL + , "NetData Web Clients" + , "connected clients" + , "netdata" + , "stats" + , 130200 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); + + rd_clients = rrddim_add(st_clients, "clients", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else + rrdset_next(st_clients); + + rrddim_set_by_pointer(st_clients, rd_clients, gs.connected_clients); + rrdset_done(st_clients); + } // ---------------------------------------------------------------- - if (!streqs) streqs = rrdset_find_localhost("netdata.requests"); - if (!streqs) { - streqs = rrdset_create_localhost("netdata", "requests", NULL, "netdata", NULL, "NetData Web Requests" - , "requests/s", 130300, localhost->rrd_update_every, RRDSET_TYPE_LINE); - - rrddim_add(streqs, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else rrdset_next(streqs); - - rrddim_set(streqs, "requests", (collected_number) gs.web_requests); - rrdset_done(streqs); + { + static RRDSET *st_reqs = NULL; + static RRDDIM *rd_requests = NULL; + + if (unlikely(!st_reqs)) { + st_reqs = rrdset_create_localhost( + "netdata" + , "requests" + , NULL + , "netdata" + , NULL + , "NetData Web Requests" + , "requests/s" + , "netdata" + , "stats" + , 130300 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); + + rd_requests = rrddim_add(st_reqs, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_reqs); + + rrddim_set_by_pointer(st_reqs, rd_requests, (collected_number) gs.web_requests); + rrdset_done(st_reqs); + } // ---------------------------------------------------------------- - if (!stbytes) stbytes = rrdset_find_localhost("netdata.net"); - if (!stbytes) { - stbytes = rrdset_create_localhost("netdata", "net", NULL, "netdata", NULL, "NetData Network Traffic" - , "kilobits/s", 130000, localhost->rrd_update_every, RRDSET_TYPE_AREA); - - rrddim_add(stbytes, "in", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(stbytes, "out", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } else rrdset_next(stbytes); - - rrddim_set(stbytes, "in", (collected_number) gs.bytes_received); - rrddim_set(stbytes, "out", (collected_number) gs.bytes_sent); - rrdset_done(stbytes); + { + static RRDSET *st_bytes = NULL; + static RRDDIM *rd_in = NULL, + *rd_out = NULL; + + if (unlikely(!st_bytes)) { + st_bytes = rrdset_create_localhost( + "netdata" + , "net" + , NULL + , "netdata" + , NULL + , "NetData Network Traffic" + , "kilobits/s" + , "netdata" + , "stats" + , 130000 + , localhost->rrd_update_every + , RRDSET_TYPE_AREA + ); + + rd_in = rrddim_add(st_bytes, "in", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_bytes, "out", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_bytes); + + rrddim_set_by_pointer(st_bytes, rd_in, (collected_number) gs.bytes_received); + rrddim_set_by_pointer(st_bytes, rd_out, (collected_number) gs.bytes_sent); + rrdset_done(st_bytes); + } // ---------------------------------------------------------------- - if (!stduration) stduration = rrdset_find_localhost("netdata.response_time"); - if (!stduration) { - stduration = rrdset_create_localhost("netdata", "response_time", NULL, "netdata", NULL - , "NetData API Response Time", "ms/request", 130400, localhost->rrd_update_every - , RRDSET_TYPE_LINE); - - rrddim_add(stduration, "average", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(stduration, "max", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - } else rrdset_next(stduration); - - uint64_t gweb_usec = gs.web_usec; - uint64_t gweb_requests = gs.web_requests; - - uint64_t web_usec = (gweb_usec >= old_web_usec) ? gweb_usec - old_web_usec : 0; - uint64_t web_requests = (gweb_requests >= old_web_requests) ? gweb_requests - old_web_requests : 0; - - old_web_usec = gweb_usec; - old_web_requests = gweb_requests; - - if (web_requests) - average_response_time = (collected_number) (web_usec / web_requests); - - if (unlikely(average_response_time != -1)) - rrddim_set(stduration, "average", average_response_time); - else - rrddim_set(stduration, "average", 0); - - rrddim_set(stduration, "max", ((gs.web_usec_max)?(collected_number)gs.web_usec_max:average_response_time)); - rrdset_done(stduration); + { + static RRDSET *st_duration = NULL; + static RRDDIM *rd_average = NULL, + *rd_max = NULL; + + if (unlikely(!st_duration)) { + st_duration = rrdset_create_localhost( + "netdata" + , "response_time" + , NULL + , "netdata" + , NULL + , "NetData API Response Time" + , "ms/request" + , "netdata" + , "stats" + , 130400 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); + + rd_average = rrddim_add(st_duration, "average", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_max = rrddim_add(st_duration, "max", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + } + else + rrdset_next(st_duration); + + uint64_t gweb_usec = gs.web_usec; + uint64_t gweb_requests = gs.web_requests; + + uint64_t web_usec = (gweb_usec >= old_web_usec) ? gweb_usec - old_web_usec : 0; + uint64_t web_requests = (gweb_requests >= old_web_requests) ? gweb_requests - old_web_requests : 0; + + old_web_usec = gweb_usec; + old_web_requests = gweb_requests; + + if (web_requests) + average_response_time = (collected_number) (web_usec / web_requests); + + if (unlikely(average_response_time != -1)) + rrddim_set_by_pointer(st_duration, rd_average, average_response_time); + else + rrddim_set_by_pointer(st_duration, rd_average, 0); + + rrddim_set_by_pointer(st_duration, rd_max, ((gs.web_usec_max)?(collected_number)gs.web_usec_max:average_response_time)); + rrdset_done(st_duration); + } // ---------------------------------------------------------------- - if (!stcompression) stcompression = rrdset_find_localhost("netdata.compression_ratio"); - if (!stcompression) { - stcompression = rrdset_create_localhost("netdata", "compression_ratio", NULL, "netdata", NULL - , "NetData API Responses Compression Savings Ratio", "percentage" - , 130500, localhost->rrd_update_every, RRDSET_TYPE_LINE); - - rrddim_add(stcompression, "savings", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - } else rrdset_next(stcompression); - - // since we don't lock here to read the global statistics - // read the smaller value first - unsigned long long gcompressed_content_size = gs.compressed_content_size; - unsigned long long gcontent_size = gs.content_size; - - unsigned long long compressed_content_size = gcompressed_content_size - old_compressed_content_size; - unsigned long long content_size = gcontent_size - old_content_size; - - old_compressed_content_size = gcompressed_content_size; - old_content_size = gcontent_size; - - if (content_size && content_size >= compressed_content_size) - compression_ratio = ((content_size - compressed_content_size) * 100 * 1000) / content_size; - - if (compression_ratio != -1) - rrddim_set(stcompression, "savings", compression_ratio); - - rrdset_done(stcompression); + { + static RRDSET *st_compression = NULL; + static RRDDIM *rd_savings = NULL; + + if (unlikely(!st_compression)) { + st_compression = rrdset_create_localhost( + "netdata" + , "compression_ratio" + , NULL + , "netdata" + , NULL + , "NetData API Responses Compression Savings Ratio" + , "percentage" + , "netdata" + , "stats" + , 130500 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); + + rd_savings = rrddim_add(st_compression, "savings", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + } + else + rrdset_next(st_compression); + + // since we don't lock here to read the global statistics + // read the smaller value first + unsigned long long gcompressed_content_size = gs.compressed_content_size; + unsigned long long gcontent_size = gs.content_size; + + unsigned long long compressed_content_size = gcompressed_content_size - old_compressed_content_size; + unsigned long long content_size = gcontent_size - old_content_size; + + old_compressed_content_size = gcompressed_content_size; + old_content_size = gcontent_size; + + if (content_size && content_size >= compressed_content_size) + compression_ratio = ((content_size - compressed_content_size) * 100 * 1000) / content_size; + + if (compression_ratio != -1) + rrddim_set_by_pointer(st_compression, rd_savings, compression_ratio); + + rrdset_done(st_compression); + } } diff --git a/src/health.c b/src/health.c index 136a1ecd..dfa7007b 100644 --- a/src/health.c +++ b/src/health.c @@ -34,10 +34,10 @@ void health_reload_host(RRDHOST *host) { rrdhost_wrlock(host); while(host->templates) - rrdcalctemplate_free(host, host->templates); + rrdcalctemplate_unlink_and_free(host, host->templates); while(host->alarms) - rrdcalc_free(host, host->alarms); + rrdcalc_unlink_and_free(host, host->alarms); rrdhost_unlock(host); @@ -84,7 +84,7 @@ void health_reload(void) { // ---------------------------------------------------------------------------- // health main thread and friends -static inline int rrdcalc_value2status(calculated_number n) { +static inline RRDCALC_STATUS rrdcalc_value2status(calculated_number n) { if(isnan(n) || isinf(n)) return RRDCALC_STATUS_UNDEFINED; if(n) return RRDCALC_STATUS_RAISED; return RRDCALC_STATUS_CLEAR; @@ -189,7 +189,6 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { done: health_alarm_log_save(host, ae); - return; } static inline void health_process_notifications(RRDHOST *host, ALARM_ENTRY *ae) { @@ -537,8 +536,8 @@ void *health_main(void *ptr) { if(unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE))) continue; - int warning_status = RRDCALC_STATUS_UNDEFINED; - int critical_status = RRDCALC_STATUS_UNDEFINED; + RRDCALC_STATUS warning_status = RRDCALC_STATUS_UNDEFINED; + RRDCALC_STATUS critical_status = RRDCALC_STATUS_UNDEFINED; // -------------------------------------------------------- // check the warning expression @@ -605,7 +604,7 @@ void *health_main(void *ptr) { // -------------------------------------------------------- // decide the final alarm status - int status = RRDCALC_STATUS_UNDEFINED; + RRDCALC_STATUS status = RRDCALC_STATUS_UNDEFINED; switch(warning_status) { case RRDCALC_STATUS_CLEAR: diff --git a/src/health.h b/src/health.h index 7028a914..f4157180 100644 --- a/src/health.h +++ b/src/health.h @@ -5,26 +5,28 @@ extern int default_health_enabled; extern int rrdvar_compare(void *a, void *b); -#define RRDVAR_TYPE_CALCULATED 1 -#define RRDVAR_TYPE_TIME_T 2 -#define RRDVAR_TYPE_COLLECTED 3 -#define RRDVAR_TYPE_TOTAL 4 -#define RRDVAR_TYPE_INT 5 -#define RRDVAR_TYPE_CALCULATED_ALLOCATED 6 - +typedef enum rrdvar_type { + RRDVAR_TYPE_CALCULATED = 1, + RRDVAR_TYPE_TIME_T = 2, + RRDVAR_TYPE_COLLECTED = 3, + RRDVAR_TYPE_TOTAL = 4, + RRDVAR_TYPE_INT = 5, + RRDVAR_TYPE_CALCULATED_ALLOCATED = 6 // a custom variable, allocated on purpose (ie. not inherited from charts) + // used only for custom host global variables +} RRDVAR_TYPE; // the variables as stored in the variables indexes // there are 3 indexes: -// 1. at each chart (RRDSET.variables_root_index) -// 2. at each context (RRDFAMILY.variables_root_index) -// 3. at each host (RRDHOST.variables_root_index) +// 1. at each chart (RRDSET.rrdvar_root_index) +// 2. at each context (RRDFAMILY.rrdvar_root_index) +// 3. at each host (RRDHOST.rrdvar_root_index) typedef struct rrdvar { avl avl; char *name; uint32_t hash; - int type; + RRDVAR_TYPE type; void *value; time_t last_updated; @@ -35,15 +37,24 @@ typedef struct rrdvar { // calculated / processed by the normal data collection process // This means, there will be no speed penalty for using // these variables + +typedef enum rrdvar_options { + RRDVAR_OPTION_DEFAULT = (0 << 0), + RRDVAR_OPTION_ALLOCATED = (1 << 0) // the value ptr is allocated (not a reference) + // future use +} RRDVAR_OPTIONS; + typedef struct rrdsetvar { + char *variable; // variable name + uint32_t hash; // variable name hash + char *key_fullid; // chart type.chart id.variable char *key_fullname; // chart type.chart name.variable - char *variable; // variable - int type; + RRDVAR_TYPE type; void *value; - uint32_t options; + RRDVAR_OPTIONS options; RRDVAR *var_local; RRDVAR *var_family; @@ -75,10 +86,10 @@ typedef struct rrddimvar { char *key_fullnameid; // chart type.chart name + dimension id char *key_fullnamename; // chart type.chart name + dimension name - int type; + RRDVAR_TYPE type; void *value; - uint32_t options; + RRDVAR_OPTIONS options; RRDVAR *var_local_id; RRDVAR *var_local_name; @@ -101,7 +112,7 @@ typedef struct rrddimvar { // calculated variables (defined in health configuration) // These aggregate time-series data at fixed intervals // (defined in their update_every member below) -// These increase the overhead of netdata. +// They increase the overhead of netdata. // // These calculations are allocated and linked (->next) // under RRDHOST. @@ -111,14 +122,6 @@ typedef struct rrddimvar { // having as RRDSET.calculations the RRDCALC to be processed // next. -#define RRDCALC_STATUS_REMOVED -2 -#define RRDCALC_STATUS_UNDEFINED -1 -#define RRDCALC_STATUS_UNINITIALIZED 0 -#define RRDCALC_STATUS_CLEAR 1 -#define RRDCALC_STATUS_RAISED 2 -#define RRDCALC_STATUS_WARNING 3 -#define RRDCALC_STATUS_CRITICAL 4 - #define RRDCALC_FLAG_DB_ERROR 0x00000001 #define RRDCALC_FLAG_DB_NAN 0x00000002 /* #define RRDCALC_FLAG_DB_STALE 0x00000004 */ @@ -179,7 +182,7 @@ typedef struct rrdcalc { // ------------------------------------------------------------------------ // runtime information - int status; // the current status of the alarm + RRDCALC_STATUS status; // the current status of the alarm calculated_number value; // the current value of the alarm calculated_number old_value; // the previous value of the alarm @@ -314,8 +317,8 @@ typedef struct alarm_entry { char *old_value_string; char *new_value_string; - int old_status; - int new_status; + RRDCALC_STATUS old_status; + RRDCALC_STATUS new_status; uint32_t flags; @@ -340,11 +343,11 @@ typedef struct alarm_log { #include "rrd.h" extern void rrdsetvar_rename_all(RRDSET *st); -extern RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options); +extern RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options); extern void rrdsetvar_free(RRDSETVAR *rs); extern void rrddimvar_rename_all(RRDDIM *rd); -extern RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options); +extern RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, const char *suffix, void *value, RRDVAR_OPTIONS options); extern void rrddimvar_free(RRDDIMVAR *rs); extern void rrdsetcalc_link_matching(RRDSET *st); @@ -364,10 +367,14 @@ extern void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after); void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf); extern RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name); -extern void rrdvar_custom_host_variable_destroy(RRDHOST *host, const char *name); -extern void rrdvar_custom_host_variable_set(RRDVAR *rv, calculated_number value); +extern void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value); -extern const char *rrdcalc_status2string(int status); +extern RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name); +extern void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rv, calculated_number value); + +extern void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock); + +extern const char *rrdcalc_status2string(RRDCALC_STATUS status); extern int health_alarm_log_open(RRDHOST *host); @@ -389,8 +396,8 @@ extern void health_alarm_log( time_t duration, calculated_number old_value, calculated_number new_value, - int old_status, - int new_status, + RRDCALC_STATUS old_status, + RRDCALC_STATUS new_status, const char *source, const char *units, const char *info, @@ -403,8 +410,13 @@ extern char *health_config_dir(void); extern void health_reload_host(RRDHOST *host); extern void health_alarm_log_free(RRDHOST *host); -extern void rrdcalc_free(RRDHOST *host, RRDCALC *rc); -extern void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt); +extern void rrdcalc_free(RRDCALC *rc); +extern void rrdcalc_unlink_and_free(RRDHOST *host, RRDCALC *rc); + +extern void rrdcalctemplate_free(RRDCALCTEMPLATE *rt); +extern void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt); + +extern int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data); #ifdef NETDATA_HEALTH_INTERNALS #define RRDVAR_MAX_LENGTH 1024 @@ -416,7 +428,7 @@ extern int rrdvar_fix_name(char *variable); extern RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart); extern void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc); -extern RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, int type, void *value); +extern RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value); extern void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv); extern void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae); diff --git a/src/health_config.c b/src/health_config.c index 2ead82ef..108eecc4 100644 --- a/src/health_config.c +++ b/src/health_config.c @@ -505,11 +505,12 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) { if (rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc))) - rrdcalc_free(host, rc); + rrdcalc_free(rc); if(rt) { if (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt)) - rrdcalctemplate_free(host, rt); + rrdcalctemplate_free(rt); + rt = NULL; } @@ -532,12 +533,13 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { else if(hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) { if(rc) { if(ignore_this || !rrdcalc_add_alarm_from_config(host, rc)) - rrdcalc_free(host, rc); + rrdcalc_free(rc); + rc = NULL; } if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt))) - rrdcalctemplate_free(host, rt); + rrdcalctemplate_free(rt); rt = callocz(1, sizeof(RRDCALCTEMPLATE)); rt->name = strdupz(value); @@ -833,10 +835,10 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { } if(rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc))) - rrdcalc_free(host, rc); + rrdcalc_free(rc); if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt))) - rrdcalctemplate_free(host, rt); + rrdcalctemplate_free(rt); fclose(fp); return 1; diff --git a/src/health_log.c b/src/health_log.c index 9881d35d..0314b086 100644 --- a/src/health_log.c +++ b/src/health_log.c @@ -351,8 +351,8 @@ inline void health_alarm_log( time_t duration, calculated_number old_value, calculated_number new_value, - int old_status, - int new_status, + RRDCALC_STATUS old_status, + RRDCALC_STATUS new_status, const char *source, const char *units, const char *info, @@ -163,11 +163,12 @@ static inline int ipc_sem_get_status(struct ipc_status *st) { int do_ipc(int update_every, usec_t dt) { (void)dt; - static int initialized = 0, read_limits_next = 0; + static int initialized = 0, read_limits_next = -1; static struct ipc_limits limits; static struct ipc_status status; - static RRDVAR *arrays_max = NULL, *semaphores_max = NULL; - static RRDSET *semaphores = NULL, *arrays = NULL; + static RRDSETVAR *arrays_max = NULL, *semaphores_max = NULL; + static RRDSET *st_semaphores = NULL, *st_arrays = NULL; + static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL; if(unlikely(!initialized)) { initialized = 1; @@ -184,28 +185,46 @@ int do_ipc(int update_every, usec_t dt) { return 1; } - arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.arrays.max"); - semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.max"); - - if(arrays_max) rrdvar_custom_host_variable_set(arrays_max, limits.semmni); - if(semaphores_max) rrdvar_custom_host_variable_set(semaphores_max, limits.semmns); - // create the charts - semaphores = rrdset_find_localhost("system.ipc_semaphores"); - if(!semaphores) { - semaphores = rrdset_create_localhost("system", "ipc_semaphores", NULL, "ipc semaphores", NULL - , "IPC Semaphores", "semaphores", 1000, localhost->rrd_update_every - , RRDSET_TYPE_AREA); - rrddim_add(semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + if(unlikely(!st_semaphores)) { + st_semaphores = rrdset_create_localhost( + "system" + , "ipc_semaphores" + , NULL + , "ipc semaphores" + , NULL + , "IPC Semaphores" + , "semaphores" + , "linux" + , "ipc" + , 1000 + , localhost->rrd_update_every + , RRDSET_TYPE_AREA + ); + rd_semaphores = rrddim_add(st_semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - arrays = rrdset_find_localhost("system.ipc_semaphore_arrays"); - if(!arrays) { - arrays = rrdset_create_localhost("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL - , "IPC Semaphore Arrays", "arrays", 1000, localhost->rrd_update_every - , RRDSET_TYPE_AREA); - rrddim_add(arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + if(unlikely(!st_arrays)) { + st_arrays = rrdset_create_localhost( + "system" + , "ipc_semaphore_arrays" + , NULL + , "ipc semaphores" + , NULL + , "IPC Semaphore Arrays" + , "arrays" + , "linux" + , "ipc" + , 1000 + , localhost->rrd_update_every + , RRDSET_TYPE_AREA + ); + rd_arrays = rrddim_add(st_arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } + + // variables + semaphores_max = rrdsetvar_custom_chart_variable_create(st_semaphores, "ipc.semaphores.max"); + arrays_max = rrdsetvar_custom_chart_variable_create(st_arrays, "ipc.semaphores.arrays.max"); } if(unlikely(read_limits_next < 0)) { @@ -213,11 +232,11 @@ int do_ipc(int update_every, usec_t dt) { error("Unable to fetch semaphore limits."); } else { - if(arrays_max) rrdvar_custom_host_variable_set(arrays_max, limits.semmni); - if(semaphores_max) rrdvar_custom_host_variable_set(semaphores_max, limits.semmns); + if(semaphores_max) rrdsetvar_custom_chart_variable_set(semaphores_max, limits.semmns); + if(arrays_max) rrdsetvar_custom_chart_variable_set(arrays_max, limits.semmni); - arrays->red = limits.semmni; - semaphores->red = limits.semmns; + st_arrays->red = limits.semmni; + st_semaphores->red = limits.semmns; read_limits_next = 60 / update_every; } @@ -230,13 +249,13 @@ int do_ipc(int update_every, usec_t dt) { return 0; } - if(semaphores->counter_done) rrdset_next(semaphores); - rrddim_set(semaphores, "semaphores", status.semaem); - rrdset_done(semaphores); + if(st_semaphores->counter_done) rrdset_next(st_semaphores); + rrddim_set_by_pointer(st_semaphores, rd_semaphores, status.semaem); + rrdset_done(st_semaphores); - if(arrays->counter_done) rrdset_next(arrays); - rrddim_set(arrays, "arrays", status.semusz); - rrdset_done(arrays); + if(st_arrays->counter_done) rrdset_next(st_arrays); + rrddim_set_by_pointer(st_arrays, rd_arrays, status.semusz); + rrdset_done(st_arrays); return 0; } diff --git a/src/macos_fw.c b/src/macos_fw.c index fa103e11..5e8ce0ee 100644 --- a/src/macos_fw.c +++ b/src/macos_fw.c @@ -112,8 +112,14 @@ int do_macos_iokit(int update_every, usec_t dt) { CFRelease(properties); IOObjectRelease(drive_media); + if(unlikely(!diskstat.name || !*diskstat.name)) { + IOObjectRelease(drive); + continue; + } + /* Obtain the properties for this drive object. */ if (unlikely(IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) { + IOObjectRelease(drive); error("MACOS: IORegistryEntryCreateCFProperties() failed"); do_io = 0; error("DISABLED: system.io"); @@ -138,9 +144,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk", diskstat.name); if (unlikely(!st)) { - st = rrdset_create_localhost("disk", diskstat.name, NULL, diskstat.name, "disk.io" - , "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every - , RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + "disk" + , diskstat.name + , NULL + , diskstat.name + , "disk.io" + , "Disk I/O Bandwidth" + , "kilobytes/s" + , "macos" + , "iokit" + , 2000 + , update_every + , RRDSET_TYPE_AREA + ); rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); @@ -165,9 +182,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_ops", diskstat.name); if (unlikely(!st)) { - st = rrdset_create_localhost("disk_ops", diskstat.name, NULL, diskstat.name, "disk.ops" - , "Disk Completed I/O Operations", "operations/s", 2001 - , update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "disk_ops" + , diskstat.name + , NULL + , diskstat.name + , "disk.ops" + , "Disk Completed I/O Operations" + , "operations/s" + , "macos" + , "iokit" + , 2001 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -193,9 +221,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_util", diskstat.name); if (unlikely(!st)) { - st = rrdset_create_localhost("disk_util", diskstat.name, NULL, diskstat.name, "disk.util" - , "Disk Utilization Time", "% of time working", 2004, update_every - , RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + "disk_util" + , diskstat.name + , NULL + , diskstat.name + , "disk.util" + , "Disk Utilization Time" + , "% of time working" + , "macos" + , "iokit" + , 2004 + , update_every + , RRDSET_TYPE_AREA + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "utilization", NULL, 1, 10000000, RRD_ALGORITHM_INCREMENTAL); @@ -220,9 +259,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_iotime", diskstat.name); if (unlikely(!st)) { - st = rrdset_create_localhost("disk_iotime", diskstat.name, NULL, diskstat.name, "disk.iotime" - , "Disk Total I/O Time", "milliseconds/s", 2022, update_every - , RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "disk_iotime" + , diskstat.name + , NULL + , diskstat.name + , "disk.iotime" + , "Disk Total I/O Time" + , "milliseconds/s" + , "macos" + , "iokit" + , 2022 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL); @@ -246,9 +296,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_await", diskstat.name); if (unlikely(!st)) { - st = rrdset_create_localhost("disk_await", diskstat.name, NULL, diskstat.name, "disk.await" - , "Average Completed I/O Operation Time", "ms per operation" - , 2005, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "disk_await" + , diskstat.name + , NULL + , diskstat.name + , "disk.await" + , "Average Completed I/O Operation Time" + , "ms per operation" + , "macos" + , "iokit" + , 2005 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); @@ -266,10 +327,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_avgsz", diskstat.name); if (unlikely(!st)) { - st = rrdset_create_localhost("disk_avgsz", diskstat.name, NULL, diskstat.name, "disk.avgsz" - , "Average Completed I/O Operation Bandwidth" - , "kilobytes per operation", 2006, update_every - , RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + "disk_avgsz" + , diskstat.name + , NULL + , diskstat.name + , "disk.avgsz" + , "Average Completed I/O Operation Bandwidth" + , "kilobytes per operation" + , "macos" + , "iokit" + , 2006 + , update_every + , RRDSET_TYPE_AREA + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); @@ -287,9 +358,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_svctm", diskstat.name); if (unlikely(!st)) { - st = rrdset_create_localhost("disk_svctm", diskstat.name, NULL, diskstat.name, "disk.svctm" - , "Average Service Time", "ms per operation", 2007 - , update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "disk_svctm" + , diskstat.name + , NULL + , diskstat.name + , "disk.svctm" + , "Average Service Time" + , "ms per operation" + , "macos" + , "iokit" + , 2007 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "svctm", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); @@ -318,8 +400,20 @@ int do_macos_iokit(int update_every, usec_t dt) { if (likely(do_io)) { st = rrdset_find_bytype_localhost("system", "io"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150 - , update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + "system" + , "io" + , NULL + , "disk" + , NULL + , "Disk I/O" + , "kilobytes/s" + , "macos" + , "iokit" + , 150 + , update_every + , RRDSET_TYPE_AREA + ); rrddim_add(st, "in", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "out", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } @@ -359,14 +453,24 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_space", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); - st = rrdset_create_localhost("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname - , "disk.space", title, "GB", 2023, update_every - , RRDSET_TYPE_STACKED); + st = rrdset_create_localhost( + "disk_space" + , mntbuf[i].f_mntonname + , NULL + , mntbuf[i].f_mntonname + , "disk.space" + , title + , "GB" + , "macos" + , "iokit" + , 2023 + , update_every + , RRDSET_TYPE_STACKED + ); rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, - RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -382,9 +486,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("disk_inodes", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); - st = rrdset_create_localhost("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname - , "disk.inodes", title, "Inodes", 2024, update_every - , RRDSET_TYPE_STACKED); + st = rrdset_create_localhost( + "disk_inodes" + , mntbuf[i].f_mntonname + , NULL + , mntbuf[i].f_mntonname + , "disk.inodes" + , title + , "Inodes" + , "macos" + , "iokit" + , 2024 + , update_every + , RRDSET_TYPE_STACKED + ); rrddim_add(st, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -417,8 +532,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("net", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create_localhost("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth" - , "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + "net" + , ifa->ifa_name + , NULL + , ifa->ifa_name + , "net.net" + , "Bandwidth" + , "kilobits/s" + , "macos" + , "iokit" + , 7000 + , update_every + , RRDSET_TYPE_AREA + ); rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); @@ -433,8 +560,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("net_packets", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create_localhost("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets" - , "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "net_packets" + , ifa->ifa_name + , NULL + , ifa->ifa_name + , "net.packets" + , "Packets" + , "packets/s" + , "macos" + , "iokit" + , 7001 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -454,8 +593,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("net_errors", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create_localhost("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors" - , "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "net_errors" + , ifa->ifa_name + , NULL + , ifa->ifa_name + , "net.errors" + , "Interface Errors" + , "errors/s" + , "macos" + , "iokit" + , 7002 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -471,8 +622,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("net_drops", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create_localhost("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops" - , "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "net_drops" + , ifa->ifa_name + , NULL + , ifa->ifa_name + , "net.drops" + , "Interface Drops" + , "drops/s" + , "macos" + , "iokit" + , 7003 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -486,9 +649,20 @@ int do_macos_iokit(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("net_events", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create_localhost("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events" - , "Network Interface Events", "events/s", 7006, update_every - , RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "net_events" + , ifa->ifa_name + , NULL + , ifa->ifa_name + , "net.events" + , "Network Interface Events" + , "events/s" + , "macos" + , "iokit" + , 7006 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); diff --git a/src/macos_mach_smi.c b/src/macos_mach_smi.c index da282551..bcde589f 100644 --- a/src/macos_mach_smi.c +++ b/src/macos_mach_smi.c @@ -25,7 +25,11 @@ int do_macos_mach_smi(int update_every, usec_t dt) { natural_t cp_time[CPU_STATE_MAX]; // NEEDED BY: do_ram, do_swapio, do_pgfaults +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) vm_statistics64_data_t vm_statistics; +#else + vm_statistics_data_t vm_statistics; +#endif host = mach_host_self(); kr = host_page_size(host, &system_pagesize); @@ -50,8 +54,20 @@ int do_macos_mach_smi(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("system", "cpu"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization" - , "percentage", 100, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost( + "system" + , "cpu" + , NULL + , "cpu" + , "system.cpu" + , "Total CPU utilization" + , "percentage" + , "macos" + , "mach_smi" + , 100 + , update_every + , RRDSET_TYPE_STACKED + ); rrddim_add(st, "user", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); @@ -73,8 +89,13 @@ int do_macos_mach_smi(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_ram || do_swapio || do_pgfaults)) { +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) count = sizeof(vm_statistics64_data_t); kr = host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vm_statistics, &count); +#else + count = sizeof(vm_statistics_data_t); + kr = host_statistics(host, HOST_VM_INFO, (host_info_t)&vm_statistics, &count); +#endif if (unlikely(kr != KERN_SUCCESS)) { error("MACOS: host_statistics64() failed: %s", mach_error_string(kr)); do_ram = 0; @@ -87,13 +108,27 @@ int do_macos_mach_smi(int update_every, usec_t dt) { if (likely(do_ram)) { st = rrdset_find_localhost("system.ram"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200 - , update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost( + "system" + , "ram" + , NULL + , "ram" + , NULL + , "System RAM" + , "MB" + , "macos" + , "mach_smi" + , 200 + , update_every + , RRDSET_TYPE_STACKED + ); rrddim_add(st, "active", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "wired", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) rrddim_add(st, "throttled", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "compressor", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); +#endif rrddim_add(st, "inactive", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "purgeable", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "speculative", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); @@ -103,8 +138,10 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrddim_set(st, "active", vm_statistics.active_count); rrddim_set(st, "wired", vm_statistics.wire_count); +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) rrddim_set(st, "throttled", vm_statistics.throttled_count); rrddim_set(st, "compressor", vm_statistics.compressor_page_count); +#endif rrddim_set(st, "inactive", vm_statistics.inactive_count); rrddim_set(st, "purgeable", vm_statistics.purgeable_count); rrddim_set(st, "speculative", vm_statistics.speculative_count); @@ -112,13 +149,26 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrdset_done(st); } +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) // -------------------------------------------------------------------- if (likely(do_swapio)) { st = rrdset_find_localhost("system.swapio"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250 - , update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + "system" + , "swapio" + , NULL + , "swap" + , NULL + , "Swap I/O" + , "kilobytes/s" + , "macos" + , "mach_smi" + , 250 + , update_every + , RRDSET_TYPE_AREA + ); rrddim_add(st, "in", NULL, system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); @@ -129,22 +179,37 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrddim_set(st, "out", vm_statistics.swapouts); rrdset_done(st); } +#endif // -------------------------------------------------------------------- if (likely(do_pgfaults)) { st = rrdset_find_localhost("mem.pgfaults"); if (unlikely(!st)) { - st = rrdset_create_localhost("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults" - , "page faults/s", 500, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "mem" + , "pgfaults" + , NULL + , "system" + , NULL + , "Memory Page Faults" + , "page faults/s" + , "macos" + , "mach_smi" + , 500 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "memory", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "cow", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "pagein", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "pageout", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) rrddim_add(st, "compress", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "decompress", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); +#endif rrddim_add(st, "zero_fill", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "reactivate", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "purge", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -155,8 +220,10 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrddim_set(st, "cow", vm_statistics.cow_faults); rrddim_set(st, "pagein", vm_statistics.pageins); rrddim_set(st, "pageout", vm_statistics.pageouts); +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) rrddim_set(st, "compress", vm_statistics.compressions); rrddim_set(st, "decompress", vm_statistics.decompressions); +#endif rrddim_set(st, "zero_fill", vm_statistics.zero_fill_count); rrddim_set(st, "reactivate", vm_statistics.reactivations); rrddim_set(st, "purge", vm_statistics.purges); diff --git a/src/macos_sysctl.c b/src/macos_sysctl.c index 843aceae..cb6fa8af 100644 --- a/src/macos_sysctl.c +++ b/src/macos_sysctl.c @@ -1,4 +1,5 @@ #include "common.h" +#include <Availability.h> #include <sys/sysctl.h> // NEEDED BY: do_bandwidth #include <net/route.h> @@ -112,9 +113,21 @@ int do_macos_sysctl(int update_every, usec_t dt) { /* * Dirty workaround for /usr/include/netinet6/ip6_var.h absence. * Struct ip6stat was copied from bsd/netinet6/ip6_var.h from xnu sources. + * Do the same for previously missing scope6_var.h on OS X < 10.11. */ #define IP6S_SRCRULE_COUNT 16 + +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101100) +#ifndef _NETINET6_SCOPE6_VAR_H_ +#define _NETINET6_SCOPE6_VAR_H_ +#include <sys/appleapiopts.h> + +#define SCOPE6_ID_MAX 16 +#endif +#else #include <netinet6/scope6_var.h> +#endif + struct ip6stat { u_quad_t ip6s_total; /* total packets received */ u_quad_t ip6s_tooshort; /* packet too short */ @@ -217,9 +230,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("system", "load"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", "load", NULL, "load", NULL, "System Load Average", "load" - , 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) - ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "system" + , "load" + , NULL + , "load" + , NULL + , "System Load Average" + , "load" + , "macos" + , "sysctl" + , 100 + , (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); @@ -246,8 +270,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { } else { st = rrdset_find_localhost("system.swap"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201 - , update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost( + "system" + , "swap" + , NULL + , "swap" + , NULL + , "System Swap" + , "MB" + , "macos" + , "sysctl" + , 201 + , update_every + , RRDSET_TYPE_STACKED + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "free", NULL, 1, 1048576, RRD_ALGORITHM_ABSOLUTE); @@ -296,8 +332,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { } st = rrdset_find_localhost("system.ipv4"); if (unlikely(!st)) { - st = rrdset_create_localhost("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s" - , 500, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + "system" + , "ipv4" + , NULL + , "network" + , NULL + , "IPv4 Bandwidth" + , "kilobits/s" + , "macos" + , "sysctl" + , 500 + , update_every + , RRDSET_TYPE_AREA + ); rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); @@ -334,8 +382,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_tcp_packets)) { st = rrdset_find_localhost("ipv4.tcppackets"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets" - , "packets/s", 2600, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "tcppackets" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Packets" + , "packets/s" + , "macos" + , "sysctl" + , 2600 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -352,8 +412,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_tcp_errors)) { st = rrdset_find_localhost("ipv4.tcperrors"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", "packets/s" - , 2700, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "tcperrors" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Errors" + , "packets/s" + , "macos" + , "sysctl" + , 2700 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -373,8 +445,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_tcp_handshake)) { st = rrdset_find_localhost("ipv4.tcphandshake"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "tcphandshake", NULL, "tcp", NULL, "IPv4 TCP Handshake Issues" - , "events/s", 2900, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "tcphandshake" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Handshake Issues" + , "events/s" + , "macos" + , "sysctl" + , 2900 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -397,8 +481,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_tcpext_connaborts = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv4.tcpconnaborts"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts" - , "connections/s", 3010, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "tcpconnaborts" + , NULL + , "tcp" + , NULL + , "TCP Connection Aborts" + , "connections/s" + , "macos" + , "sysctl" + , 3010 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -420,8 +516,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_tcpext_ofo = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv4.tcpofo"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue" - , "packets/s", 3050, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "tcpofo" + , NULL + , "tcp" + , NULL + , "TCP Out-Of-Order Queue" + , "packets/s" + , "macos" + , "sysctl" + , 3050 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); } @@ -438,8 +546,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { st = rrdset_find_localhost("ipv4.tcpsyncookies"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies" - , "packets/s", 3100, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "tcpsyncookies" + , NULL + , "tcp" + , NULL + , "TCP SYN Cookies" + , "packets/s" + , "macos" + , "sysctl" + , 3100 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -455,12 +575,26 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- + +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) if (do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) { do_ecn = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv4.ecnpkts"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics" - , "packets/s", 8700, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "ecnpkts" + , NULL + , "ecn" + , NULL + , "IPv4 ECN Statistics" + , "packets/s" + , "macos" + , "sysctl" + , 8700 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -472,6 +606,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported); rrdset_done(st); } +#endif } } @@ -489,8 +624,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_udp_packets)) { st = rrdset_find_localhost("ipv4.udppackets"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets" - , "packets/s", 2601, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "udppackets" + , NULL + , "udp" + , NULL + , "IPv4 UDP Packets" + , "packets/s" + , "macos" + , "sysctl" + , 2601 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -507,23 +654,41 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_udp_errors)) { st = rrdset_find_localhost("ipv4.udperrors"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s" - , 2701, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "udperrors" + , NULL + , "udp" + , NULL + , "IPv4 UDP Errors" + , "events/s" + , "macos" + , "sysctl" + , 2701 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); +#endif } else rrdset_next(st); rrddim_set(st, "InErrors", udpstat.udps_hdrops + udpstat.udps_badlen); rrddim_set(st, "NoPorts", udpstat.udps_noport); rrddim_set(st, "RcvbufErrors", udpstat.udps_fullsock); +#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) rrddim_set(st, "InCsumErrors", udpstat.udps_badsum + udpstat.udps_nosum); rrddim_set(st, "IgnoredMulti", udpstat.udps_filtermcast); +#else + rrddim_set(st, "InCsumErrors", udpstat.udps_badsum); +#endif rrdset_done(st); } } @@ -550,8 +715,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_icmp_packets)) { st = rrdset_find_localhost("ipv4.icmp"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s" - , 2602, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "icmp" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Packets" + , "packets/s" + , "macos" + , "sysctl" + , 2602 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -567,8 +744,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { st = rrdset_find_localhost("ipv4.icmp_errors"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors" - , "packets/s", 2603, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "icmp_errors" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Errors" + , "packets/s" + , "macos" + , "sysctl" + , 2603 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -588,8 +777,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_icmpmsg)) { st = rrdset_find_localhost("ipv4.icmpmsg"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messages" - , "packets/s", 2604, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "icmpmsg" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Messages" + , "packets/s" + , "macos" + , "sysctl" + , 2604 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InEchoReps", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -625,8 +826,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_ip_packets)) { st = rrdset_find_localhost("ipv4.packets"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s" - , 3000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "packets" + , NULL + , "packets" + , NULL + , "IPv4 Packets" + , "packets/s" + , "macos" + , "sysctl" + , 3000 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -647,8 +860,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_ip_fragsout)) { st = rrdset_find_localhost("ipv4.fragsout"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent" - , "packets/s", 3010, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "fragsout" + , NULL + , "fragments" + , NULL + , "IPv4 Fragments Sent" + , "packets/s" + , "macos" + , "sysctl" + , 3010 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -668,8 +893,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_ip_fragsin)) { st = rrdset_find_localhost("ipv4.fragsin"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "fragsin", NULL, "fragments", NULL, "IPv4 Fragments Reassembly" - , "packets/s", 3011, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "fragsin" + , NULL + , "fragments" + , NULL + , "IPv4 Fragments Reassembly" + , "packets/s" + , "macos" + , "sysctl" + , 3011 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -689,8 +926,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { if (likely(do_ip_errors)) { st = rrdset_find_localhost("ipv4.errors"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv4", "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s" - , 3002, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv4" + , "errors" + , NULL + , "errors" + , NULL + , "IPv4 Errors" + , "packets/s" + , "macos" + , "sysctl" + , 3002 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -734,8 +983,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_ip6_packets = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.packets"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s" - , 3000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "packets" + , NULL + , "packets" + , NULL + , "IPv6 Packets" + , "packets/s" + , "macos" + , "sysctl" + , 3000 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -759,8 +1020,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_ip6_fragsout = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.fragsout"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent" - , "packets/s", 3010, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "fragsout" + , NULL + , "fragments" + , NULL + , "IPv6 Fragments Sent" + , "packets/s" + , "macos" + , "sysctl" + , 3010 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -783,8 +1056,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_ip6_fragsin = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.fragsin"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly" - , "packets/s", 3011, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "fragsin" + , NULL + , "fragments" + , NULL + , "IPv6 Fragments Reassembly" + , "packets/s" + , "macos" + , "sysctl" + , 3011 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -816,8 +1101,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_ip6_errors = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.errors"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s" - , 3002, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "errors" + , NULL + , "errors" + , NULL + , "IPv6 Errors" + , "packets/s" + , "macos" + , "sysctl" + , 3002 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -863,8 +1160,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_icmp6 = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.icmp"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", "messages/s" - , 10000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "icmp" + , NULL + , "icmp" + , NULL + , "IPv6 ICMP Messages" + , "messages/s" + , "macos" + , "sysctl" + , 10000 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -882,8 +1191,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_icmp6_redir = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.icmpredir"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects" - , "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "icmpredir" + , NULL + , "icmp" + , NULL + , "IPv6 ICMP Redirects" + , "redirects/s" + , "macos" + , "sysctl" + , 10050 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -912,8 +1233,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_icmp6_errors = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.icmperrors"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors" - , "errors/s", 10100, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "icmperrors" + , NULL + , "icmp" + , NULL + , "IPv6 ICMP Errors" + , "errors/s" + , "macos" + , "sysctl" + , 10100 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -952,8 +1285,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_icmp6_echos = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.icmpechos"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s" - , 10200, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "icmpechos" + , NULL + , "icmp" + , NULL + , "IPv6 ICMP Echo" + , "messages/s" + , "macos" + , "sysctl" + , 10200 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -979,8 +1324,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_icmp6_router = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.icmprouter"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages" - , "messages/s", 10400, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "icmprouter" + , NULL + , "icmp" + , NULL + , "IPv6 Router Messages" + , "messages/s" + , "macos" + , "sysctl" + , 10400 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1006,8 +1363,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_icmp6_neighbor = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.icmpneighbor"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages" - , "messages/s", 10500, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "icmpneighbor" + , NULL + , "icmp" + , NULL + , "IPv6 Neighbor Messages" + , "messages/s" + , "macos" + , "sysctl" + , 10500 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1039,8 +1408,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_icmp6_types = CONFIG_BOOLEAN_YES; st = rrdset_find_localhost("ipv6.icmptypes"); if (unlikely(!st)) { - st = rrdset_create_localhost("ipv6", "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types" - , "messages/s", 10700, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "ipv6" + , "icmptypes" + , NULL + , "icmp" + , NULL + , "IPv6 ICMP Types" + , "messages/s" + , "macos" + , "sysctl" + , 10700 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -1081,8 +1462,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { st = rrdset_find_localhost("system.uptime"); if(unlikely(!st)) { - st = rrdset_create_localhost("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000 - , update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "system" + , "uptime" + , NULL + , "uptime" + , NULL + , "System Uptime" + , "seconds" + , "macos" + , "sysctl" + , 1000 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -32,24 +32,34 @@ void netdata_cleanup_and_exit(int ret) { } struct netdata_static_thread static_threads[] = { + #ifdef INTERNAL_PLUGIN_NFACCT -// nfacct requires root access + // nfacct requires root access // so, we build it as an external plugin with setuid to root {"nfacct", CONFIG_SECTION_PLUGINS, "nfacct", 1, NULL, NULL, nfacct_main}, #endif - {"tc", CONFIG_SECTION_PLUGINS, "tc", 1, NULL, NULL, tc_main}, - {"idlejitter", CONFIG_SECTION_PLUGINS, "idlejitter", 1, NULL, NULL, cpuidlejitter_main}, +#ifdef NETDATA_INTERNAL_CHECKS + // debugging plugin + {"check", CONFIG_SECTION_PLUGINS, "checks", 0, NULL, NULL, checks_main}, +#endif + #if defined(__FreeBSD__) + // FreeBSD internal plugins {"freebsd", CONFIG_SECTION_PLUGINS, "freebsd", 1, NULL, NULL, freebsd_main}, #elif defined(__APPLE__) + // macOS internal plugins {"macos", CONFIG_SECTION_PLUGINS, "macos", 1, NULL, NULL, macos_main}, #else + // linux internal plugins {"proc", CONFIG_SECTION_PLUGINS, "proc", 1, NULL, NULL, proc_main}, {"diskspace", CONFIG_SECTION_PLUGINS, "diskspace", 1, NULL, NULL, proc_diskspace_main}, {"cgroups", CONFIG_SECTION_PLUGINS, "cgroups", 1, NULL, NULL, cgroups_main}, + {"tc", CONFIG_SECTION_PLUGINS, "tc", 1, NULL, NULL, tc_main}, #endif /* __FreeBSD__, __APPLE__*/ - {"check", CONFIG_SECTION_PLUGINS, "checks", 0, NULL, NULL, checks_main}, + + // common plugins for all systems + {"idlejitter", CONFIG_SECTION_PLUGINS, "idlejitter", 1, NULL, NULL, cpuidlejitter_main}, {"backends", NULL, NULL, 1, NULL, NULL, backends_main}, {"health", NULL, NULL, 1, NULL, NULL, health_main}, {"plugins.d", NULL, NULL, 1, NULL, NULL, pluginsd_main}, @@ -57,6 +67,7 @@ struct netdata_static_thread static_threads[] = { {"web-single-threaded", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded}, {"push-metrics", NULL, NULL, 0, NULL, NULL, rrdpush_sender_thread}, {"statsd", NULL, NULL, 1, NULL, NULL, statsd_main}, + {NULL, NULL, NULL, 0, NULL, NULL, NULL} }; @@ -83,6 +94,13 @@ void web_server_config_options(void) { web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", ""); if(!*web_x_frame_options) web_x_frame_options = NULL; + web_allow_connections_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"), SIMPLE_PATTERN_EXACT); + web_allow_dashboard_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow dashboard from", "localhost *"), SIMPLE_PATTERN_EXACT); + web_allow_badges_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), SIMPLE_PATTERN_EXACT); + web_allow_registry_from = simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), SIMPLE_PATTERN_EXACT); + web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"), SIMPLE_PATTERN_EXACT); + web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from", "localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*"), SIMPLE_PATTERN_EXACT); + #ifdef NETDATA_WITH_ZLIB web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip); @@ -195,23 +213,8 @@ void kill_childs() tc_child_pid = 0; } - struct plugind *cd; - for(cd = pluginsd_root ; cd ; cd = cd->next) { - if(cd->enabled && !cd->obsolete) { - info("Stopping %s plugin thread", cd->id); - pthread_cancel(cd->thread); - - if(cd->pid) { - info("killing %s plugin child process pid %d", cd->id, cd->pid); - if(killpid(cd->pid, SIGTERM) != -1) - waitid(P_PID, (id_t) cd->pid, &info, WEXITED); - - cd->pid = 0; - } - - cd->obsolete = 1; - } - } + // stop all running plugins + pluginsd_stop_all_external_plugins(); // if, for any reason there is any child exited // catch it here @@ -221,7 +224,7 @@ void kill_childs() info("All threads/childs stopped."); } -struct option_def options[] = { +struct option_def option_definitions[] = { // opt description arg name default value { 'c', "Configuration file to load.", "filename", CONFIG_DIR "/" CONFIG_FILENAME}, { 'D', "Do not fork. Run in the foreground.", NULL, "run in the background"}, @@ -237,21 +240,21 @@ struct option_def options[] = { { 'W', "See Advanced options below.", "options", NULL}, }; -void help(int exitcode) { +int help(int exitcode) { FILE *stream; if(exitcode == 0) stream = stdout; else stream = stderr; - int num_opts = sizeof(options) / sizeof(struct option_def); + int num_opts = sizeof(option_definitions) / sizeof(struct option_def); int i; int max_len_arg = 0; // Compute maximum argument length for( i = 0; i < num_opts; i++ ) { - if(options[i].arg_name) { - int len_arg = (int)strlen(options[i].arg_name); + if(option_definitions[i].arg_name) { + int len_arg = (int)strlen(option_definitions[i].arg_name); if(len_arg > max_len_arg) max_len_arg = len_arg; } } @@ -289,9 +292,9 @@ void help(int exitcode) { // Output options description. for( i = 0; i < num_opts; i++ ) { - fprintf(stream, " -%c %-*s %s", options[i].val, max_len_arg, options[i].arg_name ? options[i].arg_name : "", options[i].description); - if(options[i].default_value) { - fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", options[i].default_value); + fprintf(stream, " -%c %-*s %s", option_definitions[i].val, max_len_arg, option_definitions[i].arg_name ? option_definitions[i].arg_name : "", option_definitions[i].description); + if(option_definitions[i].default_value) { + fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", option_definitions[i].default_value); } else { fprintf(stream, "\n"); } @@ -316,7 +319,7 @@ void help(int exitcode) { ); fflush(stream); - exit(exitcode); + return exitcode; } // TODO: Remove this function with the nix major release. @@ -454,17 +457,23 @@ static void get_netdata_configured_variables() { } // ------------------------------------------------------------------------ - // let the plugins know the min update_every - // get system paths + netdata_configured_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", CONFIG_DIR); netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", LOG_DIR); - netdata_configured_plugins_dir = config_get(CONFIG_SECTION_GLOBAL, "plugins directory", PLUGINS_DIR); netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR); netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", CACHE_DIR); netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", VARLIB_DIR); netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", CACHE_DIR); + { + char plugins_dirs[(FILENAME_MAX * 2) + 1]; + snprintfz(plugins_dirs, FILENAME_MAX * 2, "\"%s\" \"%s/custom-plugins.d\"", PLUGINS_DIR, CONFIG_DIR); + netdata_configured_plugins_dir_base = strdupz(config_get(CONFIG_SECTION_GLOBAL, "plugins directory", plugins_dirs)); + quoted_strings_splitter(netdata_configured_plugins_dir_base, plugin_directories, PLUGINSD_MAX_DIRECTORIES, config_isspace); + netdata_configured_plugins_dir = plugin_directories[0]; + } + // ------------------------------------------------------------------------ // get default memory mode for the database @@ -489,6 +498,95 @@ static void get_netdata_configured_variables() { get_system_pid_max(); } +static void get_system_timezone(void) { + // avoid flood calls to stat(/etc/localtime) + // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux + const char *tz = getenv("TZ"); + if(!tz || !*tz) + setenv("TZ", config_get(CONFIG_SECTION_GLOBAL, "TZ environment variable", ":/etc/localtime"), 0); + + char buffer[FILENAME_MAX + 1] = ""; + const char *timezone = NULL; + ssize_t ret; + + // use the TZ variable + if(tz && *tz && *tz != ':') { + timezone = tz; + // info("TIMEZONE: using TZ variable '%s'", timezone); + } + + // use the contents of /etc/timezone + if(!timezone && !read_file("/etc/timezone", buffer, FILENAME_MAX)) { + timezone = buffer; + // info("TIMEZONE: using the contents of /etc/timezone: '%s'", timezone); + } + + // read the link /etc/localtime + if(!timezone) { + ret = readlink("/etc/localtime", buffer, FILENAME_MAX); + + if(ret > 0) { + buffer[ret] = '\0'; + + char *cmp = "/usr/share/zoneinfo/"; + size_t cmp_len = strlen(cmp); + + char *s = strstr(buffer, cmp); + if (s && s[cmp_len]) { + timezone = &s[cmp_len]; + // info("TIMEZONE: using the link of /etc/localtime: '%s'", timezone); + } + } + else + buffer[0] = '\0'; + } + + // find the timezone from strftime() + if(!timezone) { + time_t t; + struct tm *tmp, tmbuf; + + t = now_realtime_sec(); + tmp = localtime_r(&t, &tmbuf); + + if (tmp != NULL) { + if(strftime(buffer, FILENAME_MAX, "%Z", tmp) == 0) + buffer[0] = '\0'; + else { + buffer[FILENAME_MAX] = '\0'; + timezone = buffer; + // info("TIMEZONE: using strftime(): '%s'", timezone); + } + } + } + + if(timezone && *timezone) { + // make sure it does not have illegal characters + // info("TIMEZONE: fixing '%s'", timezone); + + size_t len = strlen(timezone); + char tmp[len + 1]; + char *d = tmp; + *d = '\0'; + + while(*timezone) { + if(isalnum(*timezone) || *timezone == '_' || *timezone == '/') + *d++ = *timezone++; + else + timezone++; + } + *d = '\0'; + strncpyz(buffer, tmp, len); + timezone = buffer; + // info("TIMEZONE: fixed as '%s'", timezone); + } + + if(!timezone || !*timezone) + timezone = "unknown"; + + netdata_configured_timezone = config_get(CONFIG_SECTION_GLOBAL, "timezone", timezone); +} + void set_global_environment() { { char b[16]; @@ -506,11 +604,7 @@ void set_global_environment() { setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1); setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1); - // avoid flood calls to stat(/etc/localtime) - // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux - const char *tz = getenv("TZ"); - if(!tz || !*tz) - setenv("TZ", config_get(CONFIG_SECTION_GLOBAL, "TZ environment variable", ":/etc/localtime"), 0); + get_system_timezone(); // set the path we need char path[1024 + 1], *p = getenv("PATH"); @@ -571,14 +665,14 @@ int main(int argc, char **argv) { // parse options { - int num_opts = sizeof(options) / sizeof(struct option_def); + int num_opts = sizeof(option_definitions) / sizeof(struct option_def); char optstring[(num_opts * 2) + 1]; int string_i = 0; for( i = 0; i < num_opts; i++ ) { - optstring[string_i] = options[i].val; + optstring[string_i] = option_definitions[i].val; string_i++; - if(options[i].arg_name) { + if(option_definitions[i].arg_name) { optstring[string_i] = ':'; string_i++; } @@ -593,7 +687,7 @@ int main(int argc, char **argv) { case 'c': if(config_load(optarg, 1) != 1) { error("Cannot load configuration file %s.", optarg); - exit(1); + return 1; } else { debug(D_OPTIONS, "Configuration loaded from %s.", optarg); @@ -604,8 +698,7 @@ int main(int argc, char **argv) { dont_fork = 1; break; case 'h': - help(0); - break; + return help(0); case 'i': config_set(CONFIG_SECTION_WEB, "bind to", optarg); break; @@ -635,8 +728,8 @@ int main(int argc, char **argv) { char* debug_flags_string = "debug_flags="; if(strcmp(optarg, "unittest") == 0) { - if(unit_test_buffer()) exit(1); - if(unit_test_str2ld()) exit(1); + if(unit_test_buffer()) return 1; + if(unit_test_str2ld()) return 1; //default_rrd_update_every = 1; //default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; //if(!config_loaded) config_load(NULL, 0); @@ -646,10 +739,10 @@ int main(int argc, char **argv) { default_health_enabled = 0; rrd_init("unittest"); default_rrdpush_enabled = 0; - if(run_all_mockup_tests()) exit(1); - if(unit_test_storage()) exit(1); + if(run_all_mockup_tests()) return 1; + if(unit_test_storage()) return 1; fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); - exit(0); + return 0; } else if(strcmp(optarg, "simple-pattern") == 0) { if(optind + 2 > argc) { @@ -673,24 +766,25 @@ int main(int argc, char **argv) { " -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n" "\n" ); - exit(1); + return 1; } const char *heystack = argv[optind]; const char *needle = argv[optind + 1]; + size_t len = strlen(needle) + 1; + char wildcarded[len]; - SIMPLE_PATTERN *p = simple_pattern_create(heystack - , SIMPLE_PATTERN_EXACT); - int ret = simple_pattern_matches(p, needle); + SIMPLE_PATTERN *p = simple_pattern_create(heystack, SIMPLE_PATTERN_EXACT); + int ret = simple_pattern_matches_extract(p, needle, wildcarded, len); simple_pattern_free(p); if(ret) { - fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s'\n", heystack, needle); - exit(0); + fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", heystack, needle, wildcarded); + return 0; } else { - fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s'\n", heystack, needle); - exit(1); + fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", heystack, needle, wildcarded); + return 1; } } else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) { @@ -716,7 +810,7 @@ int main(int argc, char **argv) { " parameters." "\n" ); - exit(1); + return 1; } const char *section = argv[optind]; const char *key = argv[optind + 1]; @@ -741,7 +835,7 @@ int main(int argc, char **argv) { " -c netdata.conf has to be given before -W get.\n" "\n" ); - exit(1); + return 1; } if(!config_loaded) { @@ -757,18 +851,18 @@ int main(int argc, char **argv) { const char *def = argv[optind + 2]; const char *value = config_get(section, key, def); printf("%s\n", value); - exit(0); + return 0; } else { fprintf(stderr, "Unknown -W parameter '%s'\n", optarg); - help(1); + return help(1); } } break; + default: /* ? */ fprintf(stderr, "Unknown parameter '%c'\n", opt); - help(1); - break; + return help(1); } } } @@ -906,6 +1000,7 @@ int main(int argc, char **argv) { // -------------------------------------------------------------------- // create the listening sockets + web_client_api_v1_init(); web_server_threading_selection(); if(web_server_mode != WEB_SERVER_MODE_NONE) @@ -997,4 +1092,8 @@ int main(int argc, char **argv) { // Handle signals signals_handle(); + + // should never reach this point + // but we need it for rpmlint #2752 + return 1; } @@ -16,12 +16,6 @@ struct option_def { const char *default_value; }; -/** - * List of command line options. - * This can be used to compute manpage, help messages, ect. - */ -extern struct option_def options[]; - struct netdata_static_thread { char *name; diff --git a/src/plugin_checks.c b/src/plugin_checks.c index 3a0a83bd..9c1e42cc 100644 --- a/src/plugin_checks.c +++ b/src/plugin_checks.c @@ -1,5 +1,7 @@ #include "common.h" +#ifdef NETDATA_INTERNAL_CHECKS + void *checks_main(void *ptr) { struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; @@ -16,18 +18,55 @@ void *checks_main(void *ptr) { RRDSET *check1, *check2, *check3, *apps_cpu = NULL; - check1 = rrdset_create_localhost("netdata", "check1", NULL, "netdata", NULL, "Caller gives microseconds" - , "a million !", 99999, localhost->rrd_update_every, RRDSET_TYPE_LINE); + check1 = rrdset_create_localhost( + "netdata" + , "check1" + , NULL + , "netdata" + , NULL + , "Caller gives microseconds" + , "a million !" + , "netdata" + , "checks" + , 99999 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); + rrddim_add(check1, "absolute", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(check1, "incremental", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - check2 = rrdset_create_localhost("netdata", "check2", NULL, "netdata", NULL, "Netdata calcs microseconds" - , "a million !", 99999, localhost->rrd_update_every, RRDSET_TYPE_LINE); + check2 = rrdset_create_localhost( + "netdata" + , "check2" + , NULL + , "netdata" + , NULL + , "Netdata calcs microseconds" + , "a million !" + , "netdata" + , "checks" + , 99999 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); rrddim_add(check2, "absolute", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(check2, "incremental", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - check3 = rrdset_create_localhost("netdata", "checkdt", NULL, "netdata", NULL, "Clock difference" - , "microseconds diff", 99999, localhost->rrd_update_every, RRDSET_TYPE_LINE); + check3 = rrdset_create_localhost( + "netdata" + , "checkdt" + , NULL + , "netdata" + , NULL + , "Clock difference" + , "microseconds diff" + , "netdata" + , "checks" + , 99999 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); rrddim_add(check3, "caller", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(check3, "netdata", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -87,3 +126,4 @@ void *checks_main(void *ptr) { return NULL; } +#endif // NETDATA_INTERNAL_CHECKS diff --git a/src/plugin_checks.h b/src/plugin_checks.h index c27685b8..05a40bea 100644 --- a/src/plugin_checks.h +++ b/src/plugin_checks.h @@ -1,6 +1,8 @@ #ifndef NETDATA_PLUGIN_CHECKS_H #define NETDATA_PLUGIN_CHECKS_H 1 +#ifdef NETDATA_INTERNAL_CHECKS void *checks_main(void *ptr); +#endif // NETDATA_INTERNAL_CHECKS #endif /* NETDATA_PLUGIN_PROC_H */ diff --git a/src/plugin_freebsd.c b/src/plugin_freebsd.c index c09b28a5..a7825d85 100644 --- a/src/plugin_freebsd.c +++ b/src/plugin_freebsd.c @@ -37,6 +37,7 @@ static struct freebsd_module { // CPU metrics { .name = "kern.cp_times", .dim = "cp_times", .enabled = 1, .func = do_kern_cp_times }, { .name = "dev.cpu.temperature", .dim = "cpu_temperature", .enabled = 1, .func = do_dev_cpu_temperature }, + { .name = "dev.cpu.0.freq", .dim = "cpu_frequency", .enabled = 1, .func = do_dev_cpu_0_freq }, // disk metrics { .name = "kern.devstat", .dim = "kern_devstat", .enabled = 1, .func = do_kern_devstat }, @@ -56,6 +57,7 @@ static struct freebsd_module { // ZFS metrics { .name = "kstat.zfs.misc.arcstats", .dim = "arcstats", .enabled = 1, .func = do_kstat_zfs_misc_arcstats }, + { .name = "kstat.zfs.misc.zio_trim", .dim = "trim", .enabled = 1, .func = do_kstat_zfs_misc_zio_trim }, // ipfw metrics { .name = "ipfw", .dim = "ipfw", .enabled = 1, .func = do_ipfw }, @@ -127,9 +129,20 @@ void *freebsd_main(void *ptr) { st = rrdset_find_bytype_localhost("netdata", "plugin_freebsd_modules"); if(!st) { - st = rrdset_create_localhost("netdata", "plugin_freebsd_modules", NULL, "freebsd", NULL - , "NetData FreeBSD Plugin Modules Durations", "milliseconds/run", 132001 - , localhost->rrd_update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost( + "netdata" + , "plugin_freebsd_modules" + , NULL + , "freebsd" + , NULL + , "NetData FreeBSD Plugin Modules Durations" + , "milliseconds/run" + , "netdata" + , "stats" + , 132001 + , localhost->rrd_update_every + , RRDSET_TYPE_STACKED + ); for(i = 0 ; freebsd_modules[i].name ;i++) { struct freebsd_module *pm = &freebsd_modules[i]; diff --git a/src/plugin_freebsd.h b/src/plugin_freebsd.h index 78fe33d7..0a6f40c1 100644 --- a/src/plugin_freebsd.h +++ b/src/plugin_freebsd.h @@ -18,6 +18,7 @@ extern int do_vm_vmtotal(int update_every, usec_t dt); extern int do_kern_cp_time(int update_every, usec_t dt); extern int do_kern_cp_times(int update_every, usec_t dt); extern int do_dev_cpu_temperature(int update_every, usec_t dt); +extern int do_dev_cpu_0_freq(int update_every, usec_t dt); extern int do_hw_intcnt(int update_every, usec_t dt); extern int do_vm_stats_sys_v_intr(int update_every, usec_t dt); extern int do_vm_stats_sys_v_soft(int update_every, usec_t dt); @@ -43,6 +44,7 @@ extern int do_getifaddrs(int update_every, usec_t dt); extern int do_getmntinfo(int update_every, usec_t dt); extern int do_kern_devstat(int update_every, usec_t dt); extern int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt); +extern int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt); extern int do_ipfw(int update_every, usec_t dt); #define GETSYSCTL_MIB(name, mib) getsysctl_mib(name, mib, sizeof(mib)/sizeof(int)) diff --git a/src/plugin_idlejitter.c b/src/plugin_idlejitter.c index 89f49023..8d933683 100644 --- a/src/plugin_idlejitter.c +++ b/src/plugin_idlejitter.c @@ -27,6 +27,8 @@ void *cpuidlejitter_main(void *ptr) { , NULL , "CPU Idle Jitter" , "microseconds lost/s" + , "idlejitter" + , NULL , 9999 , localhost->rrd_update_every , RRDSET_TYPE_AREA diff --git a/src/plugin_nfacct.c b/src/plugin_nfacct.c index 4c691be0..8319c672 100644 --- a/src/plugin_nfacct.c +++ b/src/plugin_nfacct.c @@ -302,6 +302,8 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker New Connections" , "connections/s" + , "nfacct" + , NULL , 3001 , nfstat_root.update_every , RRDSET_TYPE_LINE @@ -336,6 +338,8 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Changes" , "changes/s" + , "nfacct" + , NULL , 3002 , nfstat_root.update_every , RRDSET_TYPE_LINE @@ -371,6 +375,8 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Searches" , "searches/s" + , "nfacct" + , NULL , 3010 , nfstat_root.update_every , RRDSET_TYPE_LINE @@ -406,6 +412,8 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Errors" , "events/s" + , "nfacct" + , NULL , 3005 , nfstat_root.update_every , RRDSET_TYPE_LINE @@ -443,6 +451,8 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Expectations" , "expectations/s" + , "nfacct" + , NULL , 3003 , nfstat_root.update_every , RRDSET_TYPE_LINE @@ -661,6 +671,8 @@ static void nfacct_send_metrics() { , NULL , "Netfilter Accounting Packets" , "packets/s" + , "nfacct" + , NULL , 3206 , nfacct_root.update_every , RRDSET_TYPE_STACKED @@ -702,6 +714,8 @@ static void nfacct_send_metrics() { , NULL , "Netfilter Accounting Bandwidth" , "kilobytes/s" + , "nfacct" + , NULL , 3207 , nfacct_root.update_every , RRDSET_TYPE_STACKED diff --git a/src/plugin_proc.c b/src/plugin_proc.c index e64f5739..c4249c84 100644 --- a/src/plugin_proc.c +++ b/src/plugin_proc.c @@ -32,6 +32,8 @@ static struct proc_module { // network metrics { .name = "/proc/net/dev", .dim = "netdev", .func = do_proc_net_dev }, + { .name = "/proc/net/sockstat", .dim = "sockstat", .func = do_proc_net_sockstat }, + { .name = "/proc/net/sockstat6", .dim = "sockstat6", .func = do_proc_net_sockstat6 }, { .name = "/proc/net/netstat", .dim = "netstat", .func = do_proc_net_netstat }, // this has to be before /proc/net/snmp, because there is a shared metric { .name = "/proc/net/snmp", .dim = "snmp", .func = do_proc_net_snmp }, { .name = "/proc/net/snmp6", .dim = "snmp6", .func = do_proc_net_snmp6 }, @@ -118,9 +120,20 @@ void *proc_main(void *ptr) { st = rrdset_find_bytype_localhost("netdata", "plugin_proc_modules"); if(!st) { - st = rrdset_create_localhost("netdata", "plugin_proc_modules", NULL, "proc", NULL - , "NetData Proc Plugin Modules Durations", "milliseconds/run", 132001 - , localhost->rrd_update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost( + "netdata" + , "plugin_proc_modules" + , NULL + , "proc" + , NULL + , "NetData Proc Plugin Modules Durations" + , "milliseconds/run" + , "netdata" + , "stats" + , 132001 + , localhost->rrd_update_every + , RRDSET_TYPE_STACKED + ); for(i = 0 ; proc_modules[i].name ;i++) { struct proc_module *pm = &proc_modules[i]; diff --git a/src/plugin_proc.h b/src/plugin_proc.h index 72cfc6aa..fa567544 100644 --- a/src/plugin_proc.h +++ b/src/plugin_proc.h @@ -26,6 +26,8 @@ extern int do_proc_uptime(int update_every, usec_t dt); extern int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt); extern int do_proc_sys_devices_system_node(int update_every, usec_t dt); extern int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt); +extern int do_proc_net_sockstat(int update_every, usec_t dt); +extern int do_proc_net_sockstat6(int update_every, usec_t dt); extern int get_numa_node_count(void); diff --git a/src/plugin_proc_diskspace.c b/src/plugin_proc_diskspace.c index 52c1f5ae..e41e7618 100644 --- a/src/plugin_proc_diskspace.c +++ b/src/plugin_proc_diskspace.c @@ -227,6 +227,12 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { fsfilcnt_t freserved_root = favail_root - favail; fsfilcnt_t fused = ftotal - favail_root; + if(m->do_inodes == CONFIG_BOOLEAN_AUTO && favail == (fsfilcnt_t)-1) { + // this file system does not support inodes reporting + // eg. cephfs + m->do_inodes = CONFIG_BOOLEAN_NO; + } + #ifdef NETDATA_INTERNAL_CHECKS if(unlikely(btotal != bavail + breserved_root + bused)) error("DISKSPACE: disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused); @@ -251,6 +257,8 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { , "disk.space" , title , "GB" + , "diskspace" + , NULL , 2023 , update_every , RRDSET_TYPE_STACKED @@ -289,6 +297,8 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { , "disk.inodes" , title , "Inodes" + , "diskspace" + , NULL , 2024 , update_every , RRDSET_TYPE_STACKED @@ -384,21 +394,21 @@ void *proc_diskspace_main(void *ptr) { getrusage(RUSAGE_THREAD, &thread); - if(!stcpu_thread) { - stcpu_thread = rrdset_find_localhost("netdata.plugin_diskspace"); - if(!stcpu_thread) - stcpu_thread = rrdset_create_localhost( - "netdata" - , "plugin_diskspace" - , NULL - , "diskspace" - , NULL - , "NetData Disk Space Plugin CPU usage" - , "milliseconds/s" - , 132020 - , update_every - , RRDSET_TYPE_STACKED - ); + if(unlikely(!stcpu_thread)) { + stcpu_thread = rrdset_create_localhost( + "netdata" + , "plugin_diskspace" + , NULL + , "diskspace" + , NULL + , "NetData Disk Space Plugin CPU usage" + , "milliseconds/s" + , "diskspace" + , NULL + , 132020 + , update_every + , RRDSET_TYPE_STACKED + ); rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); @@ -412,21 +422,21 @@ void *proc_diskspace_main(void *ptr) { // ---------------------------------------------------------------- - if(!st_duration) { - st_duration = rrdset_find_localhost("netdata.plugin_diskspace_dt"); - if(!st_duration) - st_duration = rrdset_create_localhost( - "netdata" - , "plugin_diskspace_dt" - , NULL - , "diskspace" - , NULL - , "NetData Disk Space Plugin Duration" - , "milliseconds/run" - , 132021 - , update_every - , RRDSET_TYPE_AREA - ); + if(unlikely(!st_duration)) { + st_duration = rrdset_create_localhost( + "netdata" + , "plugin_diskspace_dt" + , NULL + , "diskspace" + , NULL + , "NetData Disk Space Plugin Duration" + , "milliseconds/run" + , "diskspace" + , NULL + , 132021 + , update_every + , RRDSET_TYPE_AREA + ); rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } diff --git a/src/plugin_tc.c b/src/plugin_tc.c index c928e61b..0d8fd3d6 100644 --- a/src/plugin_tc.c +++ b/src/plugin_tc.c @@ -81,6 +81,7 @@ struct tc_device { avl_tree classes_index; struct tc_class *classes; + struct tc_class *last_class; struct tc_device *next; struct tc_device *prev; @@ -139,11 +140,19 @@ static inline struct tc_class *tc_class_index_find(struct tc_device *st, const c static inline void tc_class_free(struct tc_device *n, struct tc_class *c) { if(c == n->classes) { - if(c->next) + if(likely(c->next)) n->classes = c->next; else n->classes = c->prev; } + + if(c == n->last_class) { + if(unlikely(c->next)) + n->last_class = c->next; + else + n->last_class = c->prev; + } + if(c->next) c->next->prev = c->prev; if(c->prev) c->prev->next = c->next; @@ -374,11 +383,20 @@ static inline void tc_device_commit(struct tc_device *d) { d->enabled_bytes = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_bytes)) - d->st_bytes = rrdset_create_localhost(RRD_TYPE_TC, d->id, d->name ? d->name : d->id - , d->family ? d->family : d->id, RRD_TYPE_TC ".qos", "Class Usage" - , "kilobits/s", 7000, localhost->rrd_update_every - , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE - : RRDSET_TYPE_STACKED); + d->st_bytes = rrdset_create_localhost( + RRD_TYPE_TC + , d->id + , d->name ? d->name : d->id + , d->family ? d->family : d->id + , RRD_TYPE_TC ".qos" + , "Class Usage" + , "kilobits/s" + , "tc" + , NULL + , 7000 + , localhost->rrd_update_every + , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED + ); else { rrdset_next(d->st_bytes); @@ -413,10 +431,20 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id); - d->st_packets = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id - , RRD_TYPE_TC ".qos_packets", "Class Packets", "packets/s", 7010 - , localhost->rrd_update_every, d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE - : RRDSET_TYPE_STACKED); + d->st_packets = rrdset_create_localhost( + RRD_TYPE_TC + , id + , name + , d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_packets" + , "Class Packets" + , "packets/s" + , "tc" + , NULL + , 7010 + , localhost->rrd_update_every + , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED + ); } else { rrdset_next(d->st_packets); @@ -456,11 +484,20 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id); - d->st_dropped = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id - , RRD_TYPE_TC ".qos_dropped", "Class Dropped Packets", "packets/s" - , 7020, localhost->rrd_update_every - , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE - : RRDSET_TYPE_STACKED); + d->st_dropped = rrdset_create_localhost( + RRD_TYPE_TC + , id + , name + , d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_dropped" + , "Class Dropped Packets" + , "packets/s" + , "tc" + , NULL + , 7020 + , localhost->rrd_update_every + , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED + ); } else { rrdset_next(d->st_dropped); @@ -500,9 +537,20 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_tokens", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id); - d->st_tokens = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id - , RRD_TYPE_TC ".qos_tokens", "Class Tokens", "tokens", 7030 - , localhost->rrd_update_every, RRDSET_TYPE_LINE); + d->st_tokens = rrdset_create_localhost( + RRD_TYPE_TC + , id + , name + , d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_tokens" + , "Class Tokens" + , "tokens" + , "tc" + , NULL + , 7030 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); } else { rrdset_next(d->st_tokens); @@ -543,9 +591,20 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_ctokens", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id); - d->st_ctokens = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id - , RRD_TYPE_TC ".qos_ctokens", "Class cTokens", "ctokens", 7040 - , localhost->rrd_update_every, RRDSET_TYPE_LINE); + d->st_ctokens = rrdset_create_localhost( + RRD_TYPE_TC + , id + , name + , d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_ctokens" + , "Class cTokens" + , "ctokens" + , "tc" + , NULL + , 7040 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); } else { debug(D_TC_LOOP, "TC: Updating _ctokens chart for device '%s'", d->name?d->name:d->id); @@ -605,7 +664,7 @@ static inline void tc_device_set_device_name(struct tc_device *d, char *name) { d->name = NULL; } - if(likely(name && *name && strcmp(d->id, name))) { + if(likely(name && *name && strcmp(d->id, name) != 0)) { debug(D_TC_LOOP, "TC: Setting device '%s' name to '%s'", d->id, name); d->name = strdupz(name); d->name_updated = 1; @@ -663,9 +722,15 @@ static inline struct tc_class *tc_class_add(struct tc_device *n, char *id, char c = callocz(1, sizeof(struct tc_class)); - if(n->classes) n->classes->prev = c; - c->next = n->classes; - n->classes = c; + if(unlikely(!n->classes)) + n->classes = c; + + else if(likely(n->last_class)) { + n->last_class->next = c; + c->prev = n->last_class; + } + + n->last_class = c; c->id = strdupz(id); c->hash = simple_hash(c->id); @@ -776,7 +841,6 @@ void *tc_main(void *ptr) { error("Cannot set pthread cancel state to ENABLE."); struct rusage thread; - RRDSET *stcpu = NULL, *sttime = NULL; char buffer[TC_LINE_MAX+1] = ""; char *words[PLUGINSD_MAX_WORDS] = { NULL }; @@ -989,30 +1053,56 @@ void *tc_main(void *ptr) { // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]); getrusage(RUSAGE_THREAD, &thread); - if(unlikely(!stcpu)) stcpu = rrdset_find_localhost("netdata.plugin_tc_cpu"); + static RRDSET *stcpu = NULL; + static RRDDIM *rd_user = NULL, *rd_system = NULL; + if(unlikely(!stcpu)) { - stcpu = rrdset_create_localhost("netdata", "plugin_tc_cpu", NULL, "tc.helper", NULL - , "NetData TC CPU usage", "milliseconds/s", 135000, localhost->rrd_update_every - , RRDSET_TYPE_STACKED); - rrddim_add(stcpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(stcpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + stcpu = rrdset_create_localhost( + "netdata" + , "plugin_tc_cpu" + , NULL + , "tc.helper" + , NULL + , "NetData TC CPU usage" + , "milliseconds/s" + , "tc" + , NULL + , 135000 + , localhost->rrd_update_every + , RRDSET_TYPE_STACKED + ); + rd_user = rrddim_add(stcpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rd_system = rrddim_add(stcpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu); - rrddim_set(stcpu, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); - rrddim_set(stcpu, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); + rrddim_set_by_pointer(stcpu, rd_user , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); + rrddim_set_by_pointer(stcpu, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); rrdset_done(stcpu); - if(unlikely(!sttime)) sttime = rrdset_find_localhost("netdata.plugin_tc_time"); + static RRDSET *sttime = NULL; + static RRDDIM *rd_run_time = NULL; + if(unlikely(!sttime)) { - sttime = rrdset_create_localhost("netdata", "plugin_tc_time", NULL, "tc.helper", NULL - , "NetData TC script execution", "milliseconds/run", 135001 - , localhost->rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(sttime, "run_time", "run time", 1, 1, RRD_ALGORITHM_ABSOLUTE); + sttime = rrdset_create_localhost( + "netdata" + , "plugin_tc_time" + , NULL + , "tc.helper" + , NULL + , "NetData TC script execution" + , "milliseconds/run" + , "tc" + , NULL + , 135001 + , localhost->rrd_update_every + , RRDSET_TYPE_AREA + ); + rd_run_time = rrddim_add(sttime, "run_time", "run time", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(sttime); - rrddim_set(sttime, "run_time", atoll(words[1])); + rrddim_set_by_pointer(sttime, rd_run_time, str2ll(words[1], NULL)); rrdset_done(sttime); } diff --git a/src/plugins_d.c b/src/plugins_d.c index 42433b55..d0f29f4d 100644 --- a/src/plugins_d.c +++ b/src/plugins_d.c @@ -1,5 +1,8 @@ #include "common.h" +char *plugin_directories[PLUGINSD_MAX_DIRECTORIES] = { NULL }; +char *netdata_configured_plugins_dir_base; + struct plugind *pluginsd_root = NULL; static inline int pluginsd_space(char c) { @@ -16,13 +19,27 @@ static inline int pluginsd_space(char c) { } } +inline int config_isspace(char c) { + switch(c) { + case ' ': + case '\t': + case '\r': + case '\n': + case ',': + return 1; + + default: + return 0; + } +} + // split a text into words, respecting quotes -inline int pluginsd_split_words(char *str, char **words, int max_words) { +inline int quoted_strings_splitter(char *str, char **words, int max_words, int (*custom_isspace)(char)) { char *s = str, quote = 0; int i = 0, j; // skip all white space - while(unlikely(pluginsd_space(*s))) s++; + while(unlikely(custom_isspace(*s))) s++; // check for quote if(unlikely(*s == '\'' || *s == '"')) { @@ -49,13 +66,13 @@ inline int pluginsd_split_words(char *str, char **words, int max_words) { } // if it is a space - else if(unlikely(quote == 0 && pluginsd_space(*s))) { + else if(unlikely(quote == 0 && custom_isspace(*s))) { // terminate the word *s++ = '\0'; // skip all white space - while(likely(pluginsd_space(*s))) s++; + while(likely(custom_isspace(*s))) s++; // check for quote if(unlikely(*s == '\'' || *s == '"')) { @@ -82,6 +99,10 @@ inline int pluginsd_split_words(char *str, char **words, int max_words) { return i; } +inline int pluginsd_split_words(char *str, char **words, int max_words) { + return quoted_strings_splitter(str, words, max_words, pluginsd_space); +} + inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations) { int enabled = cd->enabled; @@ -101,6 +122,7 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int uint32_t CHART_HASH = simple_hash(PLUGINSD_KEYWORD_CHART); uint32_t DIMENSION_HASH = simple_hash(PLUGINSD_KEYWORD_DIMENSION); uint32_t DISABLE_HASH = simple_hash(PLUGINSD_KEYWORD_DISABLE); + uint32_t VARIABLE_HASH = simple_hash(PLUGINSD_KEYWORD_VARIABLE); RRDSET *st = NULL; uint32_t hash; @@ -212,10 +234,6 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int count++; } - else if(likely(hash == FLUSH_HASH && !strcmp(s, PLUGINSD_KEYWORD_FLUSH))) { - debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a FLUSH", cd->fullfilename); - st = NULL; - } else if(likely(hash == CHART_HASH && !strcmp(s, PLUGINSD_KEYWORD_CHART))) { st = NULL; @@ -229,6 +247,8 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int char *priority_s = words[8]; char *update_every_s = words[9]; char *options = words[10]; + char *plugin = words[11]; + char *module = words[12]; // parse the id from type char *id = NULL; @@ -275,22 +295,31 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int if(unlikely(!title)) title = ""; if(unlikely(!units)) units = "unknown"; - st = rrdset_find_bytype(host, type, id); - if(unlikely(!st)) { - debug(D_PLUGINSD, "PLUGINSD: Creating chart type='%s', id='%s', name='%s', family='%s', context='%s', chart='%s', priority=%d, update_every=%d" - , type, id - , name?name:"" - , family?family:"" - , context?context:"" - , rrdset_type_name(chart_type) - , priority - , update_every - ); - - st = rrdset_create(host, type, id, name, family, context, title, units, priority, update_every, chart_type); - cd->update_every = update_every; - } - else debug(D_PLUGINSD, "PLUGINSD: Chart '%s' already exists. Not adding it again.", st->id); + debug(D_PLUGINSD, "PLUGINSD: Creating chart type='%s', id='%s', name='%s', family='%s', context='%s', chart='%s', priority=%d, update_every=%d" + , type, id + , name?name:"" + , family?family:"" + , context?context:"" + , rrdset_type_name(chart_type) + , priority + , update_every + ); + + st = rrdset_create( + host + , type + , id + , name + , family + , context + , title + , units + , (plugin && *plugin)?plugin:cd->filename + , module + , priority + , update_every + , chart_type + ); if(options && *options) { if(strstr(options, "obsolete")) @@ -308,6 +337,11 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int else rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST); } + else { + rrdset_isnot_obsolete(st); + rrdset_flag_clear(st, RRDSET_FLAG_DETAIL); + rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST); + } } else if(likely(hash == DIMENSION_HASH && !strcmp(s, PLUGINSD_KEYWORD_DIMENSION))) { char *id = words[1]; @@ -359,6 +393,64 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int if(strstr(options, "nooverflow") != NULL) rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); } } + else if(likely(hash == VARIABLE_HASH && !strcmp(s, PLUGINSD_KEYWORD_VARIABLE))) { + char *name = words[1]; + char *value = words[2]; + int global = (st)?0:1; + + if(name && *name) { + if((strcmp(name, "GLOBAL") == 0 || strcmp(name, "HOST") == 0)) { + global = 1; + name = words[2]; + value = words[3]; + } + else if((strcmp(name, "LOCAL") == 0 || strcmp(name, "CHART") == 0)) { + global = 0; + name = words[2]; + value = words[3]; + } + } + + if(unlikely(!name || !*name)) { + error("PLUGINSD: '%s' is requesting a VARIABLE on host '%s', without a variable name. Disabling it.", cd->fullfilename, host->hostname); + enabled = 0; + break; + } + + if(unlikely(!value || !*value)) + value = NULL; + + if(value) { + char *endptr = NULL; + calculated_number v = (calculated_number)str2ld(value, &endptr); + + if(unlikely(endptr && *endptr)) { + if(endptr == value) + error("PLUGINSD: '%s': the value '%s' of VARIABLE '%s' on host '%s' cannot be parsed as a number", cd->fullfilename, value, name, host->hostname); + else + error("PLUGINSD: '%s': the value '%s' of VARIABLE '%s' on host '%s' has leftovers: '%s'", cd->fullfilename, value, name, host->hostname, endptr); + } + + if(global) { + RRDVAR *rv = rrdvar_custom_host_variable_create(host, name); + if (rv) rrdvar_custom_host_variable_set(host, rv, v); + else error("PLUGINSD: '%s': cannot find/create HOST VARIABLE '%s' on host '%s'", cd->fullfilename, name, host->hostname); + } + else if(st) { + RRDSETVAR *rs = rrdsetvar_custom_chart_variable_create(st, name); + if (rs) rrdsetvar_custom_chart_variable_set(rs, v); + else error("PLUGINSD: '%s': cannot find/create CHART VARIABLE '%s' on host '%s', chart '%s'", cd->fullfilename, name, host->hostname, st->id); + } + else + error("PLUGINSD: '%s': cannot find/create CHART VARIABLE '%s' on host '%s' without a chart", cd->fullfilename, name, host->hostname); + } + else + error("PLUGINSD: '%s': cannot set %s VARIABLE '%s' on host '%s' to an empty value", cd->fullfilename, (global)?"HOST":"CHART", name, host->hostname); + } + else if(likely(hash == FLUSH_HASH && !strcmp(s, PLUGINSD_KEYWORD_FLUSH))) { + debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a FLUSH", cd->fullfilename); + st = NULL; + } else if(unlikely(hash == DISABLE_HASH && !strcmp(s, PLUGINSD_KEYWORD_DISABLE))) { info("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename); enabled = 0; @@ -476,99 +568,131 @@ void *pluginsd_main(void *ptr) { int automatic_run = config_get_boolean(CONFIG_SECTION_PLUGINS, "enable running new plugins", 1); int scan_frequency = (int) config_get_number(CONFIG_SECTION_PLUGINS, "check for new plugins every", 60); - DIR *dir = NULL; - struct dirent *file = NULL; - struct plugind *cd; - - // enable the apps plugin by default - // config_get_boolean(CONFIG_SECTION_PLUGINS, "apps", 1); - if(scan_frequency < 1) scan_frequency = 1; + // store the errno for each plugins directory + // so that we don't log broken directories on each loop + int directory_errors[PLUGINSD_MAX_DIRECTORIES] = { 0 }; + for(;;) { if(unlikely(netdata_exit)) break; - dir = opendir(netdata_configured_plugins_dir); - if(unlikely(!dir)) { - error("Cannot open directory '%s'.", netdata_configured_plugins_dir); - goto cleanup; - } + int idx; + const char *directory_name; - while(likely((file = readdir(dir)))) { + for( idx = 0; idx < PLUGINSD_MAX_DIRECTORIES && (directory_name = plugin_directories[idx]) ; idx++ ) { if(unlikely(netdata_exit)) break; - debug(D_PLUGINSD, "PLUGINSD: Examining file '%s'", file->d_name); - - if(unlikely(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)) continue; - - int len = (int) strlen(file->d_name); - if(unlikely(len <= (int)PLUGINSD_FILE_SUFFIX_LEN)) continue; - if(unlikely(strcmp(PLUGINSD_FILE_SUFFIX, &file->d_name[len - (int)PLUGINSD_FILE_SUFFIX_LEN]) != 0)) { - debug(D_PLUGINSD, "PLUGINSD: File '%s' does not end in '%s'.", file->d_name, PLUGINSD_FILE_SUFFIX); + errno = 0; + DIR *dir = opendir(directory_name); + if(unlikely(!dir)) { + if(directory_errors[idx] != errno) { + directory_errors[idx] = errno; + error("PLUGINSD: Cannot open plugins directory '%s'.", directory_name); + } continue; } - char pluginname[CONFIG_MAX_NAME + 1]; - snprintfz(pluginname, CONFIG_MAX_NAME, "%.*s", (int)(len - PLUGINSD_FILE_SUFFIX_LEN), file->d_name); - int enabled = config_get_boolean(CONFIG_SECTION_PLUGINS, pluginname, automatic_run); + struct dirent *file = NULL; + while(likely((file = readdir(dir)))) { + if(unlikely(netdata_exit)) break; - if(unlikely(!enabled)) { - debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is not enabled", file->d_name); - continue; - } + debug(D_PLUGINSD, "PLUGINSD: Examining file '%s'", file->d_name); - // check if it runs already - for(cd = pluginsd_root ; cd ; cd = cd->next) - if(unlikely(strcmp(cd->filename, file->d_name) == 0)) break; + if(unlikely(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)) continue; - if(likely(cd && !cd->obsolete)) { - debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is already running", cd->filename); - continue; - } + int len = (int) strlen(file->d_name); + if(unlikely(len <= (int)PLUGINSD_FILE_SUFFIX_LEN)) continue; + if(unlikely(strcmp(PLUGINSD_FILE_SUFFIX, &file->d_name[len - (int)PLUGINSD_FILE_SUFFIX_LEN]) != 0)) { + debug(D_PLUGINSD, "PLUGINSD: File '%s' does not end in '%s'.", file->d_name, PLUGINSD_FILE_SUFFIX); + continue; + } + + char pluginname[CONFIG_MAX_NAME + 1]; + snprintfz(pluginname, CONFIG_MAX_NAME, "%.*s", (int)(len - PLUGINSD_FILE_SUFFIX_LEN), file->d_name); + int enabled = config_get_boolean(CONFIG_SECTION_PLUGINS, pluginname, automatic_run); + + if(unlikely(!enabled)) { + debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is not enabled", file->d_name); + continue; + } + + // check if it runs already + struct plugind *cd; + for(cd = pluginsd_root ; cd ; cd = cd->next) + if(unlikely(strcmp(cd->filename, file->d_name) == 0)) break; - // it is not running - // allocate a new one, or use the obsolete one - if(unlikely(!cd)) { - cd = callocz(sizeof(struct plugind), 1); + if(likely(cd && !cd->obsolete)) { + debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is already running", cd->filename); + continue; + } + + // it is not running + // allocate a new one, or use the obsolete one + if(unlikely(!cd)) { + cd = callocz(sizeof(struct plugind), 1); - snprintfz(cd->id, CONFIG_MAX_NAME, "plugin:%s", pluginname); + snprintfz(cd->id, CONFIG_MAX_NAME, "plugin:%s", pluginname); - strncpyz(cd->filename, file->d_name, FILENAME_MAX); - snprintfz(cd->fullfilename, FILENAME_MAX, "%s/%s", netdata_configured_plugins_dir, cd->filename); + strncpyz(cd->filename, file->d_name, FILENAME_MAX); + snprintfz(cd->fullfilename, FILENAME_MAX, "%s/%s", directory_name, cd->filename); - cd->enabled = enabled; - cd->update_every = (int) config_get_number(cd->id, "update every", localhost->rrd_update_every); - cd->started_t = now_realtime_sec(); + cd->enabled = enabled; + cd->update_every = (int) config_get_number(cd->id, "update every", localhost->rrd_update_every); + cd->started_t = now_realtime_sec(); - char *def = ""; - snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def)); + char *def = ""; + snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def)); - // link it - if(likely(pluginsd_root)) cd->next = pluginsd_root; - pluginsd_root = cd; + // link it + if(likely(pluginsd_root)) cd->next = pluginsd_root; + pluginsd_root = cd; - // it is not currently running - cd->obsolete = 1; + // it is not currently running + cd->obsolete = 1; - if(cd->enabled) { - // spawn a new thread for it - if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) - error("PLUGINSD: failed to create new thread for plugin '%s'.", cd->filename); + if(cd->enabled) { + // spawn a new thread for it + if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) + error("PLUGINSD: failed to create new thread for plugin '%s'.", cd->filename); - else if(unlikely(pthread_detach(cd->thread) != 0)) - error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename); + else if(unlikely(pthread_detach(cd->thread) != 0)) + error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename); + } } } + + closedir(dir); } - closedir(dir); sleep((unsigned int) scan_frequency); } -cleanup: info("PLUGINS.D thread exiting"); static_thread->enabled = 0; pthread_exit(NULL); return NULL; } + + +void pluginsd_stop_all_external_plugins() { + siginfo_t info; + struct plugind *cd; + for(cd = pluginsd_root ; cd ; cd = cd->next) { + if(cd->enabled && !cd->obsolete) { + info("Stopping %s plugin thread", cd->id); + pthread_cancel(cd->thread); + + if(cd->pid) { + info("killing %s plugin child process pid %d", cd->id, cd->pid); + if(killpid(cd->pid, SIGTERM) != -1) + waitid(P_PID, (id_t) cd->pid, &info, WEXITED); + + cd->pid = 0; + } + + cd->obsolete = 1; + } + } +} diff --git a/src/plugins_d.h b/src/plugins_d.h index 595a515c..4d708386 100644 --- a/src/plugins_d.h +++ b/src/plugins_d.h @@ -11,10 +11,14 @@ #define PLUGINSD_KEYWORD_END "END" #define PLUGINSD_KEYWORD_FLUSH "FLUSH" #define PLUGINSD_KEYWORD_DISABLE "DISABLE" +#define PLUGINSD_KEYWORD_VARIABLE "VARIABLE" #define PLUGINSD_LINE_MAX 1024 #define PLUGINSD_MAX_WORDS 20 +#define PLUGINSD_MAX_DIRECTORIES 20 +extern char *plugin_directories[PLUGINSD_MAX_DIRECTORIES]; + struct plugind { char id[CONFIG_MAX_NAME+1]; // config node id @@ -43,7 +47,12 @@ struct plugind { extern struct plugind *pluginsd_root; extern void *pluginsd_main(void *ptr); +extern void pluginsd_stop_all_external_plugins(void); + extern size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations); extern int pluginsd_split_words(char *str, char **words, int max_words); +extern int quoted_strings_splitter(char *str, char **words, int max_words, int (*custom_isspace)(char)); +extern int config_isspace(char c); + #endif /* NETDATA_PLUGINS_D_H */ diff --git a/src/proc_diskstats.c b/src/proc_diskstats.c index 4a32ec94..866e49c7 100644 --- a/src/proc_diskstats.c +++ b/src/proc_diskstats.c @@ -2,12 +2,13 @@ #define RRD_TYPE_DISK "disk" +#define DISK_TYPE_UNKNOWN 0 #define DISK_TYPE_PHYSICAL 1 #define DISK_TYPE_PARTITION 2 -#define DISK_TYPE_CONTAINER 3 +#define DISK_TYPE_VIRTUAL 3 #define CONFIG_SECTION_DISKSTATS "plugin:proc:/proc/diskstats" -#define DELAULT_EXLUDED_DISKS "loop* ram*" +#define DEFAULT_EXCLUDED_DISKS "loop* ram*" static struct disk { char *disk; // the name of the disk (sda, sdb, etc, after being looked up) @@ -31,16 +32,41 @@ static struct disk { int updated; - RRDSET *st_avgsz; - RRDSET *st_await; - RRDSET *st_backlog; RRDSET *st_io; - RRDSET *st_iotime; - RRDSET *st_mops; + RRDDIM *rd_io_reads; + RRDDIM *rd_io_writes; + RRDSET *st_ops; + RRDDIM *rd_ops_reads; + RRDDIM *rd_ops_writes; + RRDSET *st_qops; - RRDSET *st_svctm; + RRDDIM *rd_qops_operations; + + RRDSET *st_backlog; + RRDDIM *rd_backlog_backlog; + RRDSET *st_util; + RRDDIM *rd_util_utilization; + + RRDSET *st_mops; + RRDDIM *rd_mops_reads; + RRDDIM *rd_mops_writes; + + RRDSET *st_iotime; + RRDDIM *rd_iotime_reads; + RRDDIM *rd_iotime_writes; + + RRDSET *st_await; + RRDDIM *rd_await_reads; + RRDDIM *rd_await_writes; + + RRDSET *st_avgsz; + RRDDIM *rd_avgsz_reads; + RRDDIM *rd_avgsz_writes; + + RRDSET *st_svctm; + RRDDIM *rd_svctm_svctm; struct disk *next; } *disk_root = NULL; @@ -49,21 +75,23 @@ static struct disk { static char *path_to_get_hw_sector_size = NULL; static char *path_to_get_hw_sector_size_partitions = NULL; -static char *path_to_find_block_device = NULL; +static char *path_to_sys_dev_block_major_minor_string = NULL; +static char *path_to_sys_block_device = NULL; +static char *path_to_sys_devices_virtual_block_device = NULL; static char *path_to_device_mapper = NULL; +static char *path_to_device_label = NULL; +static char *path_to_device_id = NULL; +static int name_disks_by_id = CONFIG_BOOLEAN_NO; -static inline char *get_disk_name(unsigned long major, unsigned long minor, char *disk) { - static int enabled = 1; - - if(!enabled) goto cleanup; - +static inline int get_disk_name_from_path(const char *path, char *result, size_t result_size, unsigned long major, unsigned long minor, char *disk) { char filename[FILENAME_MAX + 1]; - char link[FILENAME_MAX + 1]; + int found = 0; - DIR *dir = opendir(path_to_device_mapper); + result_size--; + + DIR *dir = opendir(path); if (!dir) { - error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot open directory '%s'. Disabling device-mapper support.", disk, major, minor, path_to_device_mapper); - enabled = 0; + error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot open directory '%s'. Disabling device-mapper support.", disk, major, minor, path); goto cleanup; } @@ -71,18 +99,18 @@ static inline char *get_disk_name(unsigned long major, unsigned long minor, char while ((de = readdir(dir))) { if(de->d_type != DT_LNK) continue; - snprintfz(filename, FILENAME_MAX, "%s/%s", path_to_device_mapper, de->d_name); - ssize_t len = readlink(filename, link, FILENAME_MAX); + snprintfz(filename, FILENAME_MAX, "%s/%s", path, de->d_name); + ssize_t len = readlink(filename, result, result_size); if(len <= 0) { error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot read link '%s'.", disk, major, minor, filename); continue; } - link[len] = '\0'; - if(link[0] != '/') - snprintfz(filename, FILENAME_MAX, "%s/%s", path_to_device_mapper, link); + result[len] = '\0'; + if(result[0] != '/') + snprintfz(filename, FILENAME_MAX, "%s/%s", path, result); else - strncpyz(filename, link, FILENAME_MAX); + strncpyz(filename, result, FILENAME_MAX); struct stat sb; if(stat(filename, &sb) == -1) { @@ -102,17 +130,37 @@ static inline char *get_disk_name(unsigned long major, unsigned long minor, char // info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' matches.", disk, major, minor, filename); - strncpy(link, de->d_name, FILENAME_MAX); - netdata_fix_chart_name(link); - disk = link; + strncpy(result, de->d_name, result_size); + found = 1; break; } closedir(dir); + cleanup: - return strdupz(disk); + + if(!found) + result[0] = '\0'; + + return found; } +static inline char *get_disk_name(unsigned long major, unsigned long minor, char *disk) { + char result[FILENAME_MAX + 1] = ""; + + if(!path_to_device_mapper || !*path_to_device_mapper || !get_disk_name_from_path(path_to_device_mapper, result, FILENAME_MAX + 1, major, minor, disk)) + if(!path_to_device_label || !*path_to_device_label || !get_disk_name_from_path(path_to_device_label, result, FILENAME_MAX + 1, major, minor, disk)) + if(name_disks_by_id != CONFIG_BOOLEAN_YES || !path_to_device_id || !*path_to_device_id || !get_disk_name_from_path(path_to_device_id, result, FILENAME_MAX + 1, major, minor, disk)) + strncpy(result, disk, FILENAME_MAX); + + if(!result[0]) + strncpy(result, disk, FILENAME_MAX); + + netdata_fix_chart_name(result); + return strdup(result); +} + + static struct disk *get_disk(unsigned long major, unsigned long minor, char *disk) { static struct mountinfo *disk_mountinfo_root = NULL; @@ -134,7 +182,7 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis d->device = strdupz(disk); d->major = major; d->minor = minor; - d->type = DISK_TYPE_PHYSICAL; // Default type. Changed later if not correct. + d->type = DISK_TYPE_UNKNOWN; // Default type. Changed later if not correct. d->configured = 0; d->sector_size = 512; // the default, will be changed below d->next = NULL; @@ -148,33 +196,50 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis last->next = d; } + char buffer[FILENAME_MAX + 1]; + + // find if it is a physical disk + // by checking if /sys/block/DISK is readable. + snprintfz(buffer, FILENAME_MAX, path_to_sys_block_device, disk); + if(likely(access(buffer, R_OK) == 0)) { + // assign it here, but it will be overwritten if it is not a physical disk + d->type = DISK_TYPE_PHYSICAL; + } + // find if it is a partition // by checking if /sys/dev/block/MAJOR:MINOR/partition is readable. - char buffer[FILENAME_MAX + 1]; - snprintfz(buffer, FILENAME_MAX, path_to_find_block_device, major, minor, "partition"); + snprintfz(buffer, FILENAME_MAX, path_to_sys_dev_block_major_minor_string, major, minor, "partition"); if(likely(access(buffer, R_OK) == 0)) { d->type = DISK_TYPE_PARTITION; } else { - // find if it is a container - // by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries - snprintfz(buffer, FILENAME_MAX, path_to_find_block_device, major, minor, "slaves/"); - DIR *dirp = opendir(buffer); - if(likely(dirp != NULL)) { - struct dirent *dp; - while( (dp = readdir(dirp)) ) { - // . and .. are also files in empty folders. - if(unlikely(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) { - continue; + // find if it is a virtual disk + // by checking if /sys/devices/virtual/block/DISK is readable. + snprintfz(buffer, FILENAME_MAX, path_to_sys_devices_virtual_block_device, disk); + if(likely(access(buffer, R_OK) == 0)) { + d->type = DISK_TYPE_VIRTUAL; + } + else { + // find if it is a virtual device + // by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries + snprintfz(buffer, FILENAME_MAX, path_to_sys_dev_block_major_minor_string, major, minor, "slaves/"); + DIR *dirp = opendir(buffer); + if (likely(dirp != NULL)) { + struct dirent *dp; + while ((dp = readdir(dirp))) { + // . and .. are also files in empty folders. + if (unlikely(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) { + continue; + } + + d->type = DISK_TYPE_VIRTUAL; + + // Stop the loop after we found one file. + break; } - - d->type = DISK_TYPE_CONTAINER; - - // Stop the loop after we found one file. - break; + if (unlikely(closedir(dirp) == -1)) + error("Unable to close dir %s", buffer); } - if(unlikely(closedir(dirp) == -1)) - error("Unable to close dir %s", buffer); } } @@ -296,8 +361,14 @@ int do_proc_diskstats(int update_every, usec_t dt) { char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s"); + path_to_sys_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device", buffer); + + snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/block/%s"); + path_to_sys_devices_virtual_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get virtual block device", buffer); + snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/%s"); - path_to_find_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer); + path_to_sys_dev_block_major_minor_string = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer); snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size"); path_to_get_hw_sector_size = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer); @@ -307,6 +378,14 @@ int do_proc_diskstats(int update_every, usec_t dt) { snprintfz(buffer, FILENAME_MAX, "%s/dev/mapper", netdata_configured_host_prefix); path_to_device_mapper = config_get(CONFIG_SECTION_DISKSTATS, "path to device mapper", buffer); + + snprintfz(buffer, FILENAME_MAX, "%s/dev/disk/by-label", netdata_configured_host_prefix); + path_to_device_label = config_get(CONFIG_SECTION_DISKSTATS, "path to /dev/disk/by-label", buffer); + + snprintfz(buffer, FILENAME_MAX, "%s/dev/disk/by-id", netdata_configured_host_prefix); + path_to_device_id = config_get(CONFIG_SECTION_DISKSTATS, "path to /dev/disk/by-id", buffer); + + name_disks_by_id = config_get_boolean(CONFIG_SECTION_DISKSTATS, "name disks by id", name_disks_by_id); } // -------------------------------------------------------------------------- @@ -323,6 +402,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { size_t lines = procfile_lines(ff), l; + collected_number system_read_kb = 0, system_write_kb = 0; + for(l = 0; l < lines ;l++) { // -------------------------------------------------------------------------- // Read parameters @@ -398,6 +479,11 @@ int do_proc_diskstats(int update_every, usec_t dt) { struct disk *d = get_disk(major, minor, disk); d->updated = 1; + if(unlikely(d->type == DISK_TYPE_PHYSICAL)) { + system_read_kb += readsectors * d->sector_size / 1024; + system_write_kb += writesectors * d->sector_size / 1024; + } + // -------------------------------------------------------------------------- // Set its family based on mount point @@ -415,7 +501,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!excluded_disks)) { excluded_disks = simple_pattern_create( - config_get(CONFIG_SECTION_DISKSTATS, "exclude disks", DELAULT_EXLUDED_DISKS), + config_get(CONFIG_SECTION_DISKSTATS, "exclude disks", DEFAULT_EXCLUDED_DISKS), SIMPLE_PATTERN_EXACT ); } @@ -449,6 +535,10 @@ int do_proc_diskstats(int update_every, usec_t dt) { // based on the type of disk switch(d->type) { + default: + case DISK_TYPE_UNKNOWN: + break; + case DISK_TYPE_PHYSICAL: def_performance = global_enable_performance_for_physical_disks; break; @@ -457,7 +547,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { def_performance = global_enable_performance_for_partitions; break; - case DISK_TYPE_CONTAINER: + case DISK_TYPE_VIRTUAL: def_performance = global_enable_performance_for_virtual_disks; break; } @@ -518,18 +608,20 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.io" , "Disk I/O Bandwidth" , "kilobytes/s" + , "proc" + , "diskstats" , 2000 , update_every , RRDSET_TYPE_AREA ); - rrddim_add(d->st_io, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(d->st_io, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_INCREMENTAL); + d->rd_io_reads = rrddim_add(d->st_io, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_INCREMENTAL); + d->rd_io_writes = rrddim_add(d->st_io, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_io); - last_readsectors = rrddim_set(d->st_io, "reads", readsectors); - last_writesectors = rrddim_set(d->st_io, "writes", writesectors); + last_readsectors = rrddim_set_by_pointer(d->st_io, d->rd_io_reads, readsectors); + last_writesectors = rrddim_set_by_pointer(d->st_io, d->rd_io_writes, writesectors); rrdset_done(d->st_io); } @@ -547,6 +639,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.ops" , "Disk Completed I/O Operations" , "operations/s" + , "proc" + , "diskstats" , 2001 , update_every , RRDSET_TYPE_LINE @@ -554,13 +648,13 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_ops, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_ops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(d->st_ops, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_ops_reads = rrddim_add(d->st_ops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_ops_writes = rrddim_add(d->st_ops, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_ops); - last_reads = rrddim_set(d->st_ops, "reads", reads); - last_writes = rrddim_set(d->st_ops, "writes", writes); + last_reads = rrddim_set_by_pointer(d->st_ops, d->rd_ops_reads, reads); + last_writes = rrddim_set_by_pointer(d->st_ops, d->rd_ops_writes, writes); rrdset_done(d->st_ops); } @@ -578,6 +672,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.qops" , "Disk Current I/O Operations" , "operations" + , "proc" + , "diskstats" , 2002 , update_every , RRDSET_TYPE_LINE @@ -585,11 +681,11 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_qops, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_qops_operations = rrddim_add(d->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(d->st_qops); - rrddim_set(d->st_qops, "operations", queued_ios); + rrddim_set_by_pointer(d->st_qops, d->rd_qops_operations, queued_ios); rrdset_done(d->st_qops); } @@ -607,6 +703,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.backlog" , "Disk Backlog" , "backlog (ms)" + , "proc" + , "diskstats" , 2003 , update_every , RRDSET_TYPE_AREA @@ -614,11 +712,11 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_backlog, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_backlog, "backlog", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); + d->rd_backlog_backlog = rrddim_add(d->st_backlog, "backlog", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_backlog); - rrddim_set(d->st_backlog, "backlog", backlog_ms); + rrddim_set_by_pointer(d->st_backlog, d->rd_backlog_backlog, backlog_ms); rrdset_done(d->st_backlog); } @@ -636,6 +734,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.util" , "Disk Utilization Time" , "% of time working" + , "proc" + , "diskstats" , 2004 , update_every , RRDSET_TYPE_AREA @@ -643,11 +743,11 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_util, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_util, "utilization", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); + d->rd_util_utilization = rrddim_add(d->st_util, "utilization", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_util); - last_busy_ms = rrddim_set(d->st_util, "utilization", busy_ms); + last_busy_ms = rrddim_set_by_pointer(d->st_util, d->rd_util_utilization, busy_ms); rrdset_done(d->st_util); } @@ -665,6 +765,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.mops" , "Disk Merged Operations" , "merged operations/s" + , "proc" + , "diskstats" , 2021 , update_every , RRDSET_TYPE_LINE @@ -672,13 +774,13 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_mops, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_mops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(d->st_mops, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_mops_reads = rrddim_add(d->st_mops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_mops_writes = rrddim_add(d->st_mops, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_mops); - rrddim_set(d->st_mops, "reads", mreads); - rrddim_set(d->st_mops, "writes", mwrites); + rrddim_set_by_pointer(d->st_mops, d->rd_mops_reads, mreads); + rrddim_set_by_pointer(d->st_mops, d->rd_mops_writes, mwrites); rrdset_done(d->st_mops); } @@ -696,6 +798,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.iotime" , "Disk Total I/O Time" , "milliseconds/s" + , "proc" + , "diskstats" , 2022 , update_every , RRDSET_TYPE_LINE @@ -703,13 +807,13 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_iotime, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_iotime, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(d->st_iotime, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_iotime_reads = rrddim_add(d->st_iotime, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_iotime_writes = rrddim_add(d->st_iotime, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_iotime); - last_readms = rrddim_set(d->st_iotime, "reads", readms); - last_writems = rrddim_set(d->st_iotime, "writes", writems); + last_readms = rrddim_set_by_pointer(d->st_iotime, d->rd_iotime_reads, readms); + last_writems = rrddim_set_by_pointer(d->st_iotime, d->rd_iotime_writes, writems); rrdset_done(d->st_iotime); } @@ -730,6 +834,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.await" , "Average Completed I/O Operation Time" , "ms per operation" + , "proc" + , "diskstats" , 2005 , update_every , RRDSET_TYPE_LINE @@ -737,13 +843,13 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_await, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_await, "reads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(d->st_await, "writes", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_await_reads = rrddim_add(d->st_await, "reads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_await_writes = rrddim_add(d->st_await, "writes", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(d->st_await); - rrddim_set(d->st_await, "reads", (reads - last_reads) ? (readms - last_readms) / (reads - last_reads) : 0); - rrddim_set(d->st_await, "writes", (writes - last_writes) ? (writems - last_writems) / (writes - last_writes) : 0); + rrddim_set_by_pointer(d->st_await, d->rd_await_reads, (reads - last_reads) ? (readms - last_readms) / (reads - last_reads) : 0); + rrddim_set_by_pointer(d->st_await, d->rd_await_writes, (writes - last_writes) ? (writems - last_writems) / (writes - last_writes) : 0); rrdset_done(d->st_await); } @@ -759,6 +865,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.avgsz" , "Average Completed I/O Operation Bandwidth" , "kilobytes per operation" + , "proc" + , "diskstats" , 2006 , update_every , RRDSET_TYPE_AREA @@ -766,13 +874,13 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_avgsz, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_avgsz, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(d->st_avgsz, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_ABSOLUTE); + d->rd_avgsz_reads = rrddim_add(d->st_avgsz, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_ABSOLUTE); + d->rd_avgsz_writes = rrddim_add(d->st_avgsz, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(d->st_avgsz); - rrddim_set(d->st_avgsz, "reads", (reads - last_reads) ? (readsectors - last_readsectors) / (reads - last_reads) : 0); - rrddim_set(d->st_avgsz, "writes", (writes - last_writes) ? (writesectors - last_writesectors) / (writes - last_writes) : 0); + rrddim_set_by_pointer(d->st_avgsz, d->rd_avgsz_reads, (reads - last_reads) ? (readsectors - last_readsectors) / (reads - last_reads) : 0); + rrddim_set_by_pointer(d->st_avgsz, d->rd_avgsz_writes, (writes - last_writes) ? (writesectors - last_writesectors) / (writes - last_writes) : 0); rrdset_done(d->st_avgsz); } @@ -788,6 +896,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.svctm" , "Average Service Time" , "ms per operation" + , "proc" + , "diskstats" , 2007 , update_every , RRDSET_TYPE_LINE @@ -795,16 +905,52 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_flag_set(d->st_svctm, RRDSET_FLAG_DETAIL); - rrddim_add(d->st_svctm, "svctm", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_svctm_svctm = rrddim_add(d->st_svctm, "svctm", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(d->st_svctm); - rrddim_set(d->st_svctm, "svctm", ((reads - last_reads) + (writes - last_writes)) ? (busy_ms - last_busy_ms) / ((reads - last_reads) + (writes - last_writes)) : 0); + rrddim_set_by_pointer(d->st_svctm, d->rd_svctm_svctm, ((reads - last_reads) + (writes - last_writes)) ? (busy_ms - last_busy_ms) / ((reads - last_reads) + (writes - last_writes)) : 0); rrdset_done(d->st_svctm); } } } + + // ------------------------------------------------------------------------ + // update the system total I/O + + if(global_do_io == CONFIG_BOOLEAN_YES || (global_do_io == CONFIG_BOOLEAN_AUTO && (system_read_kb || system_write_kb))) { + static RRDSET *st_io = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if(unlikely(!st_io)) { + st_io = rrdset_create_localhost( + "system" + , "io" + , NULL + , "disk" + , NULL + , "Disk I/O" + , "kilobytes/s" + , "proc" + , "diskstats" + , 150 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_in = rrddim_add(st_io, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st_io); + + rrddim_set_by_pointer(st_io, rd_in, system_read_kb); + rrddim_set_by_pointer(st_io, rd_out, system_write_kb); + rrdset_done(st_io); + } + + + // ------------------------------------------------------------------------ // cleanup removed disks struct disk *d = disk_root, *last = NULL; diff --git a/src/proc_interrupts.c b/src/proc_interrupts.c index b9f3941d..867f39eb 100644 --- a/src/proc_interrupts.c +++ b/src/proc_interrupts.c @@ -154,6 +154,8 @@ int do_proc_interrupts(int update_every, usec_t dt) { , NULL , "System interrupts" , "interrupts/s" + , "proc" + , "interrupts" , 1000 , update_every , RRDSET_TYPE_STACKED @@ -217,6 +219,8 @@ int do_proc_interrupts(int update_every, usec_t dt) { , "cpu.interrupts" , title , "interrupts/s" + , "proc" + , "interrupts" , 1100 + c , update_every , RRDSET_TYPE_STACKED diff --git a/src/proc_loadavg.c b/src/proc_loadavg.c index 54fc545a..868f7d50 100644 --- a/src/proc_loadavg.c +++ b/src/proc_loadavg.c @@ -60,6 +60,8 @@ int do_proc_loadavg(int update_every, usec_t dt) { , NULL , "System Load Average" , "load" + , "proc" + , "loadavg" , 100 , (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every , RRDSET_TYPE_LINE @@ -98,6 +100,8 @@ int do_proc_loadavg(int update_every, usec_t dt) { , NULL , "System Active Processes" , "processes" + , "proc" + , "loadavg" , 750 , update_every , RRDSET_TYPE_LINE diff --git a/src/proc_meminfo.c b/src/proc_meminfo.c index 152a6366..085850c2 100644 --- a/src/proc_meminfo.c +++ b/src/proc_meminfo.c @@ -150,6 +150,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "System RAM" , "MB" + , "proc" + , "meminfo" , 200 , update_every , RRDSET_TYPE_STACKED @@ -189,6 +191,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "System Swap" , "MB" + , "proc" + , "meminfo" , 201 , update_every , RRDSET_TYPE_STACKED @@ -224,6 +228,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Corrupted Memory, detected by ECC" , "MB" + , "proc" + , "meminfo" , 9000 , update_every , RRDSET_TYPE_LINE @@ -255,6 +261,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Committed (Allocated) Memory" , "MB" + , "proc" + , "meminfo" , 5000 , update_every , RRDSET_TYPE_AREA @@ -286,6 +294,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Writeback Memory" , "MB" + , "proc" + , "meminfo" , 4000 , update_every , RRDSET_TYPE_LINE @@ -324,6 +334,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Memory Used by Kernel" , "MB" + , "proc" + , "meminfo" , 6000 , update_every , RRDSET_TYPE_STACKED @@ -361,6 +373,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Reclaimable Kernel Memory" , "MB" + , "proc" + , "meminfo" , 6500 , update_every , RRDSET_TYPE_STACKED diff --git a/src/proc_net_dev.c b/src/proc_net_dev.c index 6e12fc5d..32bb5bab 100644 --- a/src/proc_net_dev.c +++ b/src/proc_net_dev.c @@ -9,6 +9,7 @@ static struct netdev { size_t len; // flags + int virtual; int configured; int enabled; int updated; @@ -428,8 +429,14 @@ int do_proc_net_dev(int update_every, usec_t dt) { static procfile *ff = NULL; static int enable_new_interfaces = -1; static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1; + static char *path_to_sys_devices_virtual_net = NULL; if(unlikely(enable_new_interfaces == -1)) { + char filename[FILENAME_MAX + 1]; + + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/net/%s"); + path_to_sys_devices_virtual_net = config_get("plugin:proc:/proc/net/dev", "path to get virtual interfaces", filename); + enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_BOOLEAN_AUTO); do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_BOOLEAN_AUTO); @@ -459,6 +466,9 @@ int do_proc_net_dev(int update_every, usec_t dt) { netdev_found = 0; + kernel_uint_t system_rbytes = 0; + kernel_uint_t system_tbytes = 0; + size_t lines = procfile_lines(ff), l; for(l = 2; l < lines ;l++) { // require 17 words on each line @@ -479,28 +489,42 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->enabled) d->enabled = !simple_pattern_matches(disabled_list, d->name); - char var_name[512 + 1]; - snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", d->name); - d->enabled = config_get_boolean_ondemand(var_name, "enabled", d->enabled); + char buffer[FILENAME_MAX + 1]; + + snprintfz(buffer, FILENAME_MAX, path_to_sys_devices_virtual_net, d->name); + if(likely(access(buffer, R_OK) == 0)) { + d->virtual = 1; + } + else + d->virtual = 0; + + snprintfz(buffer, FILENAME_MAX, "plugin:proc:/proc/net/dev:%s", d->name); + d->enabled = config_get_boolean_ondemand(buffer, "enabled", d->enabled); + d->virtual = config_get_boolean(buffer, "virtual", d->virtual); if(d->enabled == CONFIG_BOOLEAN_NO) continue; - d->do_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", do_bandwidth); - d->do_packets = config_get_boolean_ondemand(var_name, "packets", do_packets); - d->do_errors = config_get_boolean_ondemand(var_name, "errors", do_errors); - d->do_drops = config_get_boolean_ondemand(var_name, "drops", do_drops); - d->do_fifo = config_get_boolean_ondemand(var_name, "fifo", do_fifo); - d->do_compressed = config_get_boolean_ondemand(var_name, "compressed", do_compressed); - d->do_events = config_get_boolean_ondemand(var_name, "events", do_events); + d->do_bandwidth = config_get_boolean_ondemand(buffer, "bandwidth", do_bandwidth); + d->do_packets = config_get_boolean_ondemand(buffer, "packets", do_packets); + d->do_errors = config_get_boolean_ondemand(buffer, "errors", do_errors); + d->do_drops = config_get_boolean_ondemand(buffer, "drops", do_drops); + d->do_fifo = config_get_boolean_ondemand(buffer, "fifo", do_fifo); + d->do_compressed = config_get_boolean_ondemand(buffer, "compressed", do_compressed); + d->do_events = config_get_boolean_ondemand(buffer, "events", do_events); } if(unlikely(!d->enabled)) continue; - if(likely(d->do_bandwidth != CONFIG_BOOLEAN_NO)) { + if(likely(d->do_bandwidth != CONFIG_BOOLEAN_NO || !d->virtual)) { d->rbytes = str2kernel_uint_t(procfile_lineword(ff, l, 1)); d->tbytes = str2kernel_uint_t(procfile_lineword(ff, l, 9)); + + if(likely(!d->virtual)) { + system_rbytes += d->rbytes; + system_tbytes += d->tbytes; + } } if(likely(d->do_packets != CONFIG_BOOLEAN_NO)) { @@ -551,6 +575,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.net" , "Bandwidth" , "kilobits/s" + , "proc" + , "net/dev" , d->priority , update_every , RRDSET_TYPE_AREA @@ -590,6 +616,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.packets" , "Packets" , "packets/s" + , "proc" + , "net/dev" , d->priority + 1 , update_every , RRDSET_TYPE_LINE @@ -633,6 +661,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.errors" , "Interface Errors" , "errors/s" + , "proc" + , "net/dev" , d->priority + 2 , update_every , RRDSET_TYPE_LINE @@ -674,6 +704,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.drops" , "Interface Drops" , "drops/s" + , "proc" + , "net/dev" , d->priority + 3 , update_every , RRDSET_TYPE_LINE @@ -715,6 +747,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.fifo" , "Interface FIFO Buffer Errors" , "errors" + , "proc" + , "net/dev" , d->priority + 4 , update_every , RRDSET_TYPE_LINE @@ -756,6 +790,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.compressed" , "Compressed Packets" , "packets/s" + , "proc" + , "net/dev" , d->priority + 5 , update_every , RRDSET_TYPE_LINE @@ -797,6 +833,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.events" , "Network Interface Events" , "events/s" + , "proc" + , "net/dev" , d->priority + 6 , update_every , RRDSET_TYPE_LINE @@ -817,6 +855,39 @@ int do_proc_net_dev(int update_every, usec_t dt) { } } + if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (system_rbytes || system_tbytes))) { + do_bandwidth = CONFIG_BOOLEAN_YES; + static RRDSET *st_system_net = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if(unlikely(!st_system_net)) { + st_system_net = rrdset_create_localhost( + "system" + , "net" + , NULL + , "network" + , NULL + , "Physical Network Interfaces Aggregated Bandwidth" + , "kilobits/s" + , "proc" + , "net/dev" + , 500 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_in = rrddim_add(st_system_net, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_system_net, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_system_net); + + rrddim_set_by_pointer(st_system_net, rd_in, (collected_number)system_rbytes); + rrddim_set_by_pointer(st_system_net, rd_out, (collected_number)system_tbytes); + + rrdset_done(st_system_net); + } + netdev_cleanup(); return 0; diff --git a/src/proc_net_ip_vs_stats.c b/src/proc_net_ip_vs_stats.c index aa806b46..d76972f3 100644 --- a/src/proc_net_ip_vs_stats.c +++ b/src/proc_net_ip_vs_stats.c @@ -35,16 +35,27 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { InBytes = strtoull(procfile_lineword(ff, 2, 3), NULL, 16); OutBytes = strtoull(procfile_lineword(ff, 2, 4), NULL, 16); - RRDSET *st; // -------------------------------------------------------------------- if(do_sockets) { - st = rrdset_find_localhost(RRD_TYPE_NET_IPVS ".sockets"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, NULL - , "IPVS New Connections", "connections/s", 3101, update_every - , RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_IPVS + , "sockets" + , NULL + , RRD_TYPE_NET_IPVS + , NULL + , "IPVS New Connections" + , "connections/s" + , "proc" + , "net/ip_vs_stats" + , 3101 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } @@ -57,10 +68,22 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_packets) { - st = rrdset_find_localhost(RRD_TYPE_NET_IPVS ".packets"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Packets" - , "packets/s", 3102, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_IPVS + , "packets" + , NULL + , RRD_TYPE_NET_IPVS + , NULL + , "IPVS Packets" + , "packets/s" + , "proc" + , "net/ip_vs_stats" + , 3102 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -75,10 +98,22 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_bandwidth) { - st = rrdset_find_localhost(RRD_TYPE_NET_IPVS ".net"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Bandwidth" - , "kilobits/s", 3100, update_every, RRDSET_TYPE_AREA); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_IPVS + , "net" + , NULL + , RRD_TYPE_NET_IPVS + , NULL + , "IPVS Bandwidth" + , "kilobits/s" + , "proc" + , "net/ip_vs_stats" + , 3100 + , update_every + , RRDSET_TYPE_AREA + ); rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); diff --git a/src/proc_net_netstat.c b/src/proc_net_netstat.c index e01b81d2..dd070e4c 100644 --- a/src/proc_net_netstat.c +++ b/src/proc_net_netstat.c @@ -22,7 +22,9 @@ int do_proc_net_netstat(int update_every, usec_t dt) { (void)dt; static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \ - do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1; + do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1, + do_tcpext_listen = -1; + static uint32_t hash_ipext = 0, hash_tcpext = 0; static procfile *ff = NULL; @@ -93,6 +95,10 @@ int do_proc_net_netstat(int update_every, usec_t dt) { static unsigned long long tcpext_TCPAbortOnLinger = 0; // connections aborted after user close in linger timeout static unsigned long long tcpext_TCPAbortFailed = 0; // times unable to send RST due to no memory + // https://perfchron.com/2015/12/26/investigating-linux-network-issues-with-netstat-and-nstat/ + static unsigned long long tcpext_ListenOverflows = 0; // times the listen queue of a socket overflowed + static unsigned long long tcpext_ListenDrops = 0; // SYNs to LISTEN sockets ignored + // IPv4 TCP memory pressures static unsigned long long tcpext_TCPMemoryPressures = 0; @@ -116,6 +122,7 @@ int do_proc_net_netstat(int update_every, usec_t dt) { do_tcpext_ofo = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO); do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_BOOLEAN_AUTO); do_tcpext_memory = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_BOOLEAN_AUTO); + do_tcpext_listen = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP listen issues", CONFIG_BOOLEAN_AUTO); arl_ipext = arl_create("netstat/ipext", NULL, 60); arl_tcpext = arl_create("netstat/tcpext", NULL, 60); @@ -197,6 +204,11 @@ int do_proc_net_netstat(int update_every, usec_t dt) { arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures); } + if(do_tcpext_listen != CONFIG_BOOLEAN_NO) { + arl_expect(arl_tcpext, "ListenOverflows", &tcpext_ListenOverflows); + arl_expect(arl_tcpext, "ListenDrops", &tcpext_ListenDrops); + } + // shared metrics arl_expect(arl_tcpext, "TCPSynRetrans", &tcpext_TCPSynRetrans); } @@ -248,7 +260,9 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "IPv4 Bandwidth" , "kilobits/s" - , 500 + , "proc" + , "net/netstat" + , 501 , update_every , RRDSET_TYPE_AREA ); @@ -281,6 +295,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "IPv4 Input Errors" , "packets/s" + , "proc" + , "net/netstat" , 4000 , update_every , RRDSET_TYPE_LINE @@ -318,6 +334,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "IPv4 Multicast Bandwidth" , "kilobits/s" + , "proc" + , "net/netstat" , 9000 , update_every , RRDSET_TYPE_AREA @@ -354,6 +372,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "IPv4 Broadcast Bandwidth" , "kilobits/s" + , "proc" + , "net/netstat" , 8000 , update_every , RRDSET_TYPE_AREA @@ -390,6 +410,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "IPv4 Multicast Packets" , "packets/s" + , "proc" + , "net/netstat" , 8600 , update_every , RRDSET_TYPE_LINE @@ -425,6 +447,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "IPv4 Broadcast Packets" , "packets/s" + , "proc" + , "net/netstat" , 8500 , update_every , RRDSET_TYPE_LINE @@ -461,6 +485,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "IPv4 ECN Statistics" , "packets/s" + , "proc" + , "net/netstat" , 8700 , update_every , RRDSET_TYPE_LINE @@ -511,6 +537,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "TCP Memory Pressures" , "events/s" + , "proc" + , "net/netstat" , 3000 , update_every , RRDSET_TYPE_LINE @@ -543,6 +571,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "TCP Connection Aborts" , "connections/s" + , "proc" + , "net/netstat" , 3010 , update_every , RRDSET_TYPE_LINE @@ -585,6 +615,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "TCP Reordered Packets by Detection Method" , "packets/s" + , "proc" + , "net/netstat" , 3020 , update_every , RRDSET_TYPE_LINE @@ -624,6 +656,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "TCP Out-Of-Order Queue" , "packets/s" + , "proc" + , "net/netstat" , 3050 , update_every , RRDSET_TYPE_LINE @@ -663,6 +697,8 @@ int do_proc_net_netstat(int update_every, usec_t dt) { , NULL , "TCP SYN Cookies" , "packets/s" + , "proc" + , "net/netstat" , 3100 , update_every , RRDSET_TYPE_LINE @@ -682,6 +718,42 @@ int do_proc_net_netstat(int update_every, usec_t dt) { rrdset_done(st_syncookies); } + // -------------------------------------------------------------------- + + if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && (tcpext_ListenOverflows || tcpext_ListenDrops))) { + do_tcpext_listen = CONFIG_BOOLEAN_YES; + + static RRDSET *st_listen = NULL; + static RRDDIM *rd_overflows = NULL, *rd_drops = NULL; + + if(unlikely(!st_listen)) { + + st_listen = rrdset_create_localhost( + "ipv4" + , "tcplistenissues" + , NULL + , "tcp" + , NULL + , "TCP Listen Socket Issues" + , "packets/s" + , "proc" + , "net/netstat" + , 3015 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_overflows = rrddim_add(st_listen, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_drops = rrddim_add(st_listen, "ListenDrops", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_listen); + + rrddim_set_by_pointer(st_listen, rd_overflows, tcpext_ListenOverflows); + rrddim_set_by_pointer(st_listen, rd_drops, tcpext_ListenDrops); + + rrdset_done(st_listen); + } } } diff --git a/src/proc_net_rpc_nfs.c b/src/proc_net_rpc_nfs.c index 0df91963..126216e0 100644 --- a/src/proc_net_rpc_nfs.c +++ b/src/proc_net_rpc_nfs.c @@ -4,127 +4,133 @@ struct nfs_procs { char name[30]; unsigned long long value; int present; + RRDDIM *rd; }; struct nfs_procs nfs_proc2_values[] = { - { "null", 0ULL, 0 }, - { "getattr", 0ULL, 0 }, - { "setattr", 0ULL, 0 }, - { "root", 0ULL, 0 }, - { "lookup", 0ULL, 0 }, - { "readlink", 0ULL, 0 }, - { "read", 0ULL, 0 }, - { "wrcache", 0ULL, 0 }, - { "write", 0ULL, 0 }, - { "create", 0ULL, 0 }, - { "remove", 0ULL, 0 }, - { "rename", 0ULL, 0 }, - { "link", 0ULL, 0 }, - { "symlink", 0ULL, 0 }, - { "mkdir", 0ULL, 0 }, - { "rmdir", 0ULL, 0 }, - { "readdir", 0ULL, 0 }, - { "fsstat", 0ULL, 0 }, - - /* termination */ - { "", 0ULL, 0 } + { "null" , 0ULL, 0, NULL} + , {"getattr" , 0ULL, 0, NULL} + , {"setattr" , 0ULL, 0, NULL} + , {"root" , 0ULL, 0, NULL} + , {"lookup" , 0ULL, 0, NULL} + , {"readlink", 0ULL, 0, NULL} + , {"read" , 0ULL, 0, NULL} + , {"wrcache" , 0ULL, 0, NULL} + , {"write" , 0ULL, 0, NULL} + , {"create" , 0ULL, 0, NULL} + , {"remove" , 0ULL, 0, NULL} + , {"rename" , 0ULL, 0, NULL} + , {"link" , 0ULL, 0, NULL} + , {"symlink" , 0ULL, 0, NULL} + , {"mkdir" , 0ULL, 0, NULL} + , {"rmdir" , 0ULL, 0, NULL} + , {"readdir" , 0ULL, 0, NULL} + , {"fsstat" , 0ULL, 0, NULL} + , + + /* termination */ + { "" , 0ULL, 0, NULL} }; struct nfs_procs nfs_proc3_values[] = { - { "null", 0ULL, 0 }, - { "getattr", 0ULL, 0 }, - { "setattr", 0ULL, 0 }, - { "lookup", 0ULL, 0 }, - { "access", 0ULL, 0 }, - { "readlink", 0ULL, 0 }, - { "read", 0ULL, 0 }, - { "write", 0ULL, 0 }, - { "create", 0ULL, 0 }, - { "mkdir", 0ULL, 0 }, - { "symlink", 0ULL, 0 }, - { "mknod", 0ULL, 0 }, - { "remove", 0ULL, 0 }, - { "rmdir", 0ULL, 0 }, - { "rename", 0ULL, 0 }, - { "link", 0ULL, 0 }, - { "readdir", 0ULL, 0 }, - { "readdirplus", 0ULL, 0 }, - { "fsstat", 0ULL, 0 }, - { "fsinfo", 0ULL, 0 }, - { "pathconf", 0ULL, 0 }, - { "commit", 0ULL, 0 }, - - /* termination */ - { "", 0ULL, 0 } + { "null" , 0ULL, 0, NULL} + , {"getattr" , 0ULL, 0, NULL} + , {"setattr" , 0ULL, 0, NULL} + , {"lookup" , 0ULL, 0, NULL} + , {"access" , 0ULL, 0, NULL} + , {"readlink" , 0ULL, 0, NULL} + , {"read" , 0ULL, 0, NULL} + , {"write" , 0ULL, 0, NULL} + , {"create" , 0ULL, 0, NULL} + , {"mkdir" , 0ULL, 0, NULL} + , {"symlink" , 0ULL, 0, NULL} + , {"mknod" , 0ULL, 0, NULL} + , {"remove" , 0ULL, 0, NULL} + , {"rmdir" , 0ULL, 0, NULL} + , {"rename" , 0ULL, 0, NULL} + , {"link" , 0ULL, 0, NULL} + , {"readdir" , 0ULL, 0, NULL} + , {"readdirplus", 0ULL, 0, NULL} + , {"fsstat" , 0ULL, 0, NULL} + , {"fsinfo" , 0ULL, 0, NULL} + , {"pathconf" , 0ULL, 0, NULL} + , {"commit" , 0ULL, 0, NULL} + , + + /* termination */ + { "" , 0ULL, 0, NULL} }; struct nfs_procs nfs_proc4_values[] = { - { "null", 0ULL, 0 }, - { "read", 0ULL, 0 }, - { "write", 0ULL, 0 }, - { "commit", 0ULL, 0 }, - { "open", 0ULL, 0 }, - { "open_conf", 0ULL, 0 }, - { "open_noat", 0ULL, 0 }, - { "open_dgrd", 0ULL, 0 }, - { "close", 0ULL, 0 }, - { "setattr", 0ULL, 0 }, - { "fsinfo", 0ULL, 0 }, - { "renew", 0ULL, 0 }, - { "setclntid", 0ULL, 0 }, - { "confirm", 0ULL, 0 }, - { "lock", 0ULL, 0 }, - { "lockt", 0ULL, 0 }, - { "locku", 0ULL, 0 }, - { "access", 0ULL, 0 }, - { "getattr", 0ULL, 0 }, - { "lookup", 0ULL, 0 }, - { "lookup_root", 0ULL, 0 }, - { "remove", 0ULL, 0 }, - { "rename", 0ULL, 0 }, - { "link", 0ULL, 0 }, - { "symlink", 0ULL, 0 }, - { "create", 0ULL, 0 }, - { "pathconf", 0ULL, 0 }, - { "statfs", 0ULL, 0 }, - { "readlink", 0ULL, 0 }, - { "readdir", 0ULL, 0 }, - { "server_caps", 0ULL, 0 }, - { "delegreturn", 0ULL, 0 }, - { "getacl", 0ULL, 0 }, - { "setacl", 0ULL, 0 }, - { "fs_locations", 0ULL, 0 }, - { "rel_lkowner", 0ULL, 0 }, - { "secinfo", 0ULL, 0 }, - { "fsid_present", 0ULL, 0 }, - - /* nfsv4.1 client ops */ - { "exchange_id", 0ULL, 0 }, - { "create_session", 0ULL, 0 }, - { "destroy_session", 0ULL, 0 }, - { "sequence", 0ULL, 0 }, - { "get_lease_time", 0ULL, 0 }, - { "reclaim_comp", 0ULL, 0 }, - { "layoutget", 0ULL, 0 }, - { "getdevinfo", 0ULL, 0 }, - { "layoutcommit", 0ULL, 0 }, - { "layoutreturn", 0ULL, 0 }, - { "secinfo_no", 0ULL, 0 }, - { "test_stateid", 0ULL, 0 }, - { "free_stateid", 0ULL, 0 }, - { "getdevicelist", 0ULL, 0 }, - { "bind_conn_to_ses", 0ULL, 0 }, - { "destroy_clientid", 0ULL, 0 }, - - /* nfsv4.2 client ops */ - { "seek", 0ULL, 0 }, - { "allocate", 0ULL, 0 }, - { "deallocate", 0ULL, 0 }, - { "layoutstats", 0ULL, 0 }, - { "clone", 0ULL, 0 }, - - /* termination */ - { "", 0ULL, 0 } + { "null" , 0ULL, 0, NULL} + , {"read" , 0ULL, 0, NULL} + , {"write" , 0ULL, 0, NULL} + , {"commit" , 0ULL, 0, NULL} + , {"open" , 0ULL, 0, NULL} + , {"open_conf" , 0ULL, 0, NULL} + , {"open_noat" , 0ULL, 0, NULL} + , {"open_dgrd" , 0ULL, 0, NULL} + , {"close" , 0ULL, 0, NULL} + , {"setattr" , 0ULL, 0, NULL} + , {"fsinfo" , 0ULL, 0, NULL} + , {"renew" , 0ULL, 0, NULL} + , {"setclntid" , 0ULL, 0, NULL} + , {"confirm" , 0ULL, 0, NULL} + , {"lock" , 0ULL, 0, NULL} + , {"lockt" , 0ULL, 0, NULL} + , {"locku" , 0ULL, 0, NULL} + , {"access" , 0ULL, 0, NULL} + , {"getattr" , 0ULL, 0, NULL} + , {"lookup" , 0ULL, 0, NULL} + , {"lookup_root" , 0ULL, 0, NULL} + , {"remove" , 0ULL, 0, NULL} + , {"rename" , 0ULL, 0, NULL} + , {"link" , 0ULL, 0, NULL} + , {"symlink" , 0ULL, 0, NULL} + , {"create" , 0ULL, 0, NULL} + , {"pathconf" , 0ULL, 0, NULL} + , {"statfs" , 0ULL, 0, NULL} + , {"readlink" , 0ULL, 0, NULL} + , {"readdir" , 0ULL, 0, NULL} + , {"server_caps" , 0ULL, 0, NULL} + , {"delegreturn" , 0ULL, 0, NULL} + , {"getacl" , 0ULL, 0, NULL} + , {"setacl" , 0ULL, 0, NULL} + , {"fs_locations" , 0ULL, 0, NULL} + , {"rel_lkowner" , 0ULL, 0, NULL} + , {"secinfo" , 0ULL, 0, NULL} + , {"fsid_present" , 0ULL, 0, NULL} + , + + /* nfsv4.1 client ops */ + { "exchange_id" , 0ULL, 0, NULL} + , {"create_session" , 0ULL, 0, NULL} + , {"destroy_session" , 0ULL, 0, NULL} + , {"sequence" , 0ULL, 0, NULL} + , {"get_lease_time" , 0ULL, 0, NULL} + , {"reclaim_comp" , 0ULL, 0, NULL} + , {"layoutget" , 0ULL, 0, NULL} + , {"getdevinfo" , 0ULL, 0, NULL} + , {"layoutcommit" , 0ULL, 0, NULL} + , {"layoutreturn" , 0ULL, 0, NULL} + , {"secinfo_no" , 0ULL, 0, NULL} + , {"test_stateid" , 0ULL, 0, NULL} + , {"free_stateid" , 0ULL, 0, NULL} + , {"getdevicelist" , 0ULL, 0, NULL} + , {"bind_conn_to_ses", 0ULL, 0, NULL} + , {"destroy_clientid", 0ULL, 0, NULL} + , + + /* nfsv4.2 client ops */ + { "seek" , 0ULL, 0, NULL} + , {"allocate" , 0ULL, 0, NULL} + , {"deallocate" , 0ULL, 0, NULL} + , {"layoutstats" , 0ULL, 0, NULL} + , {"clone" , 0ULL, 0, NULL} + , + + /* termination */ + { "" , 0ULL, 0, NULL} }; int do_proc_net_rpc_nfs(int update_every, usec_t dt) { @@ -264,68 +270,111 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { } } - RRDSET *st; - // -------------------------------------------------------------------- if(do_net == 2) { - st = rrdset_find_bytype_localhost("nfs", "net"); - if(!st) { - st = rrdset_create_localhost("nfs", "net", NULL, "network", NULL, "NFS Client Network", "operations/s", 5007 - , update_every, RRDSET_TYPE_STACKED); + static RRDSET *st = NULL; + static RRDDIM *rd_udp = NULL, + *rd_tcp = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfs" + , "net" + , NULL + , "network" + , NULL + , "NFS Client Network" + , "operations/s" + , "proc" + , "net/rpc/nfs" + , 5007 + , update_every + , RRDSET_TYPE_STACKED + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); // ignore net_count, net_tcp_connections - if(net_count) {}; - if(net_tcp_connections) {}; + (void)net_count; + (void)net_tcp_connections; - rrddim_set(st, "udp", net_udp_count); - rrddim_set(st, "tcp", net_tcp_count); + rrddim_set_by_pointer(st, rd_udp, net_udp_count); + rrddim_set_by_pointer(st, rd_tcp, net_tcp_count); rrdset_done(st); } // -------------------------------------------------------------------- if(do_rpc == 2) { - st = rrdset_find_bytype_localhost("nfs", "rpc"); - if(!st) { - st = rrdset_create_localhost("nfs", "rpc", NULL, "rpc", NULL, "NFS Client Remote Procedure Calls Statistics" - , "calls/s", 5008, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_calls = NULL, + *rd_retransmits = NULL, + *rd_auth_refresh = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfs" + , "rpc" + , NULL + , "rpc" + , NULL + , "NFS Client Remote Procedure Calls Statistics" + , "calls/s" + , "proc" + , "net/rpc/nfs" + , 5008 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "retransmits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "auth_refresh", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_retransmits = rrddim_add(st, "retransmits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_auth_refresh = rrddim_add(st, "auth_refresh", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "calls", rpc_calls); - rrddim_set(st, "retransmits", rpc_retransmits); - rrddim_set(st, "auth_refresh", rpc_auth_refresh); + rrddim_set_by_pointer(st, rd_calls, rpc_calls); + rrddim_set_by_pointer(st, rd_retransmits, rpc_retransmits); + rrddim_set_by_pointer(st, rd_auth_refresh, rpc_auth_refresh); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc2 == 2) { - unsigned int i; - st = rrdset_find_bytype_localhost("nfs", "proc2"); - if(!st) { - st = rrdset_create_localhost("nfs", "proc2", NULL, "nfsv2rpc", NULL, "NFS v2 Client Remote Procedure Calls" - , "calls/s", 5009, update_every, RRDSET_TYPE_STACKED); - - for(i = 0; nfs_proc2_values[i].present ; i++) - rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfs" + , "proc2" + , NULL + , "nfsv2rpc" + , NULL + , "NFS v2 Client Remote Procedure Calls" + , "calls/s" + , "proc" + , "net/rpc/nfs" + , 5009 + , update_every + , RRDSET_TYPE_STACKED + ); } else rrdset_next(st); - for(i = 0; nfs_proc2_values[i].present ; i++) - rrddim_set(st, nfs_proc2_values[i].name, nfs_proc2_values[i].value); + size_t i; + for(i = 0; nfs_proc2_values[i].present ; i++) { + if(unlikely(!nfs_proc2_values[i].rd)) + nfs_proc2_values[i].rd = rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_set_by_pointer(st, nfs_proc2_values[i].rd, nfs_proc2_values[i].value); + } rrdset_done(st); } @@ -333,19 +382,32 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_proc3 == 2) { - unsigned int i; - st = rrdset_find_bytype_localhost("nfs", "proc3"); - if(!st) { - st = rrdset_create_localhost("nfs", "proc3", NULL, "nfsv3rpc", NULL, "NFS v3 Client Remote Procedure Calls" - , "calls/s", 5010, update_every, RRDSET_TYPE_STACKED); - - for(i = 0; nfs_proc3_values[i].present ; i++) - rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfs" + , "proc3" + , NULL + , "nfsv3rpc" + , NULL + , "NFS v3 Client Remote Procedure Calls" + , "calls/s" + , "proc" + , "net/rpc/nfs" + , 5010 + , update_every + , RRDSET_TYPE_STACKED + ); } else rrdset_next(st); - for(i = 0; nfs_proc3_values[i].present ; i++) - rrddim_set(st, nfs_proc3_values[i].name, nfs_proc3_values[i].value); + size_t i; + for(i = 0; nfs_proc3_values[i].present ; i++) { + if(unlikely(!nfs_proc3_values[i].rd)) + nfs_proc3_values[i].rd = rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_set_by_pointer(st, nfs_proc3_values[i].rd, nfs_proc3_values[i].value); + } rrdset_done(st); } @@ -353,19 +415,32 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_proc4 == 2) { - unsigned int i; - st = rrdset_find_bytype_localhost("nfs", "proc4"); - if(!st) { - st = rrdset_create_localhost("nfs", "proc4", NULL, "nfsv4rpc", NULL, "NFS v4 Client Remote Procedure Calls" - , "calls/s", 5011, update_every, RRDSET_TYPE_STACKED); - - for(i = 0; nfs_proc4_values[i].present ; i++) - rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfs" + , "proc4" + , NULL + , "nfsv4rpc" + , NULL + , "NFS v4 Client Remote Procedure Calls" + , "calls/s" + , "proc" + , "net/rpc/nfs" + , 5011 + , update_every + , RRDSET_TYPE_STACKED + ); } else rrdset_next(st); - for(i = 0; nfs_proc4_values[i].present ; i++) - rrddim_set(st, nfs_proc4_values[i].name, nfs_proc4_values[i].value); + size_t i; + for(i = 0; nfs_proc4_values[i].present ; i++) { + if(unlikely(!nfs_proc4_values[i].rd)) + nfs_proc4_values[i].rd = rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_set_by_pointer(st, nfs_proc4_values[i].rd, nfs_proc4_values[i].value); + } rrdset_done(st); } diff --git a/src/proc_net_rpc_nfsd.c b/src/proc_net_rpc_nfsd.c index b0ed58d1..f0c9a20c 100644 --- a/src/proc_net_rpc_nfsd.c +++ b/src/proc_net_rpc_nfsd.c @@ -4,208 +4,217 @@ struct nfsd_procs { char name[30]; unsigned long long value; int present; + RRDDIM *rd; }; struct nfsd_procs nfsd_proc2_values[] = { - { "null", 0ULL, 0 }, - { "getattr", 0ULL, 0 }, - { "setattr", 0ULL, 0 }, - { "root", 0ULL, 0 }, - { "lookup", 0ULL, 0 }, - { "readlink", 0ULL, 0 }, - { "read", 0ULL, 0 }, - { "wrcache", 0ULL, 0 }, - { "write", 0ULL, 0 }, - { "create", 0ULL, 0 }, - { "remove", 0ULL, 0 }, - { "rename", 0ULL, 0 }, - { "link", 0ULL, 0 }, - { "symlink", 0ULL, 0 }, - { "mkdir", 0ULL, 0 }, - { "rmdir", 0ULL, 0 }, - { "readdir", 0ULL, 0 }, - { "fsstat", 0ULL, 0 }, - - /* termination */ - { "", 0ULL, 0 } + { "null" , 0ULL, 0, NULL} + , {"getattr" , 0ULL, 0, NULL} + , {"setattr" , 0ULL, 0, NULL} + , {"root" , 0ULL, 0, NULL} + , {"lookup" , 0ULL, 0, NULL} + , {"readlink", 0ULL, 0, NULL} + , {"read" , 0ULL, 0, NULL} + , {"wrcache" , 0ULL, 0, NULL} + , {"write" , 0ULL, 0, NULL} + , {"create" , 0ULL, 0, NULL} + , {"remove" , 0ULL, 0, NULL} + , {"rename" , 0ULL, 0, NULL} + , {"link" , 0ULL, 0, NULL} + , {"symlink" , 0ULL, 0, NULL} + , {"mkdir" , 0ULL, 0, NULL} + , {"rmdir" , 0ULL, 0, NULL} + , {"readdir" , 0ULL, 0, NULL} + , {"fsstat" , 0ULL, 0, NULL} + , + + /* termination */ + { "" , 0ULL, 0, NULL} }; struct nfsd_procs nfsd_proc3_values[] = { - { "null", 0ULL, 0 }, - { "getattr", 0ULL, 0 }, - { "setattr", 0ULL, 0 }, - { "lookup", 0ULL, 0 }, - { "access", 0ULL, 0 }, - { "readlink", 0ULL, 0 }, - { "read", 0ULL, 0 }, - { "write", 0ULL, 0 }, - { "create", 0ULL, 0 }, - { "mkdir", 0ULL, 0 }, - { "symlink", 0ULL, 0 }, - { "mknod", 0ULL, 0 }, - { "remove", 0ULL, 0 }, - { "rmdir", 0ULL, 0 }, - { "rename", 0ULL, 0 }, - { "link", 0ULL, 0 }, - { "readdir", 0ULL, 0 }, - { "readdirplus", 0ULL, 0 }, - { "fsstat", 0ULL, 0 }, - { "fsinfo", 0ULL, 0 }, - { "pathconf", 0ULL, 0 }, - { "commit", 0ULL, 0 }, - - /* termination */ - { "", 0ULL, 0 } + { "null" , 0ULL, 0, NULL} + , {"getattr" , 0ULL, 0, NULL} + , {"setattr" , 0ULL, 0, NULL} + , {"lookup" , 0ULL, 0, NULL} + , {"access" , 0ULL, 0, NULL} + , {"readlink" , 0ULL, 0, NULL} + , {"read" , 0ULL, 0, NULL} + , {"write" , 0ULL, 0, NULL} + , {"create" , 0ULL, 0, NULL} + , {"mkdir" , 0ULL, 0, NULL} + , {"symlink" , 0ULL, 0, NULL} + , {"mknod" , 0ULL, 0, NULL} + , {"remove" , 0ULL, 0, NULL} + , {"rmdir" , 0ULL, 0, NULL} + , {"rename" , 0ULL, 0, NULL} + , {"link" , 0ULL, 0, NULL} + , {"readdir" , 0ULL, 0, NULL} + , {"readdirplus", 0ULL, 0, NULL} + , {"fsstat" , 0ULL, 0, NULL} + , {"fsinfo" , 0ULL, 0, NULL} + , {"pathconf" , 0ULL, 0, NULL} + , {"commit" , 0ULL, 0, NULL} + , + + /* termination */ + { "" , 0ULL, 0, NULL} }; struct nfsd_procs nfsd_proc4_values[] = { - { "null", 0ULL, 0 }, - { "read", 0ULL, 0 }, - { "write", 0ULL, 0 }, - { "commit", 0ULL, 0 }, - { "open", 0ULL, 0 }, - { "open_conf", 0ULL, 0 }, - { "open_noat", 0ULL, 0 }, - { "open_dgrd", 0ULL, 0 }, - { "close", 0ULL, 0 }, - { "setattr", 0ULL, 0 }, - { "fsinfo", 0ULL, 0 }, - { "renew", 0ULL, 0 }, - { "setclntid", 0ULL, 0 }, - { "confirm", 0ULL, 0 }, - { "lock", 0ULL, 0 }, - { "lockt", 0ULL, 0 }, - { "locku", 0ULL, 0 }, - { "access", 0ULL, 0 }, - { "getattr", 0ULL, 0 }, - { "lookup", 0ULL, 0 }, - { "lookup_root", 0ULL, 0 }, - { "remove", 0ULL, 0 }, - { "rename", 0ULL, 0 }, - { "link", 0ULL, 0 }, - { "symlink", 0ULL, 0 }, - { "create", 0ULL, 0 }, - { "pathconf", 0ULL, 0 }, - { "statfs", 0ULL, 0 }, - { "readlink", 0ULL, 0 }, - { "readdir", 0ULL, 0 }, - { "server_caps", 0ULL, 0 }, - { "delegreturn", 0ULL, 0 }, - { "getacl", 0ULL, 0 }, - { "setacl", 0ULL, 0 }, - { "fs_locations", 0ULL, 0 }, - { "rel_lkowner", 0ULL, 0 }, - { "secinfo", 0ULL, 0 }, - { "fsid_present", 0ULL, 0 }, - - /* nfsv4.1 client ops */ - { "exchange_id", 0ULL, 0 }, - { "create_session", 0ULL, 0 }, - { "destroy_session", 0ULL, 0 }, - { "sequence", 0ULL, 0 }, - { "get_lease_time", 0ULL, 0 }, - { "reclaim_comp", 0ULL, 0 }, - { "layoutget", 0ULL, 0 }, - { "getdevinfo", 0ULL, 0 }, - { "layoutcommit", 0ULL, 0 }, - { "layoutreturn", 0ULL, 0 }, - { "secinfo_no", 0ULL, 0 }, - { "test_stateid", 0ULL, 0 }, - { "free_stateid", 0ULL, 0 }, - { "getdevicelist", 0ULL, 0 }, - { "bind_conn_to_ses", 0ULL, 0 }, - { "destroy_clientid", 0ULL, 0 }, - - /* nfsv4.2 client ops */ - { "seek", 0ULL, 0 }, - { "allocate", 0ULL, 0 }, - { "deallocate", 0ULL, 0 }, - { "layoutstats", 0ULL, 0 }, - { "clone", 0ULL, 0 }, - - /* termination */ - { "", 0ULL, 0 } + { "null" , 0ULL, 0, NULL} + , {"read" , 0ULL, 0, NULL} + , {"write" , 0ULL, 0, NULL} + , {"commit" , 0ULL, 0, NULL} + , {"open" , 0ULL, 0, NULL} + , {"open_conf" , 0ULL, 0, NULL} + , {"open_noat" , 0ULL, 0, NULL} + , {"open_dgrd" , 0ULL, 0, NULL} + , {"close" , 0ULL, 0, NULL} + , {"setattr" , 0ULL, 0, NULL} + , {"fsinfo" , 0ULL, 0, NULL} + , {"renew" , 0ULL, 0, NULL} + , {"setclntid" , 0ULL, 0, NULL} + , {"confirm" , 0ULL, 0, NULL} + , {"lock" , 0ULL, 0, NULL} + , {"lockt" , 0ULL, 0, NULL} + , {"locku" , 0ULL, 0, NULL} + , {"access" , 0ULL, 0, NULL} + , {"getattr" , 0ULL, 0, NULL} + , {"lookup" , 0ULL, 0, NULL} + , {"lookup_root" , 0ULL, 0, NULL} + , {"remove" , 0ULL, 0, NULL} + , {"rename" , 0ULL, 0, NULL} + , {"link" , 0ULL, 0, NULL} + , {"symlink" , 0ULL, 0, NULL} + , {"create" , 0ULL, 0, NULL} + , {"pathconf" , 0ULL, 0, NULL} + , {"statfs" , 0ULL, 0, NULL} + , {"readlink" , 0ULL, 0, NULL} + , {"readdir" , 0ULL, 0, NULL} + , {"server_caps" , 0ULL, 0, NULL} + , {"delegreturn" , 0ULL, 0, NULL} + , {"getacl" , 0ULL, 0, NULL} + , {"setacl" , 0ULL, 0, NULL} + , {"fs_locations" , 0ULL, 0, NULL} + , {"rel_lkowner" , 0ULL, 0, NULL} + , {"secinfo" , 0ULL, 0, NULL} + , {"fsid_present" , 0ULL, 0, NULL} + , + + /* nfsv4.1 client ops */ + { "exchange_id" , 0ULL, 0, NULL} + , {"create_session" , 0ULL, 0, NULL} + , {"destroy_session" , 0ULL, 0, NULL} + , {"sequence" , 0ULL, 0, NULL} + , {"get_lease_time" , 0ULL, 0, NULL} + , {"reclaim_comp" , 0ULL, 0, NULL} + , {"layoutget" , 0ULL, 0, NULL} + , {"getdevinfo" , 0ULL, 0, NULL} + , {"layoutcommit" , 0ULL, 0, NULL} + , {"layoutreturn" , 0ULL, 0, NULL} + , {"secinfo_no" , 0ULL, 0, NULL} + , {"test_stateid" , 0ULL, 0, NULL} + , {"free_stateid" , 0ULL, 0, NULL} + , {"getdevicelist" , 0ULL, 0, NULL} + , {"bind_conn_to_ses", 0ULL, 0, NULL} + , {"destroy_clientid", 0ULL, 0, NULL} + , + + /* nfsv4.2 client ops */ + { "seek" , 0ULL, 0, NULL} + , {"allocate" , 0ULL, 0, NULL} + , {"deallocate" , 0ULL, 0, NULL} + , {"layoutstats" , 0ULL, 0, NULL} + , {"clone" , 0ULL, 0, NULL} + , + + /* termination */ + { "" , 0ULL, 0, NULL} }; struct nfsd_procs nfsd4_ops_values[] = { - { "unused_op0", 0ULL, 0}, - { "unused_op1", 0ULL, 0}, - { "future_op2", 0ULL, 0}, - { "access", 0ULL, 0}, - { "close", 0ULL, 0}, - { "commit", 0ULL, 0}, - { "create", 0ULL, 0}, - { "delegpurge", 0ULL, 0}, - { "delegreturn", 0ULL, 0}, - { "getattr", 0ULL, 0}, - { "getfh", 0ULL, 0}, - { "link", 0ULL, 0}, - { "lock", 0ULL, 0}, - { "lockt", 0ULL, 0}, - { "locku", 0ULL, 0}, - { "lookup", 0ULL, 0}, - { "lookup_root", 0ULL, 0}, - { "nverify", 0ULL, 0}, - { "open", 0ULL, 0}, - { "openattr", 0ULL, 0}, - { "open_confirm", 0ULL, 0}, - { "open_downgrade", 0ULL, 0}, - { "putfh", 0ULL, 0}, - { "putpubfh", 0ULL, 0}, - { "putrootfh", 0ULL, 0}, - { "read", 0ULL, 0}, - { "readdir", 0ULL, 0}, - { "readlink", 0ULL, 0}, - { "remove", 0ULL, 0}, - { "rename", 0ULL, 0}, - { "renew", 0ULL, 0}, - { "restorefh", 0ULL, 0}, - { "savefh", 0ULL, 0}, - { "secinfo", 0ULL, 0}, - { "setattr", 0ULL, 0}, - { "setclientid", 0ULL, 0}, - { "setclientid_confirm", 0ULL, 0}, - { "verify", 0ULL, 0}, - { "write", 0ULL, 0}, - { "release_lockowner", 0ULL, 0}, - - /* nfs41 */ - { "backchannel_ctl", 0ULL, 0}, - { "bind_conn_to_session", 0ULL, 0}, - { "exchange_id", 0ULL, 0}, - { "create_session", 0ULL, 0}, - { "destroy_session", 0ULL, 0}, - { "free_stateid", 0ULL, 0}, - { "get_dir_delegation", 0ULL, 0}, - { "getdeviceinfo", 0ULL, 0}, - { "getdevicelist", 0ULL, 0}, - { "layoutcommit", 0ULL, 0}, - { "layoutget", 0ULL, 0}, - { "layoutreturn", 0ULL, 0}, - { "secinfo_no_name", 0ULL, 0}, - { "sequence", 0ULL, 0}, - { "set_ssv", 0ULL, 0}, - { "test_stateid", 0ULL, 0}, - { "want_delegation", 0ULL, 0}, - { "destroy_clientid", 0ULL, 0}, - { "reclaim_complete", 0ULL, 0}, - - /* nfs42 */ - { "allocate", 0ULL, 0}, - { "copy", 0ULL, 0}, - { "copy_notify", 0ULL, 0}, - { "deallocate", 0ULL, 0}, - { "ioadvise", 0ULL, 0}, - { "layouterror", 0ULL, 0}, - { "layoutstats", 0ULL, 0}, - { "offload_cancel", 0ULL, 0}, - { "offload_status", 0ULL, 0}, - { "read_plus", 0ULL, 0}, - { "seek", 0ULL, 0}, - { "write_same", 0ULL, 0}, - - /* termination */ - { "", 0ULL, 0 } + { "unused_op0" , 0ULL, 0, NULL} + , {"unused_op1" , 0ULL, 0, NULL} + , {"future_op2" , 0ULL, 0, NULL} + , {"access" , 0ULL, 0, NULL} + , {"close" , 0ULL, 0, NULL} + , {"commit" , 0ULL, 0, NULL} + , {"create" , 0ULL, 0, NULL} + , {"delegpurge" , 0ULL, 0, NULL} + , {"delegreturn" , 0ULL, 0, NULL} + , {"getattr" , 0ULL, 0, NULL} + , {"getfh" , 0ULL, 0, NULL} + , {"link" , 0ULL, 0, NULL} + , {"lock" , 0ULL, 0, NULL} + , {"lockt" , 0ULL, 0, NULL} + , {"locku" , 0ULL, 0, NULL} + , {"lookup" , 0ULL, 0, NULL} + , {"lookup_root" , 0ULL, 0, NULL} + , {"nverify" , 0ULL, 0, NULL} + , {"open" , 0ULL, 0, NULL} + , {"openattr" , 0ULL, 0, NULL} + , {"open_confirm" , 0ULL, 0, NULL} + , {"open_downgrade" , 0ULL, 0, NULL} + , {"putfh" , 0ULL, 0, NULL} + , {"putpubfh" , 0ULL, 0, NULL} + , {"putrootfh" , 0ULL, 0, NULL} + , {"read" , 0ULL, 0, NULL} + , {"readdir" , 0ULL, 0, NULL} + , {"readlink" , 0ULL, 0, NULL} + , {"remove" , 0ULL, 0, NULL} + , {"rename" , 0ULL, 0, NULL} + , {"renew" , 0ULL, 0, NULL} + , {"restorefh" , 0ULL, 0, NULL} + , {"savefh" , 0ULL, 0, NULL} + , {"secinfo" , 0ULL, 0, NULL} + , {"setattr" , 0ULL, 0, NULL} + , {"setclientid" , 0ULL, 0, NULL} + , {"setclientid_confirm" , 0ULL, 0, NULL} + , {"verify" , 0ULL, 0, NULL} + , {"write" , 0ULL, 0, NULL} + , {"release_lockowner" , 0ULL, 0, NULL} + , + + /* nfs41 */ + { "backchannel_ctl" , 0ULL, 0, NULL} + , {"bind_conn_to_session", 0ULL, 0, NULL} + , {"exchange_id" , 0ULL, 0, NULL} + , {"create_session" , 0ULL, 0, NULL} + , {"destroy_session" , 0ULL, 0, NULL} + , {"free_stateid" , 0ULL, 0, NULL} + , {"get_dir_delegation" , 0ULL, 0, NULL} + , {"getdeviceinfo" , 0ULL, 0, NULL} + , {"getdevicelist" , 0ULL, 0, NULL} + , {"layoutcommit" , 0ULL, 0, NULL} + , {"layoutget" , 0ULL, 0, NULL} + , {"layoutreturn" , 0ULL, 0, NULL} + , {"secinfo_no_name" , 0ULL, 0, NULL} + , {"sequence" , 0ULL, 0, NULL} + , {"set_ssv" , 0ULL, 0, NULL} + , {"test_stateid" , 0ULL, 0, NULL} + , {"want_delegation" , 0ULL, 0, NULL} + , {"destroy_clientid" , 0ULL, 0, NULL} + , {"reclaim_complete" , 0ULL, 0, NULL} + , + + /* nfs42 */ + { "allocate" , 0ULL, 0, NULL} + , {"copy" , 0ULL, 0, NULL} + , {"copy_notify" , 0ULL, 0, NULL} + , {"deallocate" , 0ULL, 0, NULL} + , {"ioadvise" , 0ULL, 0, NULL} + , {"layouterror" , 0ULL, 0, NULL} + , {"layoutstats" , 0ULL, 0, NULL} + , {"offload_cancel" , 0ULL, 0, NULL} + , {"offload_status" , 0ULL, 0, NULL} + , {"read_plus" , 0ULL, 0, NULL} + , {"seek" , 0ULL, 0, NULL} + , {"write_same" , 0ULL, 0, NULL} + , + + /* termination */ + { "" , 0ULL, 0, NULL} }; @@ -487,234 +496,403 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { } } - RRDSET *st; - // -------------------------------------------------------------------- if(do_rc == 2) { - st = rrdset_find_bytype_localhost("nfsd", "readcache"); - if(!st) { - st = rrdset_create_localhost("nfsd", "readcache", NULL, "cache", NULL, "NFS Server Read Cache", "reads/s" - , 5000, update_every, RRDSET_TYPE_STACKED); - - rrddim_add(st, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "nocache", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + static RRDDIM *rd_hits = NULL, + *rd_misses = NULL, + *rd_nocache = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "readcache" + , NULL + , "cache" + , NULL + , "NFS Server Read Cache" + , "reads/s" + , "proc" + , "net/rpc/nfsd" + , 5000 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_hits = rrddim_add(st, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_misses = rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_nocache = rrddim_add(st, "nocache", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "hits", rc_hits); - rrddim_set(st, "misses", rc_misses); - rrddim_set(st, "nocache", rc_nocache); + rrddim_set_by_pointer(st, rd_hits, rc_hits); + rrddim_set_by_pointer(st, rd_misses, rc_misses); + rrddim_set_by_pointer(st, rd_nocache, rc_nocache); rrdset_done(st); } // -------------------------------------------------------------------- if(do_fh == 2) { - st = rrdset_find_bytype_localhost("nfsd", "filehandles"); - if(!st) { - st = rrdset_create_localhost("nfsd", "filehandles", NULL, "filehandles", NULL, "NFS Server File Handles" - , "handles/s", 5001, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_stale = NULL, + *rd_total_lookups = NULL, + *rd_anonymous_lookups = NULL, + *rd_dir_not_in_dcache = NULL, + *rd_non_dir_not_in_dcache = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "filehandles" + , NULL + , "filehandles" + , NULL + , "NFS Server File Handles" + , "handles/s" + , "proc" + , "net/rpc/nfsd" + , 5001 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "stale", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "total_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_stale = rrddim_add(st, "stale", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_total_lookups = rrddim_add(st, "total_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_anonymous_lookups = rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_dir_not_in_dcache = rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_non_dir_not_in_dcache = rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "stale", fh_stale); - rrddim_set(st, "total_lookups", fh_total_lookups); - rrddim_set(st, "anonymous_lookups", fh_anonymous_lookups); - rrddim_set(st, "dir_not_in_dcache", fh_dir_not_in_dcache); - rrddim_set(st, "non_dir_not_in_dcache", fh_non_dir_not_in_dcache); + rrddim_set_by_pointer(st, rd_stale, fh_stale); + rrddim_set_by_pointer(st, rd_total_lookups, fh_total_lookups); + rrddim_set_by_pointer(st, rd_anonymous_lookups, fh_anonymous_lookups); + rrddim_set_by_pointer(st, rd_dir_not_in_dcache, fh_dir_not_in_dcache); + rrddim_set_by_pointer(st, rd_non_dir_not_in_dcache, fh_non_dir_not_in_dcache); rrdset_done(st); } // -------------------------------------------------------------------- if(do_io == 2) { - st = rrdset_find_bytype_localhost("nfsd", "io"); - if(!st) { - st = rrdset_create_localhost("nfsd", "io", NULL, "io", NULL, "NFS Server I/O", "kilobytes/s", 5002 - , update_every, RRDSET_TYPE_AREA); - - rrddim_add(st, "read", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "write", NULL, -1, 1000, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + static RRDDIM *rd_read = NULL, + *rd_write = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "io" + , NULL + , "io" + , NULL + , "NFS Server I/O" + , "kilobytes/s" + , "proc" + , "net/rpc/nfsd" + , 5002 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_read = rrddim_add(st, "read", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rd_write = rrddim_add(st, "write", NULL, -1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "read", io_read); - rrddim_set(st, "write", io_write); + rrddim_set_by_pointer(st, rd_read, io_read); + rrddim_set_by_pointer(st, rd_write, io_write); rrdset_done(st); } // -------------------------------------------------------------------- if(do_th == 2) { - st = rrdset_find_bytype_localhost("nfsd", "threads"); - if(!st) { - st = rrdset_create_localhost("nfsd", "threads", NULL, "threads", NULL, "NFS Server Threads", "threads", 5003 - , update_every, RRDSET_TYPE_LINE); + { + static RRDSET *st = NULL; + static RRDDIM *rd_threads = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "threads" + , NULL + , "threads" + , NULL + , "NFS Server Threads" + , "threads" + , "proc" + , "net/rpc/nfsd" + , 5003 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_threads = rrddim_add(st, "threads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); - rrddim_add(st, "threads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_set_by_pointer(st, rd_threads, th_threads); + rrdset_done(st); } - else rrdset_next(st); - - rrddim_set(st, "threads", th_threads); - rrdset_done(st); - st = rrdset_find_bytype_localhost("nfsd", "threads_fullcnt"); - if(!st) { - st = rrdset_create_localhost("nfsd", "threads_fullcnt", NULL, "threads", NULL - , "NFS Server Threads Full Count", "ops/s", 5004, update_every - , RRDSET_TYPE_LINE); + { + static RRDSET *st = NULL; + static RRDDIM *rd_full_count = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "threads_fullcnt" + , NULL + , "threads" + , NULL + , "NFS Server Threads Full Count" + , "ops/s" + , "proc" + , "net/rpc/nfsd" + , 5004 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_full_count = rrddim_add(st, "full_count", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st); - rrddim_add(st, "full_count", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_set_by_pointer(st, rd_full_count, th_fullcnt); + rrdset_done(st); } - else rrdset_next(st); - rrddim_set(st, "full_count", th_fullcnt); - rrdset_done(st); - - st = rrdset_find_bytype_localhost("nfsd", "threads_histogram"); - if(!st) { - st = rrdset_create_localhost("nfsd", "threads_histogram", NULL, "threads", NULL - , "NFS Server Threads Usage Histogram", "percentage", 5005, update_every - , RRDSET_TYPE_LINE); - - rrddim_add(st, "0%-10%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "10%-20%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "20%-30%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "30%-40%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "40%-50%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "50%-60%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "60%-70%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "70%-80%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "80%-90%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - rrddim_add(st, "90%-100%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + { + static RRDSET *st = NULL; + static RRDDIM *rd_th_hist10 = NULL, + *rd_th_hist20 = NULL, + *rd_th_hist30 = NULL, + *rd_th_hist40 = NULL, + *rd_th_hist50 = NULL, + *rd_th_hist60 = NULL, + *rd_th_hist70 = NULL, + *rd_th_hist80 = NULL, + *rd_th_hist90 = NULL, + *rd_th_hist100 = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "threads_histogram" + , NULL + , "threads" + , NULL + , "NFS Server Threads Usage Histogram" + , "percentage" + , "proc" + , "net/rpc/nfsd" + , 5005 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_th_hist10 = rrddim_add(st, "0%-10%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist20 = rrddim_add(st, "10%-20%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist30 = rrddim_add(st, "20%-30%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist40 = rrddim_add(st, "30%-40%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist50 = rrddim_add(st, "40%-50%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist60 = rrddim_add(st, "50%-60%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist70 = rrddim_add(st, "60%-70%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist80 = rrddim_add(st, "70%-80%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist90 = rrddim_add(st, "80%-90%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rd_th_hist100 = rrddim_add(st, "90%-100%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_th_hist10, th_hist10); + rrddim_set_by_pointer(st, rd_th_hist20, th_hist20); + rrddim_set_by_pointer(st, rd_th_hist30, th_hist30); + rrddim_set_by_pointer(st, rd_th_hist40, th_hist40); + rrddim_set_by_pointer(st, rd_th_hist50, th_hist50); + rrddim_set_by_pointer(st, rd_th_hist60, th_hist60); + rrddim_set_by_pointer(st, rd_th_hist70, th_hist70); + rrddim_set_by_pointer(st, rd_th_hist80, th_hist80); + rrddim_set_by_pointer(st, rd_th_hist90, th_hist90); + rrddim_set_by_pointer(st, rd_th_hist100, th_hist100); + rrdset_done(st); } - else rrdset_next(st); - - rrddim_set(st, "0%-10%", th_hist10); - rrddim_set(st, "10%-20%", th_hist20); - rrddim_set(st, "20%-30%", th_hist30); - rrddim_set(st, "30%-40%", th_hist40); - rrddim_set(st, "40%-50%", th_hist50); - rrddim_set(st, "50%-60%", th_hist60); - rrddim_set(st, "60%-70%", th_hist70); - rrddim_set(st, "70%-80%", th_hist80); - rrddim_set(st, "80%-90%", th_hist90); - rrddim_set(st, "90%-100%", th_hist100); - rrdset_done(st); } // -------------------------------------------------------------------- if(do_ra == 2) { - st = rrdset_find_bytype_localhost("nfsd", "readahead"); - if(!st) { - st = rrdset_create_localhost("nfsd", "readahead", NULL, "readahead", NULL, "NFS Server Read Ahead Depth" - , "percentage", 5005, update_every, RRDSET_TYPE_STACKED); - - rrddim_add(st, "10%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "20%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "30%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "40%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "50%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "60%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "70%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "80%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "90%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "100%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + static RRDSET *st = NULL; + static RRDDIM *rd_ra_hist10 = NULL, + *rd_ra_hist20 = NULL, + *rd_ra_hist30 = NULL, + *rd_ra_hist40 = NULL, + *rd_ra_hist50 = NULL, + *rd_ra_hist60 = NULL, + *rd_ra_hist70 = NULL, + *rd_ra_hist80 = NULL, + *rd_ra_hist90 = NULL, + *rd_ra_hist100 = NULL, + *rd_ra_none = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "readahead" + , NULL + , "readahead" + , NULL + , "NFS Server Read Ahead Depth" + , "percentage" + , "proc" + , "net/rpc/nfsd" + , 5005 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_ra_hist10 = rrddim_add(st, "10%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist20 = rrddim_add(st, "20%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist30 = rrddim_add(st, "30%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist40 = rrddim_add(st, "40%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist50 = rrddim_add(st, "50%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist60 = rrddim_add(st, "60%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist70 = rrddim_add(st, "70%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist80 = rrddim_add(st, "80%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist90 = rrddim_add(st, "90%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_hist100 = rrddim_add(st, "100%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rd_ra_none = rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } else rrdset_next(st); // ignore ra_size - if(ra_size) {}; - - rrddim_set(st, "10%", ra_hist10); - rrddim_set(st, "20%", ra_hist20); - rrddim_set(st, "30%", ra_hist30); - rrddim_set(st, "40%", ra_hist40); - rrddim_set(st, "50%", ra_hist50); - rrddim_set(st, "60%", ra_hist60); - rrddim_set(st, "70%", ra_hist70); - rrddim_set(st, "80%", ra_hist80); - rrddim_set(st, "90%", ra_hist90); - rrddim_set(st, "100%", ra_hist100); - rrddim_set(st, "misses", ra_none); + (void)ra_size; + + rrddim_set_by_pointer(st, rd_ra_hist10, ra_hist10); + rrddim_set_by_pointer(st, rd_ra_hist20, ra_hist20); + rrddim_set_by_pointer(st, rd_ra_hist30, ra_hist30); + rrddim_set_by_pointer(st, rd_ra_hist40, ra_hist40); + rrddim_set_by_pointer(st, rd_ra_hist50, ra_hist50); + rrddim_set_by_pointer(st, rd_ra_hist60, ra_hist60); + rrddim_set_by_pointer(st, rd_ra_hist70, ra_hist70); + rrddim_set_by_pointer(st, rd_ra_hist80, ra_hist80); + rrddim_set_by_pointer(st, rd_ra_hist90, ra_hist90); + rrddim_set_by_pointer(st, rd_ra_hist100,ra_hist100); + rrddim_set_by_pointer(st, rd_ra_none, ra_none); rrdset_done(st); } // -------------------------------------------------------------------- if(do_net == 2) { - st = rrdset_find_bytype_localhost("nfsd", "net"); - if(!st) { - st = rrdset_create_localhost("nfsd", "net", NULL, "network", NULL, "NFS Server Network Statistics" - , "packets/s", 5007, update_every, RRDSET_TYPE_STACKED); + static RRDSET *st = NULL; + static RRDDIM *rd_udp = NULL, + *rd_tcp = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "net" + , NULL + , "network" + , NULL + , "NFS Server Network Statistics" + , "packets/s" + , "proc" + , "net/rpc/nfsd" + , 5007 + , update_every + , RRDSET_TYPE_STACKED + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); // ignore net_count, net_tcp_connections - if(net_count) {}; - if(net_tcp_connections) {}; + (void)net_count; + (void)net_tcp_connections; - rrddim_set(st, "udp", net_udp_count); - rrddim_set(st, "tcp", net_tcp_count); + rrddim_set_by_pointer(st, rd_udp, net_udp_count); + rrddim_set_by_pointer(st, rd_tcp, net_tcp_count); rrdset_done(st); } // -------------------------------------------------------------------- if(do_rpc == 2) { - st = rrdset_find_bytype_localhost("nfsd", "rpc"); - if(!st) { - st = rrdset_create_localhost("nfsd", "rpc", NULL, "rpc", NULL - , "NFS Server Remote Procedure Calls Statistics", "calls/s", 5008, update_every - , RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_calls = NULL, + *rd_bad_format = NULL, + *rd_bad_auth = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "rpc" + , NULL + , "rpc" + , NULL + , "NFS Server Remote Procedure Calls Statistics" + , "calls/s" + , "proc" + , "net/rpc/nfsd" + , 5008 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "bad_format", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "bad_auth", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_bad_format = rrddim_add(st, "bad_format", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_bad_auth = rrddim_add(st, "bad_auth", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); // ignore rpc_bad_client - if(rpc_bad_client) {}; + (void)rpc_bad_client; - rrddim_set(st, "calls", rpc_calls); - rrddim_set(st, "bad_format", rpc_bad_format); - rrddim_set(st, "bad_auth", rpc_bad_auth); + rrddim_set_by_pointer(st, rd_calls, rpc_calls); + rrddim_set_by_pointer(st, rd_bad_format, rpc_bad_format); + rrddim_set_by_pointer(st, rd_bad_auth, rpc_bad_auth); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc2 == 2) { - unsigned int i; - st = rrdset_find_bytype_localhost("nfsd", "proc2"); - if(!st) { - st = rrdset_create_localhost("nfsd", "proc2", NULL, "nfsv2rpc", NULL, "NFS v2 Server Remote Procedure Calls" - , "calls/s", 5009, update_every, RRDSET_TYPE_STACKED); - - for(i = 0; nfsd_proc2_values[i].present ; i++) - rrddim_add(st, nfsd_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "proc2" + , NULL + , "nfsv2rpc" + , NULL + , "NFS v2 Server Remote Procedure Calls" + , "calls/s" + , "proc" + , "net/rpc/nfsd" + , 5009 + , update_every + , RRDSET_TYPE_STACKED + ); } else rrdset_next(st); - for(i = 0; nfsd_proc2_values[i].present ; i++) - rrddim_set(st, nfsd_proc2_values[i].name, nfsd_proc2_values[i].value); + size_t i; + for(i = 0; nfsd_proc2_values[i].present ; i++) { + if(unlikely(!nfsd_proc2_values[i].rd)) + nfsd_proc2_values[i].rd = rrddim_add(st, nfsd_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_set_by_pointer(st, nfsd_proc2_values[i].rd, nfsd_proc2_values[i].value); + } rrdset_done(st); } @@ -722,19 +900,32 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_proc3 == 2) { - unsigned int i; - st = rrdset_find_bytype_localhost("nfsd", "proc3"); - if(!st) { - st = rrdset_create_localhost("nfsd", "proc3", NULL, "nfsv3rpc", NULL, "NFS v3 Server Remote Procedure Calls" - , "calls/s", 5010, update_every, RRDSET_TYPE_STACKED); - - for(i = 0; nfsd_proc3_values[i].present ; i++) - rrddim_add(st, nfsd_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "proc3" + , NULL + , "nfsv3rpc" + , NULL + , "NFS v3 Server Remote Procedure Calls" + , "calls/s" + , "proc" + , "net/rpc/nfsd" + , 5010 + , update_every + , RRDSET_TYPE_STACKED + ); } else rrdset_next(st); - for(i = 0; nfsd_proc3_values[i].present ; i++) - rrddim_set(st, nfsd_proc3_values[i].name, nfsd_proc3_values[i].value); + size_t i; + for(i = 0; nfsd_proc3_values[i].present ; i++) { + if(unlikely(!nfsd_proc3_values[i].rd)) + nfsd_proc3_values[i].rd = rrddim_add(st, nfsd_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_set_by_pointer(st, nfsd_proc3_values[i].rd, nfsd_proc3_values[i].value); + } rrdset_done(st); } @@ -742,19 +933,32 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_proc4 == 2) { - unsigned int i; - st = rrdset_find_bytype_localhost("nfsd", "proc4"); - if(!st) { - st = rrdset_create_localhost("nfsd", "proc4", NULL, "nfsv4rpc", NULL, "NFS v4 Server Remote Procedure Calls" - , "calls/s", 5011, update_every, RRDSET_TYPE_STACKED); - - for(i = 0; nfsd_proc4_values[i].present ; i++) - rrddim_add(st, nfsd_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "proc4" + , NULL + , "nfsv4rpc" + , NULL + , "NFS v4 Server Remote Procedure Calls" + , "calls/s" + , "proc" + , "net/rpc/nfsd" + , 5011 + , update_every + , RRDSET_TYPE_STACKED + ); } else rrdset_next(st); - for(i = 0; nfsd_proc4_values[i].present ; i++) - rrddim_set(st, nfsd_proc4_values[i].name, nfsd_proc4_values[i].value); + size_t i; + for(i = 0; nfsd_proc4_values[i].present ; i++) { + if(unlikely(!nfsd_proc4_values[i].rd)) + nfsd_proc4_values[i].rd = rrddim_add(st, nfsd_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_set_by_pointer(st, nfsd_proc4_values[i].rd, nfsd_proc4_values[i].value); + } rrdset_done(st); } @@ -762,19 +966,32 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_proc4ops == 2) { - unsigned int i; - st = rrdset_find_bytype_localhost("nfsd", "proc4ops"); - if(!st) { - st = rrdset_create_localhost("nfsd", "proc4ops", NULL, "nfsv2ops", NULL, "NFS v4 Server Operations" - , "operations/s", 5012, update_every, RRDSET_TYPE_STACKED); - - for(i = 0; nfsd4_ops_values[i].present ; i++) - rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + if(unlikely(!st)) { + st = rrdset_create_localhost( + "nfsd" + , "proc4ops" + , NULL + , "nfsv2ops" + , NULL + , "NFS v4 Server Operations" + , "operations/s" + , "proc" + , "net/rpc/nfsd" + , 5012 + , update_every + , RRDSET_TYPE_STACKED + ); } else rrdset_next(st); - for(i = 0; nfsd4_ops_values[i].present ; i++) - rrddim_set(st, nfsd4_ops_values[i].name, nfsd4_ops_values[i].value); + size_t i; + for(i = 0; nfsd4_ops_values[i].present ; i++) { + if(unlikely(!nfsd4_ops_values[i].rd)) + nfsd4_ops_values[i].rd = rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_set_by_pointer(st, nfsd4_ops_values[i].rd, nfsd4_ops_values[i].value); + } rrdset_done(st); } diff --git a/src/proc_net_snmp.c b/src/proc_net_snmp.c index 817c964b..fabfdf8c 100644 --- a/src/proc_net_snmp.c +++ b/src/proc_net_snmp.c @@ -2,197 +2,88 @@ #define RRD_TYPE_NET_SNMP "ipv4" -struct netstat_columns { - char *name; - uint32_t hash; - unsigned long long value; - int multiplier; // not needed everywhere - char *label; // not needed everywhere -}; - -static struct netstat_columns ip_data[] = { -// { "Forwarding", 0, 0, 1, NULL }, -// { "DefaultTTL", 0, 0, 1, NULL }, - { "InReceives", 0, 0, 1, NULL }, - { "InHdrErrors", 0, 0, 1, NULL }, - { "InAddrErrors", 0, 0, 1, NULL }, - { "ForwDatagrams", 0, 0, 1, NULL }, - { "InUnknownProtos", 0, 0, 1, NULL }, - { "InDiscards", 0, 0, 1, NULL }, - { "InDelivers", 0, 0, 1, NULL }, - { "OutRequests", 0, 0, 1, NULL }, - { "OutDiscards", 0, 0, 1, NULL }, - { "OutNoRoutes", 0, 0, 1, NULL }, -// { "ReasmTimeout", 0, 0, 1, NULL }, - { "ReasmReqds", 0, 0, 1, NULL }, - { "ReasmOKs", 0, 0, 1, NULL }, - { "ReasmFails", 0, 0, 1, NULL }, - { "FragOKs", 0, 0, 1, NULL }, - { "FragFails", 0, 0, 1, NULL }, - { "FragCreates", 0, 0, 1, NULL }, - { NULL, 0, 0, 0, NULL } -}; - -static struct netstat_columns icmp_data[] = { - { "InMsgs", 0, 0, 1, NULL }, - { "OutMsgs", 0, 0, -1, NULL }, - { "InErrors", 0, 0, 1, NULL }, - { "OutErrors", 0, 0, -1, NULL }, - { "InCsumErrors", 0, 0, 1, NULL }, - - // all these are available in icmpmsg -// { "InDestUnreachs", 0, 0, 1, NULL }, -// { "OutDestUnreachs", 0, 0, -1, NULL }, -// { "InTimeExcds", 0, 0, 1, NULL }, -// { "OutTimeExcds", 0, 0, -1, NULL }, -// { "InParmProbs", 0, 0, 1, NULL }, -// { "OutParmProbs", 0, 0, -1, NULL }, -// { "InSrcQuenchs", 0, 0, 1, NULL }, -// { "OutSrcQuenchs", 0, 0, -1, NULL }, -// { "InRedirects", 0, 0, 1, NULL }, -// { "OutRedirects", 0, 0, -1, NULL }, -// { "InEchos", 0, 0, 1, NULL }, -// { "OutEchos", 0, 0, -1, NULL }, -// { "InEchoReps", 0, 0, 1, NULL }, -// { "OutEchoReps", 0, 0, -1, NULL }, -// { "InTimestamps", 0, 0, 1, NULL }, -// { "OutTimestamps", 0, 0, -1, NULL }, -// { "InTimestampReps", 0, 0, 1, NULL }, -// { "OutTimestampReps", 0, 0, -1, NULL }, -// { "InAddrMasks", 0, 0, 1, NULL }, -// { "OutAddrMasks", 0, 0, -1, NULL }, -// { "InAddrMaskReps", 0, 0, 1, NULL }, -// { "OutAddrMaskReps", 0, 0, -1, NULL }, - - { NULL, 0, 0, 0, NULL } -}; - -static struct netstat_columns icmpmsg_data[] = { - { "InType0", 0, 0, 1, "InEchoReps" }, - { "OutType0", 0, 0, -1, "OutEchoReps" }, -// { "InType1", 0, 0, 1, NULL }, // unassigned -// { "OutType1", 0, 0, -1, NULL }, // unassigned -// { "InType2", 0, 0, 1, NULL }, // unassigned -// { "OutType2", 0, 0, -1, NULL }, // unassigned - { "InType3", 0, 0, 1, "InDestUnreachs" }, - { "OutType3", 0, 0, -1, "OutDestUnreachs" }, -// { "InType4", 0, 0, 1, "InSrcQuenchs" }, // deprecated -// { "OutType4", 0, 0, -1, "OutSrcQuenchs" }, // deprecated - { "InType5", 0, 0, 1, "InRedirects" }, - { "OutType5", 0, 0, -1, "OutRedirects" }, -// { "InType6", 0, 0, 1, "InAlterHostAddr" }, // deprecated -// { "OutType6", 0, 0, -1, "OutAlterHostAddr" }, // deprecated -// { "InType7", 0, 0, 1, NULL }, // unassigned -// { "OutType7", 0, 0, -1, NULL }, // unassigned - { "InType8", 0, 0, 1, "InEchos" }, - { "OutType8", 0, 0, -1, "OutEchos" }, - { "InType9", 0, 0, 1, "InRouterAdvert" }, - { "OutType9", 0, 0, -1, "OutRouterAdvert" }, - { "InType10", 0, 0, 1, "InRouterSelect" }, - { "OutType10", 0, 0, -1, "OutRouterSelect" }, - { "InType11", 0, 0, 1, "InTimeExcds" }, - { "OutType11", 0, 0, -1, "OutTimeExcds" }, - { "InType12", 0, 0, 1, "InParmProbs" }, - { "OutType12", 0, 0, -1, "OutParmProbs" }, - { "InType13", 0, 0, 1, "InTimestamps" }, - { "OutType13", 0, 0, -1, "OutTimestamps" }, - { "InType14", 0, 0, 1, "InTimestampReps" }, - { "OutType14", 0, 0, -1, "OutTimestampReps" }, -// { "InType15", 0, 0, 1, "InInfos" }, // deprecated -// { "OutType15", 0, 0, -1, "OutInfos" }, // deprecated -// { "InType16", 0, 0, 1, "InInfoReps" }, // deprecated -// { "OutType16", 0, 0, -1, "OutInfoReps" }, // deprecated -// { "InType17", 0, 0, 1, "InAddrMasks" }, // deprecated -// { "OutType17", 0, 0, -1, "OutAddrMasks" }, // deprecated -// { "InType18", 0, 0, 1, "InAddrMaskReps" }, // deprecated -// { "OutType18", 0, 0, -1, "OutAddrMaskReps" }, // deprecated -// { "InType30", 0, 0, 1, "InTraceroute" }, // deprecated -// { "OutType30", 0, 0, -1, "OutTraceroute" }, // deprecated - { NULL, 0, 0, 0, NULL } -}; - -static struct netstat_columns tcp_data[] = { -// { "RtoAlgorithm", 0, 0, 1, NULL }, -// { "RtoMin", 0, 0, 1, NULL }, -// { "RtoMax", 0, 0, 1, NULL }, -// { "MaxConn", 0, 0, 1, NULL }, - { "ActiveOpens", 0, 0, 1, NULL }, - { "PassiveOpens", 0, 0, 1, NULL }, - { "AttemptFails", 0, 0, 1, NULL }, - { "EstabResets", 0, 0, 1, NULL }, - { "CurrEstab", 0, 0, 1, NULL }, - { "InSegs", 0, 0, 1, NULL }, - { "OutSegs", 0, 0, 1, NULL }, - { "RetransSegs", 0, 0, 1, NULL }, - { "InErrs", 0, 0, 1, NULL }, - { "OutRsts", 0, 0, 1, NULL }, - { "InCsumErrors", 0, 0, 1, NULL }, - { NULL, 0, 0, 0, NULL } -}; - -static struct netstat_columns udp_data[] = { - { "InDatagrams", 0, 0, 1, NULL }, - { "NoPorts", 0, 0, 1, NULL }, - { "InErrors", 0, 0, 1, NULL }, - { "OutDatagrams", 0, 0, 1, NULL }, - { "RcvbufErrors", 0, 0, 1, NULL }, - { "SndbufErrors", 0, 0, 1, NULL }, - { "InCsumErrors", 0, 0, 1, NULL }, - { "IgnoredMulti", 0, 0, 1, NULL }, - { NULL, 0, 0, 0, NULL } -}; - -static struct netstat_columns udplite_data[] = { - { "InDatagrams", 0, 0, 1, NULL }, - { "NoPorts", 0, 0, 1, NULL }, - { "InErrors", 0, 0, 1, NULL }, - { "OutDatagrams", 0, 0, 1, NULL }, - { "RcvbufErrors", 0, 0, 1, NULL }, - { "SndbufErrors", 0, 0, 1, NULL }, - { "InCsumErrors", 0, 0, 1, NULL }, - { "IgnoredMulti", 0, 0, 1, NULL }, - { NULL, 0, 0, 0, NULL } -}; - -static void hash_array(struct netstat_columns *nc) { - int i; - - for(i = 0; nc[i].name ;i++) - nc[i].hash = simple_hash(nc[i].name); -} - -static unsigned long long *netstat_columns_find(struct netstat_columns *nc, const char *name) { - uint32_t i, hash = simple_hash(name); - - for(i = 0; nc[i].name ;i++) - if(unlikely(nc[i].hash == hash && !strcmp(nc[i].name, name))) - return &nc[i].value; - - fatal("Cannot find key '%s' in /proc/net/snmp internal array.", name); -} - -static void parse_line_pair(procfile *ff, struct netstat_columns *nc, size_t header_line, size_t values_line) { - size_t hwords = procfile_linewords(ff, header_line); - size_t vwords = procfile_linewords(ff, values_line); - size_t w, i; - - if(unlikely(vwords > hwords)) { - error("File /proc/net/snmp on header line %zu has %zu words, but on value line %zu has %zu words.", header_line, hwords, values_line, vwords); - vwords = hwords; - } - - for(w = 1; w < vwords ;w++) { - char *key = procfile_lineword(ff, header_line, w); - uint32_t hash = simple_hash(key); - - for(i = 0 ; nc[i].name ;i++) { - if(unlikely(hash == nc[i].hash && !strcmp(key, nc[i].name))) { - nc[i].value = str2ull(procfile_lineword(ff, values_line, w)); - break; - } - } - } -} +static struct proc_net_snmp { + // kernel_uint_t ip_Forwarding; + kernel_uint_t ip_DefaultTTL; + kernel_uint_t ip_InReceives; + kernel_uint_t ip_InHdrErrors; + kernel_uint_t ip_InAddrErrors; + kernel_uint_t ip_ForwDatagrams; + kernel_uint_t ip_InUnknownProtos; + kernel_uint_t ip_InDiscards; + kernel_uint_t ip_InDelivers; + kernel_uint_t ip_OutRequests; + kernel_uint_t ip_OutDiscards; + kernel_uint_t ip_OutNoRoutes; + kernel_uint_t ip_ReasmTimeout; + kernel_uint_t ip_ReasmReqds; + kernel_uint_t ip_ReasmOKs; + kernel_uint_t ip_ReasmFails; + kernel_uint_t ip_FragOKs; + kernel_uint_t ip_FragFails; + kernel_uint_t ip_FragCreates; + + kernel_uint_t icmp_InMsgs; + kernel_uint_t icmp_OutMsgs; + kernel_uint_t icmp_InErrors; + kernel_uint_t icmp_OutErrors; + kernel_uint_t icmp_InCsumErrors; + + kernel_uint_t icmpmsg_InEchoReps; + kernel_uint_t icmpmsg_OutEchoReps; + kernel_uint_t icmpmsg_InDestUnreachs; + kernel_uint_t icmpmsg_OutDestUnreachs; + kernel_uint_t icmpmsg_InRedirects; + kernel_uint_t icmpmsg_OutRedirects; + kernel_uint_t icmpmsg_InEchos; + kernel_uint_t icmpmsg_OutEchos; + kernel_uint_t icmpmsg_InRouterAdvert; + kernel_uint_t icmpmsg_OutRouterAdvert; + kernel_uint_t icmpmsg_InRouterSelect; + kernel_uint_t icmpmsg_OutRouterSelect; + kernel_uint_t icmpmsg_InTimeExcds; + kernel_uint_t icmpmsg_OutTimeExcds; + kernel_uint_t icmpmsg_InParmProbs; + kernel_uint_t icmpmsg_OutParmProbs; + kernel_uint_t icmpmsg_InTimestamps; + kernel_uint_t icmpmsg_OutTimestamps; + kernel_uint_t icmpmsg_InTimestampReps; + kernel_uint_t icmpmsg_OutTimestampReps; + + //kernel_uint_t tcp_RtoAlgorithm; + //kernel_uint_t tcp_RtoMin; + //kernel_uint_t tcp_RtoMax; + ssize_t tcp_MaxConn; + kernel_uint_t tcp_ActiveOpens; + kernel_uint_t tcp_PassiveOpens; + kernel_uint_t tcp_AttemptFails; + kernel_uint_t tcp_EstabResets; + kernel_uint_t tcp_CurrEstab; + kernel_uint_t tcp_InSegs; + kernel_uint_t tcp_OutSegs; + kernel_uint_t tcp_RetransSegs; + kernel_uint_t tcp_InErrs; + kernel_uint_t tcp_OutRsts; + kernel_uint_t tcp_InCsumErrors; + + kernel_uint_t udp_InDatagrams; + kernel_uint_t udp_NoPorts; + kernel_uint_t udp_InErrors; + kernel_uint_t udp_OutDatagrams; + kernel_uint_t udp_RcvbufErrors; + kernel_uint_t udp_SndbufErrors; + kernel_uint_t udp_InCsumErrors; + kernel_uint_t udp_IgnoredMulti; + + kernel_uint_t udplite_InDatagrams; + kernel_uint_t udplite_NoPorts; + kernel_uint_t udplite_InErrors; + kernel_uint_t udplite_OutDatagrams; + kernel_uint_t udplite_RcvbufErrors; + kernel_uint_t udplite_SndbufErrors; + kernel_uint_t udplite_InCsumErrors; + kernel_uint_t udplite_IgnoredMulti; +} snmp_root = { 0 }; int do_proc_net_snmp(int update_every, usec_t dt) { (void)dt; @@ -203,67 +94,17 @@ int do_proc_net_snmp(int update_every, usec_t dt) { do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1, do_udplite_packets = -1; static uint32_t hash_ip = 0, hash_icmp = 0, hash_tcp = 0, hash_udp = 0, hash_icmpmsg = 0, hash_udplite = 0; - //static unsigned long long *ip_Forwarding = NULL; - //static unsigned long long *ip_DefaultTTL = NULL; - static unsigned long long *ip_InReceives = NULL; - static unsigned long long *ip_InHdrErrors = NULL; - static unsigned long long *ip_InAddrErrors = NULL; - static unsigned long long *ip_ForwDatagrams = NULL; - static unsigned long long *ip_InUnknownProtos = NULL; - static unsigned long long *ip_InDiscards = NULL; - static unsigned long long *ip_InDelivers = NULL; - static unsigned long long *ip_OutRequests = NULL; - static unsigned long long *ip_OutDiscards = NULL; - static unsigned long long *ip_OutNoRoutes = NULL; - //static unsigned long long *ip_ReasmTimeout = NULL; - static unsigned long long *ip_ReasmReqds = NULL; - static unsigned long long *ip_ReasmOKs = NULL; - static unsigned long long *ip_ReasmFails = NULL; - static unsigned long long *ip_FragOKs = NULL; - static unsigned long long *ip_FragFails = NULL; - static unsigned long long *ip_FragCreates = NULL; - - static unsigned long long *icmp_InMsgs = NULL; - static unsigned long long *icmp_OutMsgs = NULL; - static unsigned long long *icmp_InErrors = NULL; - static unsigned long long *icmp_OutErrors = NULL; - static unsigned long long *icmp_InCsumErrors = NULL; - - //static unsigned long long *tcp_RtoAlgorithm = NULL; - //static unsigned long long *tcp_RtoMin = NULL; - //static unsigned long long *tcp_RtoMax = NULL; - //static unsigned long long *tcp_MaxConn = NULL; - static unsigned long long *tcp_ActiveOpens = NULL; - static unsigned long long *tcp_PassiveOpens = NULL; - static unsigned long long *tcp_AttemptFails = NULL; - static unsigned long long *tcp_EstabResets = NULL; - static unsigned long long *tcp_CurrEstab = NULL; - static unsigned long long *tcp_InSegs = NULL; - static unsigned long long *tcp_OutSegs = NULL; - static unsigned long long *tcp_RetransSegs = NULL; - static unsigned long long *tcp_InErrs = NULL; - static unsigned long long *tcp_OutRsts = NULL; - static unsigned long long *tcp_InCsumErrors = NULL; - - static unsigned long long *udp_InDatagrams = NULL; - static unsigned long long *udp_NoPorts = NULL; - static unsigned long long *udp_InErrors = NULL; - static unsigned long long *udp_OutDatagrams = NULL; - static unsigned long long *udp_RcvbufErrors = NULL; - static unsigned long long *udp_SndbufErrors = NULL; - static unsigned long long *udp_InCsumErrors = NULL; - static unsigned long long *udp_IgnoredMulti = NULL; - - static unsigned long long *udplite_InDatagrams = NULL; - static unsigned long long *udplite_NoPorts = NULL; - static unsigned long long *udplite_InErrors = NULL; - static unsigned long long *udplite_OutDatagrams = NULL; - static unsigned long long *udplite_RcvbufErrors = NULL; - static unsigned long long *udplite_SndbufErrors = NULL; - static unsigned long long *udplite_InCsumErrors = NULL; - static unsigned long long *udplite_IgnoredMulti = NULL; - - if(unlikely(do_ip_packets == -1)) { + static ARL_BASE *arl_ip = NULL, + *arl_icmp = NULL, + *arl_icmpmsg = NULL, + *arl_tcp = NULL, + *arl_udp = NULL, + *arl_udplite = NULL; + + static RRDVAR *tcp_max_connections_var = NULL; + static ssize_t last_max_connections = 0; + + if(unlikely(!arl_ip)) { do_ip_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1); do_ip_fragsout = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", 1); do_ip_fragsin = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1); @@ -285,72 +126,94 @@ int do_proc_net_snmp(int update_every, usec_t dt) { hash_icmpmsg = simple_hash("IcmpMsg"); hash_udplite = simple_hash("UdpLite"); - hash_array(ip_data); - hash_array(tcp_data); - hash_array(udp_data); - hash_array(icmp_data); - hash_array(icmpmsg_data); - hash_array(udplite_data); - - //ip_Forwarding = netstat_columns_find(ip_data, "Forwarding"); - //ip_DefaultTTL = netstat_columns_find(ip_data, "DefaultTTL"); - ip_InReceives = netstat_columns_find(ip_data, "InReceives"); - ip_InHdrErrors = netstat_columns_find(ip_data, "InHdrErrors"); - ip_InAddrErrors = netstat_columns_find(ip_data, "InAddrErrors"); - ip_ForwDatagrams = netstat_columns_find(ip_data, "ForwDatagrams"); - ip_InUnknownProtos = netstat_columns_find(ip_data, "InUnknownProtos"); - ip_InDiscards = netstat_columns_find(ip_data, "InDiscards"); - ip_InDelivers = netstat_columns_find(ip_data, "InDelivers"); - ip_OutRequests = netstat_columns_find(ip_data, "OutRequests"); - ip_OutDiscards = netstat_columns_find(ip_data, "OutDiscards"); - ip_OutNoRoutes = netstat_columns_find(ip_data, "OutNoRoutes"); - //ip_ReasmTimeout = netstat_columns_find(ip_data, "ReasmTimeout"); - ip_ReasmReqds = netstat_columns_find(ip_data, "ReasmReqds"); - ip_ReasmOKs = netstat_columns_find(ip_data, "ReasmOKs"); - ip_ReasmFails = netstat_columns_find(ip_data, "ReasmFails"); - ip_FragOKs = netstat_columns_find(ip_data, "FragOKs"); - ip_FragFails = netstat_columns_find(ip_data, "FragFails"); - ip_FragCreates = netstat_columns_find(ip_data, "FragCreates"); - - icmp_InMsgs = netstat_columns_find(icmp_data, "InMsgs"); - icmp_OutMsgs = netstat_columns_find(icmp_data, "OutMsgs"); - icmp_InErrors = netstat_columns_find(icmp_data, "InErrors"); - icmp_OutErrors = netstat_columns_find(icmp_data, "OutErrors"); - icmp_InCsumErrors = netstat_columns_find(icmp_data, "InCsumErrors"); - - //tcp_RtoAlgorithm = netstat_columns_find(tcp_data, "RtoAlgorithm"); - //tcp_RtoMin = netstat_columns_find(tcp_data, "RtoMin"); - //tcp_RtoMax = netstat_columns_find(tcp_data, "RtoMax"); - //tcp_MaxConn = netstat_columns_find(tcp_data, "MaxConn"); - tcp_ActiveOpens = netstat_columns_find(tcp_data, "ActiveOpens"); - tcp_PassiveOpens = netstat_columns_find(tcp_data, "PassiveOpens"); - tcp_AttemptFails = netstat_columns_find(tcp_data, "AttemptFails"); - tcp_EstabResets = netstat_columns_find(tcp_data, "EstabResets"); - tcp_CurrEstab = netstat_columns_find(tcp_data, "CurrEstab"); - tcp_InSegs = netstat_columns_find(tcp_data, "InSegs"); - tcp_OutSegs = netstat_columns_find(tcp_data, "OutSegs"); - tcp_RetransSegs = netstat_columns_find(tcp_data, "RetransSegs"); - tcp_InErrs = netstat_columns_find(tcp_data, "InErrs"); - tcp_OutRsts = netstat_columns_find(tcp_data, "OutRsts"); - tcp_InCsumErrors = netstat_columns_find(tcp_data, "InCsumErrors"); - - udp_InDatagrams = netstat_columns_find(udp_data, "InDatagrams"); - udp_NoPorts = netstat_columns_find(udp_data, "NoPorts"); - udp_InErrors = netstat_columns_find(udp_data, "InErrors"); - udp_OutDatagrams = netstat_columns_find(udp_data, "OutDatagrams"); - udp_RcvbufErrors = netstat_columns_find(udp_data, "RcvbufErrors"); - udp_SndbufErrors = netstat_columns_find(udp_data, "SndbufErrors"); - udp_InCsumErrors = netstat_columns_find(udp_data, "InCsumErrors"); - udp_IgnoredMulti = netstat_columns_find(udp_data, "IgnoredMulti"); - - udplite_InDatagrams = netstat_columns_find(udplite_data, "InDatagrams"); - udplite_NoPorts = netstat_columns_find(udplite_data, "NoPorts"); - udplite_InErrors = netstat_columns_find(udplite_data, "InErrors"); - udplite_OutDatagrams = netstat_columns_find(udplite_data, "OutDatagrams"); - udplite_RcvbufErrors = netstat_columns_find(udplite_data, "RcvbufErrors"); - udplite_SndbufErrors = netstat_columns_find(udplite_data, "SndbufErrors"); - udplite_InCsumErrors = netstat_columns_find(udplite_data, "InCsumErrors"); - udplite_IgnoredMulti = netstat_columns_find(udplite_data, "IgnoredMulti"); + arl_ip = arl_create("snmp/Ip", arl_callback_str2kernel_uint_t, 60); + // arl_expect(arl_ip, "Forwarding", &snmp_root.ip_Forwarding); + arl_expect(arl_ip, "DefaultTTL", &snmp_root.ip_DefaultTTL); + arl_expect(arl_ip, "InReceives", &snmp_root.ip_InReceives); + arl_expect(arl_ip, "InHdrErrors", &snmp_root.ip_InHdrErrors); + arl_expect(arl_ip, "InAddrErrors", &snmp_root.ip_InAddrErrors); + arl_expect(arl_ip, "ForwDatagrams", &snmp_root.ip_ForwDatagrams); + arl_expect(arl_ip, "InUnknownProtos", &snmp_root.ip_InUnknownProtos); + arl_expect(arl_ip, "InDiscards", &snmp_root.ip_InDiscards); + arl_expect(arl_ip, "InDelivers", &snmp_root.ip_InDelivers); + arl_expect(arl_ip, "OutRequests", &snmp_root.ip_OutRequests); + arl_expect(arl_ip, "OutDiscards", &snmp_root.ip_OutDiscards); + arl_expect(arl_ip, "OutNoRoutes", &snmp_root.ip_OutNoRoutes); + arl_expect(arl_ip, "ReasmTimeout", &snmp_root.ip_ReasmTimeout); + arl_expect(arl_ip, "ReasmReqds", &snmp_root.ip_ReasmReqds); + arl_expect(arl_ip, "ReasmOKs", &snmp_root.ip_ReasmOKs); + arl_expect(arl_ip, "ReasmFails", &snmp_root.ip_ReasmFails); + arl_expect(arl_ip, "FragOKs", &snmp_root.ip_FragOKs); + arl_expect(arl_ip, "FragFails", &snmp_root.ip_FragFails); + arl_expect(arl_ip, "FragCreates", &snmp_root.ip_FragCreates); + + arl_icmp = arl_create("snmp/Icmp", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_icmp, "InMsgs", &snmp_root.icmp_InMsgs); + arl_expect(arl_icmp, "OutMsgs", &snmp_root.icmp_OutMsgs); + arl_expect(arl_icmp, "InErrors", &snmp_root.icmp_InErrors); + arl_expect(arl_icmp, "OutErrors", &snmp_root.icmp_OutErrors); + arl_expect(arl_icmp, "InCsumErrors", &snmp_root.icmp_InCsumErrors); + + arl_icmpmsg = arl_create("snmp/Icmpmsg", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_icmpmsg, "InType0", &snmp_root.icmpmsg_InEchoReps); + arl_expect(arl_icmpmsg, "OutType0", &snmp_root.icmpmsg_OutEchoReps); + arl_expect(arl_icmpmsg, "InType3", &snmp_root.icmpmsg_InDestUnreachs); + arl_expect(arl_icmpmsg, "OutType3", &snmp_root.icmpmsg_OutDestUnreachs); + arl_expect(arl_icmpmsg, "InType5", &snmp_root.icmpmsg_InRedirects); + arl_expect(arl_icmpmsg, "OutType5", &snmp_root.icmpmsg_OutRedirects); + arl_expect(arl_icmpmsg, "InType8", &snmp_root.icmpmsg_InEchos); + arl_expect(arl_icmpmsg, "OutType8", &snmp_root.icmpmsg_OutEchos); + arl_expect(arl_icmpmsg, "InType9", &snmp_root.icmpmsg_InRouterAdvert); + arl_expect(arl_icmpmsg, "OutType9", &snmp_root.icmpmsg_OutRouterAdvert); + arl_expect(arl_icmpmsg, "InType10", &snmp_root.icmpmsg_InRouterSelect); + arl_expect(arl_icmpmsg, "OutType10", &snmp_root.icmpmsg_OutRouterSelect); + arl_expect(arl_icmpmsg, "InType11", &snmp_root.icmpmsg_InTimeExcds); + arl_expect(arl_icmpmsg, "OutType11", &snmp_root.icmpmsg_OutTimeExcds); + arl_expect(arl_icmpmsg, "InType12", &snmp_root.icmpmsg_InParmProbs); + arl_expect(arl_icmpmsg, "OutType12", &snmp_root.icmpmsg_OutParmProbs); + arl_expect(arl_icmpmsg, "InType13", &snmp_root.icmpmsg_InTimestamps); + arl_expect(arl_icmpmsg, "OutType13", &snmp_root.icmpmsg_OutTimestamps); + arl_expect(arl_icmpmsg, "InType14", &snmp_root.icmpmsg_InTimestampReps); + arl_expect(arl_icmpmsg, "OutType14", &snmp_root.icmpmsg_OutTimestampReps); + + arl_tcp = arl_create("snmp/Tcp", arl_callback_str2kernel_uint_t, 60); + // arl_expect(arl_tcp, "RtoAlgorithm", &snmp_root.tcp_RtoAlgorithm); + // arl_expect(arl_tcp, "RtoMin", &snmp_root.tcp_RtoMin); + // arl_expect(arl_tcp, "RtoMax", &snmp_root.tcp_RtoMax); + arl_expect(arl_tcp, "MaxConn", &snmp_root.tcp_MaxConn); + arl_expect(arl_tcp, "ActiveOpens", &snmp_root.tcp_ActiveOpens); + arl_expect(arl_tcp, "PassiveOpens", &snmp_root.tcp_PassiveOpens); + arl_expect(arl_tcp, "AttemptFails", &snmp_root.tcp_AttemptFails); + arl_expect(arl_tcp, "EstabResets", &snmp_root.tcp_EstabResets); + arl_expect(arl_tcp, "CurrEstab", &snmp_root.tcp_CurrEstab); + arl_expect(arl_tcp, "InSegs", &snmp_root.tcp_InSegs); + arl_expect(arl_tcp, "OutSegs", &snmp_root.tcp_OutSegs); + arl_expect(arl_tcp, "RetransSegs", &snmp_root.tcp_RetransSegs); + arl_expect(arl_tcp, "InErrs", &snmp_root.tcp_InErrs); + arl_expect(arl_tcp, "OutRsts", &snmp_root.tcp_OutRsts); + arl_expect(arl_tcp, "InCsumErrors", &snmp_root.tcp_InCsumErrors); + + arl_udp = arl_create("snmp/Udp", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_udp, "InDatagrams", &snmp_root.udp_InDatagrams); + arl_expect(arl_udp, "NoPorts", &snmp_root.udp_NoPorts); + arl_expect(arl_udp, "InErrors", &snmp_root.udp_InErrors); + arl_expect(arl_udp, "OutDatagrams", &snmp_root.udp_OutDatagrams); + arl_expect(arl_udp, "RcvbufErrors", &snmp_root.udp_RcvbufErrors); + arl_expect(arl_udp, "SndbufErrors", &snmp_root.udp_SndbufErrors); + arl_expect(arl_udp, "InCsumErrors", &snmp_root.udp_InCsumErrors); + arl_expect(arl_udp, "IgnoredMulti", &snmp_root.udp_IgnoredMulti); + + arl_udplite = arl_create("snmp/Udplite", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_udplite, "InDatagrams", &snmp_root.udplite_InDatagrams); + arl_expect(arl_udplite, "NoPorts", &snmp_root.udplite_NoPorts); + arl_expect(arl_udplite, "InErrors", &snmp_root.udplite_InErrors); + arl_expect(arl_udplite, "OutDatagrams", &snmp_root.udplite_OutDatagrams); + arl_expect(arl_udplite, "RcvbufErrors", &snmp_root.udplite_RcvbufErrors); + arl_expect(arl_udplite, "SndbufErrors", &snmp_root.udplite_SndbufErrors); + arl_expect(arl_udplite, "InCsumErrors", &snmp_root.udplite_InCsumErrors); + arl_expect(arl_udplite, "IgnoredMulti", &snmp_root.udplite_IgnoredMulti); + + tcp_max_connections_var = rrdvar_custom_host_variable_create(localhost, "tcp_max_connections"); } if(unlikely(!ff)) { @@ -364,9 +227,7 @@ int do_proc_net_snmp(int update_every, usec_t dt) { if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time size_t lines = procfile_lines(ff), l; - size_t words; - - RRDSET *st; + size_t words, w; for(l = 0; l < lines ;l++) { char *key = procfile_lineword(ff, l, 0); @@ -386,101 +247,170 @@ int do_proc_net_snmp(int update_every, usec_t dt) { continue; } - // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html - parse_line_pair(ff, ip_data, h, l); + arl_begin(arl_ip); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_ip, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0)) + break; + } // -------------------------------------------------------------------- if(do_ip_packets) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".packets"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets" - , "packets/s", 3000, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL); + static RRDSET *st = NULL; + static RRDDIM *rd_InReceives = NULL, + *rd_OutRequests = NULL, + *rd_ForwDatagrams = NULL, + *rd_InDelivers = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "packets" + , NULL + , "packets" + , NULL + , "IPv4 Packets" + , "packets/s" + , "proc" + , "net/snmp" + , 2450 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InReceives = rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutRequests = rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ForwDatagrams = rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InDelivers = rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "OutRequests", *ip_OutRequests); - rrddim_set(st, "InReceives", *ip_InReceives); - rrddim_set(st, "ForwDatagrams", *ip_ForwDatagrams); - rrddim_set(st, "InDelivers", *ip_InDelivers); + rrddim_set_by_pointer(st, rd_OutRequests, (collected_number)snmp_root.ip_OutRequests); + rrddim_set_by_pointer(st, rd_InReceives, (collected_number)snmp_root.ip_InReceives); + rrddim_set_by_pointer(st, rd_ForwDatagrams, (collected_number)snmp_root.ip_ForwDatagrams); + rrddim_set_by_pointer(st, rd_InDelivers, (collected_number)snmp_root.ip_InDelivers); rrdset_done(st); } // -------------------------------------------------------------------- if(do_ip_fragsout) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsout"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL - , "IPv4 Fragments Sent", "packets/s", 3010, update_every - , RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_FragOKs = NULL, + *rd_FragFails = NULL, + *rd_FragCreates = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "fragsout" + , NULL + , "fragments" + , NULL + , "IPv4 Fragments Sent" + , "packets/s" + , "proc" + , "net/snmp" + , 3020 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_FragOKs = rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_FragFails = rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_FragCreates = rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "FragOKs", *ip_FragOKs); - rrddim_set(st, "FragFails", *ip_FragFails); - rrddim_set(st, "FragCreates", *ip_FragCreates); + rrddim_set_by_pointer(st, rd_FragOKs, (collected_number)snmp_root.ip_FragOKs); + rrddim_set_by_pointer(st, rd_FragFails, (collected_number)snmp_root.ip_FragFails); + rrddim_set_by_pointer(st, rd_FragCreates, (collected_number)snmp_root.ip_FragCreates); rrdset_done(st); } // -------------------------------------------------------------------- if(do_ip_fragsin) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsin"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL - , "IPv4 Fragments Reassembly", "packets/s", 3011, update_every - , RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_ReasmOKs = NULL, + *rd_ReasmFails = NULL, + *rd_ReasmReqds = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "fragsin" + , NULL + , "fragments" + , NULL + , "IPv4 Fragments Reassembly" + , "packets/s" + , "proc" + , "net/snmp" + , 3030 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ReasmOKs = rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ReasmFails = rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ReasmReqds = rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "ReasmOKs", *ip_ReasmOKs); - rrddim_set(st, "ReasmFails", *ip_ReasmFails); - rrddim_set(st, "ReasmReqds", *ip_ReasmReqds); + rrddim_set_by_pointer(st, rd_ReasmOKs, (collected_number)snmp_root.ip_ReasmOKs); + rrddim_set_by_pointer(st, rd_ReasmFails, (collected_number)snmp_root.ip_ReasmFails); + rrddim_set_by_pointer(st, rd_ReasmReqds, (collected_number)snmp_root.ip_ReasmReqds); rrdset_done(st); } // -------------------------------------------------------------------- if(do_ip_errors) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".errors"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors" - , "packets/s", 3002, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InDiscards = NULL, + *rd_OutDiscards = NULL, + *rd_InHdrErrors = NULL, + *rd_OutNoRoutes = NULL, + *rd_InAddrErrors = NULL, + *rd_InUnknownProtos = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "errors" + , NULL + , "errors" + , NULL + , "IPv4 Errors" + , "packets/s" + , "proc" + , "net/snmp" + , 2470 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InDiscards = rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutDiscards = rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InHdrErrors = rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutNoRoutes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InAddrErrors = rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InUnknownProtos = rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InDiscards", *ip_InDiscards); - rrddim_set(st, "OutDiscards", *ip_OutDiscards); - rrddim_set(st, "InHdrErrors", *ip_InHdrErrors); - rrddim_set(st, "InAddrErrors", *ip_InAddrErrors); - rrddim_set(st, "InUnknownProtos", *ip_InUnknownProtos); - rrddim_set(st, "OutNoRoutes", *ip_OutNoRoutes); + rrddim_set_by_pointer(st, rd_InDiscards, (collected_number)snmp_root.ip_InDiscards); + rrddim_set_by_pointer(st, rd_OutDiscards, (collected_number)snmp_root.ip_OutDiscards); + rrddim_set_by_pointer(st, rd_InHdrErrors, (collected_number)snmp_root.ip_InHdrErrors); + rrddim_set_by_pointer(st, rd_InAddrErrors, (collected_number)snmp_root.ip_InAddrErrors); + rrddim_set_by_pointer(st, rd_InUnknownProtos, (collected_number)snmp_root.ip_InUnknownProtos); + rrddim_set_by_pointer(st, rd_OutNoRoutes, (collected_number)snmp_root.ip_OutNoRoutes); rrdset_done(st); } } @@ -498,43 +428,81 @@ int do_proc_net_snmp(int update_every, usec_t dt) { continue; } - parse_line_pair(ff, icmp_data, h, l); + arl_begin(arl_icmp); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_icmp, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0)) + break; + } // -------------------------------------------------------------------- if(do_icmp_packets) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets" - , "packets/s", 2602, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + { + static RRDSET *st_packets = NULL; + static RRDDIM *rd_InMsgs = NULL, + *rd_OutMsgs = NULL; + + if(unlikely(!st_packets)) { + st_packets = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "icmp" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Packets" + , "packets/s" + , "proc" + , "net/snmp" + , 2602 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InMsgs = rrddim_add(st_packets, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutMsgs = rrddim_add(st_packets, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st_packets); + + rrddim_set_by_pointer(st_packets, rd_InMsgs, (collected_number)snmp_root.icmp_InMsgs); + rrddim_set_by_pointer(st_packets, rd_OutMsgs, (collected_number)snmp_root.icmp_OutMsgs); + + rrdset_done(st_packets); } - else rrdset_next(st); - - rrddim_set(st, "InMsgs", *icmp_InMsgs); - rrddim_set(st, "OutMsgs", *icmp_OutMsgs); - - rrdset_done(st); - - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp_errors"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp_errors", NULL, "icmp", NULL - , "IPv4 ICMP Errors", "packets/s", 2603, update_every - , RRDSET_TYPE_LINE); - rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + { + static RRDSET *st_errors = NULL; + static RRDDIM *rd_InErrors = NULL, + *rd_OutErrors = NULL, + *rd_InCsumErrors = NULL; + + if(unlikely(!st_errors)) { + st_errors = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "icmp_errors" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Errors" + , "packets/s" + , "proc" + , "net/snmp" + , 2603 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InErrors = rrddim_add(st_errors, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutErrors = rrddim_add(st_errors, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCsumErrors = rrddim_add(st_errors, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st_errors); + + rrddim_set_by_pointer(st_errors, rd_InErrors, (collected_number)snmp_root.icmp_InErrors); + rrddim_set_by_pointer(st_errors, rd_OutErrors, (collected_number)snmp_root.icmp_OutErrors); + rrddim_set_by_pointer(st_errors, rd_InCsumErrors, (collected_number)snmp_root.icmp_InCsumErrors); + + rrdset_done(st_errors); } - else rrdset_next(st); - - rrddim_set(st, "InErrors", *icmp_InErrors); - rrddim_set(st, "OutErrors", *icmp_OutErrors); - rrddim_set(st, "InCsumErrors", *icmp_InCsumErrors); - - rrdset_done(st); } } else if(unlikely(hash == hash_icmpmsg && strcmp(key, "IcmpMsg") == 0)) { @@ -545,25 +513,102 @@ int do_proc_net_snmp(int update_every, usec_t dt) { break; } - parse_line_pair(ff, icmpmsg_data, h, l); + words = procfile_linewords(ff, l); + if(words < 3) { + error("Cannot read /proc/net/snmp IcmpMsg line. Expected 3+ params, read %zu.", words); + continue; + } + + arl_begin(arl_icmpmsg); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_icmpmsg, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0)) + break; + } // -------------------------------------------------------------------- if(do_icmpmsg) { - int i; - - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmpmsg"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messages" - , "packets/s", 2604, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InEchoReps = NULL, + *rd_OutEchoReps = NULL, + *rd_InDestUnreachs = NULL, + *rd_OutDestUnreachs = NULL, + *rd_InRedirects = NULL, + *rd_OutRedirects = NULL, + *rd_InEchos = NULL, + *rd_OutEchos = NULL, + *rd_InRouterAdvert = NULL, + *rd_OutRouterAdvert = NULL, + *rd_InRouterSelect = NULL, + *rd_OutRouterSelect = NULL, + *rd_InTimeExcds = NULL, + *rd_OutTimeExcds = NULL, + *rd_InParmProbs = NULL, + *rd_OutParmProbs = NULL, + *rd_InTimestamps = NULL, + *rd_OutTimestamps = NULL, + *rd_InTimestampReps = NULL, + *rd_OutTimestampReps = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "icmpmsg" + , NULL + , "icmp" + , NULL + , "IPv4 ICMP Messages" + , "packets/s" + , "proc" + , "net/snmp" + , 2604 + , update_every + , RRDSET_TYPE_LINE + ); - for(i = 0; icmpmsg_data[i].name ;i++) - rrddim_add(st, icmpmsg_data[i].name, icmpmsg_data[i].label, icmpmsg_data[i].multiplier, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InEchoReps = rrddim_add(st, "InType0", "InEchoReps", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutEchoReps = rrddim_add(st, "OutType0", "OutEchoReps", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InDestUnreachs = rrddim_add(st, "InType3", "InDestUnreachs", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutDestUnreachs = rrddim_add(st, "OutType3", "OutDestUnreachs", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InRedirects = rrddim_add(st, "InType5", "InRedirects", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutRedirects = rrddim_add(st, "OutType5", "OutRedirects", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InEchos = rrddim_add(st, "InType8", "InEchos", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutEchos = rrddim_add(st, "OutType8", "OutEchos", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InRouterAdvert = rrddim_add(st, "InType9", "InRouterAdvert", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutRouterAdvert = rrddim_add(st, "OutType9", "OutRouterAdvert", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InRouterSelect = rrddim_add(st, "InType10", "InRouterSelect", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutRouterSelect = rrddim_add(st, "OutType10", "OutRouterSelect", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InTimeExcds = rrddim_add(st, "InType11", "InTimeExcds", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutTimeExcds = rrddim_add(st, "OutType11", "OutTimeExcds", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InParmProbs = rrddim_add(st, "InType12", "InParmProbs", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutParmProbs = rrddim_add(st, "OutType12", "OutParmProbs", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InTimestamps = rrddim_add(st, "InType13", "InTimestamps", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutTimestamps = rrddim_add(st, "OutType13", "OutTimestamps", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InTimestampReps = rrddim_add(st, "InType14", "InTimestampReps", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutTimestampReps = rrddim_add(st, "OutType14", "OutTimestampReps", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - for(i = 0; icmpmsg_data[i].name ;i++) - rrddim_set(st, icmpmsg_data[i].name, icmpmsg_data[i].value); + rrddim_set_by_pointer(st, rd_InEchoReps, (collected_number)snmp_root.icmpmsg_InEchoReps); + rrddim_set_by_pointer(st, rd_OutEchoReps, (collected_number)snmp_root.icmpmsg_OutEchoReps); + rrddim_set_by_pointer(st, rd_InDestUnreachs, (collected_number)snmp_root.icmpmsg_InDestUnreachs); + rrddim_set_by_pointer(st, rd_OutDestUnreachs, (collected_number)snmp_root.icmpmsg_OutDestUnreachs); + rrddim_set_by_pointer(st, rd_InRedirects, (collected_number)snmp_root.icmpmsg_InRedirects); + rrddim_set_by_pointer(st, rd_OutRedirects, (collected_number)snmp_root.icmpmsg_OutRedirects); + rrddim_set_by_pointer(st, rd_InEchos, (collected_number)snmp_root.icmpmsg_InEchos); + rrddim_set_by_pointer(st, rd_OutEchos, (collected_number)snmp_root.icmpmsg_OutEchos); + rrddim_set_by_pointer(st, rd_InRouterAdvert, (collected_number)snmp_root.icmpmsg_InRouterAdvert); + rrddim_set_by_pointer(st, rd_OutRouterAdvert, (collected_number)snmp_root.icmpmsg_OutRouterAdvert); + rrddim_set_by_pointer(st, rd_InRouterSelect, (collected_number)snmp_root.icmpmsg_InRouterSelect); + rrddim_set_by_pointer(st, rd_OutRouterSelect, (collected_number)snmp_root.icmpmsg_OutRouterSelect); + rrddim_set_by_pointer(st, rd_InTimeExcds, (collected_number)snmp_root.icmpmsg_InTimeExcds); + rrddim_set_by_pointer(st, rd_OutTimeExcds, (collected_number)snmp_root.icmpmsg_OutTimeExcds); + rrddim_set_by_pointer(st, rd_InParmProbs, (collected_number)snmp_root.icmpmsg_InParmProbs); + rrddim_set_by_pointer(st, rd_OutParmProbs, (collected_number)snmp_root.icmpmsg_OutParmProbs); + rrddim_set_by_pointer(st, rd_InTimestamps, (collected_number)snmp_root.icmpmsg_InTimestamps); + rrddim_set_by_pointer(st, rd_OutTimestamps, (collected_number)snmp_root.icmpmsg_OutTimestamps); + rrddim_set_by_pointer(st, rd_InTimestampReps, (collected_number)snmp_root.icmpmsg_InTimestampReps); + rrddim_set_by_pointer(st, rd_OutTimestampReps, (collected_number)snmp_root.icmpmsg_OutTimestampReps); rrdset_done(st); } @@ -582,69 +627,132 @@ int do_proc_net_snmp(int update_every, usec_t dt) { continue; } - parse_line_pair(ff, tcp_data, h, l); + arl_begin(arl_tcp); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_tcp, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0)) + break; + } + + // -------------------------------------------------------------------- + + if(snmp_root.tcp_MaxConn != last_max_connections) { + last_max_connections = snmp_root.tcp_MaxConn; + rrdvar_custom_host_variable_set(localhost, tcp_max_connections_var, last_max_connections); + } // -------------------------------------------------------------------- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html if(do_tcp_sockets) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcpsock"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections" - , "active connections", 2500, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_CurrEstab = NULL; - rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "tcpsock" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Connections" + , "active connections" + , "proc" + , "net/snmp" + , 2501 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_CurrEstab = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); - rrddim_set(st, "CurrEstab", *tcp_CurrEstab); + rrddim_set_by_pointer(st, rd_CurrEstab, (collected_number)snmp_root.tcp_CurrEstab); rrdset_done(st); } // -------------------------------------------------------------------- if(do_tcp_packets) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcppackets"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets" - , "packets/s", 2600, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InSegs = NULL, + *rd_OutSegs = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "tcppackets" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Packets" + , "packets/s" + , "proc" + , "net/snmp" + , 2510 + , update_every + , RRDSET_TYPE_LINE + ); - rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InSegs = rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutSegs = rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InSegs", *tcp_InSegs); - rrddim_set(st, "OutSegs", *tcp_OutSegs); + rrddim_set_by_pointer(st, rd_InSegs, (collected_number)snmp_root.tcp_InSegs); + rrddim_set_by_pointer(st, rd_OutSegs, (collected_number)snmp_root.tcp_OutSegs); rrdset_done(st); } // -------------------------------------------------------------------- if(do_tcp_errors) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcperrors"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors" - , "packets/s", 2700, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InErrs = NULL, + *rd_InCsumErrors = NULL, + *rd_RetransSegs = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "tcperrors" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Errors" + , "packets/s" + , "proc" + , "net/snmp" + , 2520 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InErrs = rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_RetransSegs = rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InErrs", *tcp_InErrs); - rrddim_set(st, "InCsumErrors", *tcp_InCsumErrors); - rrddim_set(st, "RetransSegs", *tcp_RetransSegs); + rrddim_set_by_pointer(st, rd_InErrs, (collected_number)snmp_root.tcp_InErrs); + rrddim_set_by_pointer(st, rd_InCsumErrors, (collected_number)snmp_root.tcp_InCsumErrors); + rrddim_set_by_pointer(st, rd_RetransSegs, (collected_number)snmp_root.tcp_RetransSegs); rrdset_done(st); } // -------------------------------------------------------------------- if(do_tcp_handshake) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcphandshake"); - if(!st) { + static RRDSET *st = NULL; + static RRDDIM *rd_EstabResets = NULL, + *rd_OutRsts = NULL, + *rd_ActiveOpens = NULL, + *rd_PassiveOpens = NULL, + *rd_AttemptFails = NULL, + *rd_TCPSynRetrans = NULL; + + if(unlikely(!st)) { st = rrdset_create_localhost( RRD_TYPE_NET_SNMP , "tcphandshake" @@ -653,27 +761,29 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 TCP Handshake Issues" , "events/s" - , 2900 + , "proc" + , "net/snmp" + , 2530 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutRsts", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "TCPSynRetrans", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_EstabResets = rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutRsts = rrddim_add(st, "OutRsts", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ActiveOpens = rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_PassiveOpens = rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_AttemptFails = rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_TCPSynRetrans = rrddim_add(st, "TCPSynRetrans", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "EstabResets", *tcp_EstabResets); - rrddim_set(st, "OutRsts", *tcp_OutRsts); - rrddim_set(st, "ActiveOpens", *tcp_ActiveOpens); - rrddim_set(st, "PassiveOpens", *tcp_PassiveOpens); - rrddim_set(st, "AttemptFails", *tcp_AttemptFails); - rrddim_set(st, "TCPSynRetrans", tcpext_TCPSynRetrans); + rrddim_set_by_pointer(st, rd_EstabResets, (collected_number)snmp_root.tcp_EstabResets); + rrddim_set_by_pointer(st, rd_OutRsts, (collected_number)snmp_root.tcp_OutRsts); + rrddim_set_by_pointer(st, rd_ActiveOpens, (collected_number)snmp_root.tcp_ActiveOpens); + rrddim_set_by_pointer(st, rd_PassiveOpens, (collected_number)snmp_root.tcp_PassiveOpens); + rrddim_set_by_pointer(st, rd_AttemptFails, (collected_number)snmp_root.tcp_AttemptFails); + rrddim_set_by_pointer(st, rd_TCPSynRetrans, tcpext_TCPSynRetrans); rrdset_done(st); } } @@ -691,51 +801,89 @@ int do_proc_net_snmp(int update_every, usec_t dt) { continue; } - parse_line_pair(ff, udp_data, h, l); + arl_begin(arl_udp); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_udp, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0)) + break; + } // -------------------------------------------------------------------- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html if(do_udp_packets) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udppackets"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets" - , "packets/s", 2601, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InDatagrams = NULL, + *rd_OutDatagrams = NULL; - rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "udppackets" + , NULL + , "udp" + , NULL + , "IPv4 UDP Packets" + , "packets/s" + , "proc" + , "net/snmp" + , 2602 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InDatagrams = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutDatagrams = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InDatagrams", *udp_InDatagrams); - rrddim_set(st, "OutDatagrams", *udp_OutDatagrams); + rrddim_set_by_pointer(st, rd_InDatagrams, (collected_number)snmp_root.udp_InDatagrams); + rrddim_set_by_pointer(st, rd_OutDatagrams, (collected_number)snmp_root.udp_OutDatagrams); rrdset_done(st); } // -------------------------------------------------------------------- if(do_udp_errors) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udperrors"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors" - , "events/s", 2701, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_RcvbufErrors = NULL, + *rd_SndbufErrors = NULL, + *rd_InErrors = NULL, + *rd_NoPorts = NULL, + *rd_InCsumErrors = NULL, + *rd_IgnoredMulti = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "udperrors" + , NULL + , "udp" + , NULL + , "IPv4 UDP Errors" + , "events/s" + , "proc" + , "net/snmp" + , 2701 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_IgnoredMulti = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InErrors", *udp_InErrors); - rrddim_set(st, "NoPorts", *udp_NoPorts); - rrddim_set(st, "RcvbufErrors", *udp_RcvbufErrors); - rrddim_set(st, "SndbufErrors", *udp_SndbufErrors); - rrddim_set(st, "InCsumErrors", *udp_InCsumErrors); - rrddim_set(st, "IgnoredMulti", *udp_IgnoredMulti); + rrddim_set_by_pointer(st, rd_InErrors, (collected_number)snmp_root.udp_InErrors); + rrddim_set_by_pointer(st, rd_NoPorts, (collected_number)snmp_root.udp_NoPorts); + rrddim_set_by_pointer(st, rd_RcvbufErrors, (collected_number)snmp_root.udp_RcvbufErrors); + rrddim_set_by_pointer(st, rd_SndbufErrors, (collected_number)snmp_root.udp_SndbufErrors); + rrddim_set_by_pointer(st, rd_InCsumErrors, (collected_number)snmp_root.udp_InCsumErrors); + rrddim_set_by_pointer(st, rd_IgnoredMulti, (collected_number)snmp_root.udp_IgnoredMulti); rrdset_done(st); } } @@ -753,48 +901,87 @@ int do_proc_net_snmp(int update_every, usec_t dt) { continue; } - parse_line_pair(ff, udplite_data, h, l); + arl_begin(arl_udplite); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_udplite, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0)) + break; + } // -------------------------------------------------------------------- if(do_udplite_packets) { - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite", NULL, "udplite", NULL - , "IPv4 UDPLite Packets", "packets/s", 2603, update_every - , RRDSET_TYPE_LINE); - - rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + { + static RRDSET *st = NULL; + static RRDDIM *rd_InDatagrams = NULL, + *rd_OutDatagrams = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "udplite" + , NULL + , "udplite" + , NULL + , "IPv4 UDPLite Packets" + , "packets/s" + , "proc" + , "net/snmp" + , 2603 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InDatagrams = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutDatagrams = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_InDatagrams, (collected_number)snmp_root.udplite_InDatagrams); + rrddim_set_by_pointer(st, rd_OutDatagrams, (collected_number)snmp_root.udplite_OutDatagrams); + rrdset_done(st); } - else rrdset_next(st); - - rrddim_set(st, "InDatagrams", *udplite_InDatagrams); - rrddim_set(st, "OutDatagrams", *udplite_OutDatagrams); - rrdset_done(st); - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite_errors"); - if(!st) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite_errors", NULL, "udplite", NULL - , "IPv4 UDPLite Errors", "packets/s", 2604, update_every - , RRDSET_TYPE_LINE); - - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + { + static RRDSET *st = NULL; + static RRDDIM *rd_RcvbufErrors = NULL, + *rd_SndbufErrors = NULL, + *rd_InErrors = NULL, + *rd_NoPorts = NULL, + *rd_InCsumErrors = NULL, + *rd_IgnoredMulti = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "udplite_errors" + , NULL + , "udplite" + , NULL + , "IPv4 UDPLite Errors" + , "packets/s" + , "proc" + , "net/snmp" + , 2604 + , update_every + , RRDSET_TYPE_LINE); + + rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_IgnoredMulti = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_NoPorts, (collected_number)snmp_root.udplite_NoPorts); + rrddim_set_by_pointer(st, rd_InErrors, (collected_number)snmp_root.udplite_InErrors); + rrddim_set_by_pointer(st, rd_InCsumErrors, (collected_number)snmp_root.udplite_InCsumErrors); + rrddim_set_by_pointer(st, rd_RcvbufErrors, (collected_number)snmp_root.udplite_RcvbufErrors); + rrddim_set_by_pointer(st, rd_SndbufErrors, (collected_number)snmp_root.udplite_SndbufErrors); + rrddim_set_by_pointer(st, rd_IgnoredMulti, (collected_number)snmp_root.udplite_IgnoredMulti); + rrdset_done(st); } - else rrdset_next(st); - - rrddim_set(st, "NoPorts", *udplite_NoPorts); - rrddim_set(st, "InErrors", *udplite_InErrors); - rrddim_set(st, "InCsumErrors", *udplite_InCsumErrors); - rrddim_set(st, "RcvbufErrors", *udplite_RcvbufErrors); - rrddim_set(st, "SndbufErrors", *udplite_SndbufErrors); - rrddim_set(st, "IgnoredMulti", *udplite_IgnoredMulti); - rrdset_done(st); } } } diff --git a/src/proc_net_snmp6.c b/src/proc_net_snmp6.c index 6649b7af..bd71b391 100644 --- a/src/proc_net_snmp6.c +++ b/src/proc_net_snmp6.c @@ -272,24 +272,37 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { procfile_lineword(ff, l, 1)))) break; } - RRDSET *st; - // -------------------------------------------------------------------- if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (Ip6InOctets || Ip6OutOctets))) { do_bandwidth = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost("system.ipv6"); - if(unlikely(!st)) { - st = rrdset_create_localhost("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500 - , update_every, RRDSET_TYPE_AREA); + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL; - rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + "system" + , "ipv6" + , NULL + , "network" + , NULL + , "IPv6 Bandwidth" + , "kilobits/s" + , "proc" + , "net/snmp6" + , 502 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_received = rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_sent = rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Ip6OutOctets); - rrddim_set(st, "received", Ip6InOctets); + rrddim_set_by_pointer(st, rd_received, Ip6InOctets); + rrddim_set_by_pointer(st, rd_sent, Ip6OutOctets); rrdset_done(st); } @@ -297,22 +310,39 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_ip_packets == CONFIG_BOOLEAN_YES || (do_ip_packets == CONFIG_BOOLEAN_AUTO && (Ip6InReceives || Ip6OutRequests || Ip6InDelivers || Ip6OutForwDatagrams))) { do_ip_packets = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".packets"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "packets", NULL, "packets", NULL, "IPv6 Packets" - , "packets/s", 3000, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL, + *rd_forwarded = NULL, + *rd_delivers = NULL; - rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "forwarded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "delivers", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "packets" + , NULL + , "packets" + , NULL + , "IPv6 Packets" + , "packets/s" + , "proc" + , "net/snmp6" + , 3000 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_received = rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_sent = rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_forwarded = rrddim_add(st, "OutForwDatagrams", "forwarded", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_delivers = rrddim_add(st, "InDelivers", "delivers", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Ip6OutRequests); - rrddim_set(st, "received", Ip6InReceives); - rrddim_set(st, "forwarded", Ip6OutForwDatagrams); - rrddim_set(st, "delivers", Ip6InDelivers); + rrddim_set_by_pointer(st, rd_received, Ip6InReceives); + rrddim_set_by_pointer(st, rd_sent, Ip6OutRequests); + rrddim_set_by_pointer(st, rd_forwarded, Ip6OutForwDatagrams); + rrddim_set_by_pointer(st, rd_delivers, Ip6InDelivers); rrdset_done(st); } @@ -320,21 +350,37 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_ip_fragsout == CONFIG_BOOLEAN_YES || (do_ip_fragsout == CONFIG_BOOLEAN_AUTO && (Ip6FragOKs || Ip6FragFails || Ip6FragCreates))) { do_ip_fragsout = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".fragsout"); + static RRDSET *st = NULL; + static RRDDIM *rd_ok = NULL, + *rd_failed = NULL, + *rd_all = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent" - , "packets/s", 3010, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "fragsout" + , NULL + , "fragments6" + , NULL + , "IPv6 Fragments Sent" + , "packets/s" + , "proc" + , "net/snmp6" + , 3011 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ok = rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_failed = rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_all = rrddim_add(st, "FragCreates", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "ok", Ip6FragOKs); - rrddim_set(st, "failed", Ip6FragFails); - rrddim_set(st, "all", Ip6FragCreates); + rrddim_set_by_pointer(st, rd_ok, Ip6FragOKs); + rrddim_set_by_pointer(st, rd_failed, Ip6FragFails); + rrddim_set_by_pointer(st, rd_all, Ip6FragCreates); rrdset_done(st); } @@ -348,24 +394,40 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Ip6ReasmReqds ))) { do_ip_fragsin = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".fragsin"); + + static RRDSET *st = NULL; + static RRDDIM *rd_ok = NULL, + *rd_failed = NULL, + *rd_timeout = NULL, + *rd_all = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "fragsin", NULL, "fragments", NULL - , "IPv6 Fragments Reassembly", "packets/s", 3011, update_every - , RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "fragsin" + , NULL + , "fragments6" + , NULL + , "IPv6 Fragments Reassembly" + , "packets/s" + , "proc" + , "net/snmp6" + , 3012 + , update_every + , RRDSET_TYPE_LINE); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ok = rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_failed = rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_timeout = rrddim_add(st, "ReasmTimeout", "timeout", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_all = rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "ok", Ip6ReasmOKs); - rrddim_set(st, "failed", Ip6ReasmFails); - rrddim_set(st, "timeout", Ip6ReasmTimeout); - rrddim_set(st, "all", Ip6ReasmReqds); + rrddim_set_by_pointer(st, rd_ok, Ip6ReasmOKs); + rrddim_set_by_pointer(st, rd_failed, Ip6ReasmFails); + rrddim_set_by_pointer(st, rd_timeout, Ip6ReasmTimeout); + rrddim_set_by_pointer(st, rd_all, Ip6ReasmReqds); rrdset_done(st); } @@ -383,37 +445,55 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Ip6InNoRoutes ))) { do_ip_errors = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".errors"); + static RRDSET *st = NULL; + static RRDDIM *rd_InDiscards = NULL, + *rd_OutDiscards = NULL, + *rd_InHdrErrors = NULL, + *rd_InAddrErrors = NULL, + *rd_InUnknownProtos = NULL, + *rd_InTooBigErrors = NULL, + *rd_InTruncatedPkts = NULL, + *rd_InNoRoutes = NULL, + *rd_OutNoRoutes = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s" - , 3002, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "errors" + , NULL + , "errors" + , NULL + , "IPv6 Errors" + , "packets/s" + , "proc" + , "net/snmp6" + , 3002 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InTooBigErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InDiscards = rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutDiscards = rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InHdrErrors = rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InAddrErrors = rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InUnknownProtos = rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InTooBigErrors = rrddim_add(st, "InTooBigErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InTruncatedPkts = rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InNoRoutes = rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutNoRoutes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InDiscards", Ip6InDiscards); - rrddim_set(st, "OutDiscards", Ip6OutDiscards); - - rrddim_set(st, "InHdrErrors", Ip6InHdrErrors); - rrddim_set(st, "InAddrErrors", Ip6InAddrErrors); - rrddim_set(st, "InUnknownProtos", Ip6InUnknownProtos); - rrddim_set(st, "InTooBigErrors", Ip6InTooBigErrors); - rrddim_set(st, "InTruncatedPkts", Ip6InTruncatedPkts); - rrddim_set(st, "InNoRoutes", Ip6InNoRoutes); - - rrddim_set(st, "OutNoRoutes", Ip6OutNoRoutes); + rrddim_set_by_pointer(st, rd_InDiscards, Ip6InDiscards); + rrddim_set_by_pointer(st, rd_OutDiscards, Ip6OutDiscards); + rrddim_set_by_pointer(st, rd_InHdrErrors, Ip6InHdrErrors); + rrddim_set_by_pointer(st, rd_InAddrErrors, Ip6InAddrErrors); + rrddim_set_by_pointer(st, rd_InUnknownProtos, Ip6InUnknownProtos); + rrddim_set_by_pointer(st, rd_InTooBigErrors, Ip6InTooBigErrors); + rrddim_set_by_pointer(st, rd_InTruncatedPkts, Ip6InTruncatedPkts); + rrddim_set_by_pointer(st, rd_InNoRoutes, Ip6InNoRoutes); + rrddim_set_by_pointer(st, rd_OutNoRoutes, Ip6OutNoRoutes); rrdset_done(st); } @@ -421,18 +501,33 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_udp_packets == CONFIG_BOOLEAN_YES || (do_udp_packets == CONFIG_BOOLEAN_AUTO && (Udp6InDatagrams || Udp6OutDatagrams))) { do_udp_packets = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udppackets"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udppackets", NULL, "udp", NULL, "IPv6 UDP Packets" - , "packets/s", 3601, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL; - rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "udppackets" + , NULL + , "udp6" + , NULL + , "IPv6 UDP Packets" + , "packets/s" + , "proc" + , "net/snmp6" + , 3601 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_received = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_sent = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "received", Udp6InDatagrams); - rrddim_set(st, "sent", Udp6OutDatagrams); + rrddim_set_by_pointer(st, rd_received, Udp6InDatagrams); + rrddim_set_by_pointer(st, rd_sent, Udp6OutDatagrams); rrdset_done(st); } @@ -448,27 +543,46 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Udp6IgnoredMulti ))) { do_udp_errors = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udperrors"); + static RRDSET *st = NULL; + static RRDDIM *rd_RcvbufErrors = NULL, + *rd_SndbufErrors = NULL, + *rd_InErrors = NULL, + *rd_NoPorts = NULL, + *rd_InCsumErrors = NULL, + *rd_IgnoredMulti = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udperrors", NULL, "udp", NULL, "IPv6 UDP Errors" - , "events/s", 3701, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "udperrors" + , NULL + , "udp6" + , NULL + , "IPv6 UDP Errors" + , "events/s" + , "proc" + , "net/snmp6" + , 3701 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_IgnoredMulti = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InErrors", Udp6InErrors); - rrddim_set(st, "NoPorts", Udp6NoPorts); - rrddim_set(st, "RcvbufErrors", Udp6RcvbufErrors); - rrddim_set(st, "SndbufErrors", Udp6SndbufErrors); - rrddim_set(st, "InCsumErrors", Udp6InCsumErrors); - rrddim_set(st, "IgnoredMulti", Udp6IgnoredMulti); + rrddim_set_by_pointer(st, rd_RcvbufErrors, Udp6RcvbufErrors); + rrddim_set_by_pointer(st, rd_SndbufErrors, Udp6SndbufErrors); + rrddim_set_by_pointer(st, rd_InErrors, Udp6InErrors); + rrddim_set_by_pointer(st, rd_NoPorts, Udp6NoPorts); + rrddim_set_by_pointer(st, rd_InCsumErrors, Udp6InCsumErrors); + rrddim_set_by_pointer(st, rd_IgnoredMulti, Udp6IgnoredMulti); rrdset_done(st); } @@ -476,18 +590,33 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_udplite_packets == CONFIG_BOOLEAN_YES || (do_udplite_packets == CONFIG_BOOLEAN_AUTO && (UdpLite6InDatagrams || UdpLite6OutDatagrams))) { do_udplite_packets = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udplitepackets"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udplitepackets", NULL, "udplite", NULL - , "IPv6 UDPlite Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL; - rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "udplitepackets" + , NULL + , "udplite6" + , NULL + , "IPv6 UDPlite Packets" + , "packets/s" + , "proc" + , "net/snmp6" + , 3602 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_received = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_sent = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "received", UdpLite6InDatagrams); - rrddim_set(st, "sent", UdpLite6OutDatagrams); + rrddim_set_by_pointer(st, rd_received, UdpLite6InDatagrams); + rrddim_set_by_pointer(st, rd_sent, UdpLite6OutDatagrams); rrdset_done(st); } @@ -503,25 +632,43 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || UdpLite6InCsumErrors ))) { do_udplite_errors = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udpliteerrors"); + static RRDSET *st = NULL; + static RRDDIM *rd_RcvbufErrors = NULL, + *rd_SndbufErrors = NULL, + *rd_InErrors = NULL, + *rd_NoPorts = NULL, + *rd_InCsumErrors = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udpliteerrors", NULL, "udplite", NULL - , "IPv6 UDP Lite Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "udpliteerrors" + , NULL + , "udplite6" + , NULL + , "IPv6 UDP Lite Errors" + , "events/s" + , "proc" + , "net/snmp6" + , 3701 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InErrors", UdpLite6InErrors); - rrddim_set(st, "NoPorts", UdpLite6NoPorts); - rrddim_set(st, "RcvbufErrors", UdpLite6RcvbufErrors); - rrddim_set(st, "SndbufErrors", UdpLite6SndbufErrors); - rrddim_set(st, "InCsumErrors", UdpLite6InCsumErrors); + rrddim_set_by_pointer(st, rd_InErrors, UdpLite6InErrors); + rrddim_set_by_pointer(st, rd_NoPorts, UdpLite6NoPorts); + rrddim_set_by_pointer(st, rd_RcvbufErrors, UdpLite6RcvbufErrors); + rrddim_set_by_pointer(st, rd_SndbufErrors, UdpLite6SndbufErrors); + rrddim_set_by_pointer(st, rd_InCsumErrors, UdpLite6InCsumErrors); rrdset_done(st); } @@ -529,20 +676,34 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (Ip6OutMcastOctets || Ip6InMcastOctets))) { do_mcast = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".mcast"); + static RRDSET *st = NULL; + static RRDDIM *rd_Ip6InMcastOctets = NULL, + *rd_Ip6OutMcastOctets = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "mcast", NULL, "multicast", NULL - , "IPv6 Multicast Bandwidth", "kilobits/s", 9000, update_every - , RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "mcast" + , NULL + , "multicast6" + , NULL + , "IPv6 Multicast Bandwidth" + , "kilobits/s" + , "proc" + , "net/snmp6" + , 9000 + , update_every + , RRDSET_TYPE_AREA + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_Ip6InMcastOctets = rrddim_add(st, "InMcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_Ip6OutMcastOctets = rrddim_add(st, "OutMcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Ip6OutMcastOctets); - rrddim_set(st, "received", Ip6InMcastOctets); + rrddim_set_by_pointer(st, rd_Ip6InMcastOctets, Ip6InMcastOctets); + rrddim_set_by_pointer(st, rd_Ip6OutMcastOctets, Ip6OutMcastOctets); rrdset_done(st); } @@ -550,20 +711,34 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (Ip6OutBcastOctets || Ip6InBcastOctets))) { do_bcast = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".bcast"); + static RRDSET *st = NULL; + static RRDDIM *rd_Ip6InBcastOctets = NULL, + *rd_Ip6OutBcastOctets = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "bcast", NULL, "broadcast", NULL - , "IPv6 Broadcast Bandwidth", "kilobits/s", 8000, update_every - , RRDSET_TYPE_AREA); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "bcast" + , NULL + , "broadcast6" + , NULL + , "IPv6 Broadcast Bandwidth" + , "kilobits/s" + , "proc" + , "net/snmp6" + , 8000 + , update_every + , RRDSET_TYPE_AREA + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_Ip6InBcastOctets = rrddim_add(st, "InBcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_Ip6OutBcastOctets = rrddim_add(st, "OutBcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Ip6OutBcastOctets); - rrddim_set(st, "received", Ip6InBcastOctets); + rrddim_set_by_pointer(st, rd_Ip6InBcastOctets, Ip6InBcastOctets); + rrddim_set_by_pointer(st, rd_Ip6OutBcastOctets, Ip6OutBcastOctets); rrdset_done(st); } @@ -571,19 +746,34 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (Ip6OutMcastPkts || Ip6InMcastPkts))) { do_mcast_p = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".mcastpkts"); + static RRDSET *st = NULL; + static RRDDIM *rd_Ip6InMcastPkts = NULL, + *rd_Ip6OutMcastPkts = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "mcastpkts", NULL, "multicast", NULL - , "IPv6 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "mcastpkts" + , NULL + , "multicast6" + , NULL + , "IPv6 Multicast Packets" + , "packets/s" + , "proc" + , "net/snmp6" + , 9500 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_Ip6InMcastPkts = rrddim_add(st, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_Ip6OutMcastPkts = rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Ip6OutMcastPkts); - rrddim_set(st, "received", Ip6InMcastPkts); + rrddim_set_by_pointer(st, rd_Ip6InMcastPkts, Ip6InMcastPkts); + rrddim_set_by_pointer(st, rd_Ip6OutMcastPkts, Ip6OutMcastPkts); rrdset_done(st); } @@ -591,18 +781,33 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_icmp == CONFIG_BOOLEAN_YES || (do_icmp == CONFIG_BOOLEAN_AUTO && (Icmp6InMsgs || Icmp6OutMsgs))) { do_icmp = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmp"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages" - , "messages/s", 10000, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_Icmp6InMsgs = NULL, + *rd_Icmp6OutMsgs = NULL; - rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmp" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Messages" + , "messages/s" + , "proc" + , "net/snmp6" + , 10000 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_Icmp6InMsgs = rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_Icmp6OutMsgs = rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Icmp6InMsgs); - rrddim_set(st, "received", Icmp6OutMsgs); + rrddim_set_by_pointer(st, rd_Icmp6InMsgs, Icmp6InMsgs); + rrddim_set_by_pointer(st, rd_Icmp6OutMsgs, Icmp6OutMsgs); rrdset_done(st); } @@ -610,18 +815,33 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_icmp_redir == CONFIG_BOOLEAN_YES || (do_icmp_redir == CONFIG_BOOLEAN_AUTO && (Icmp6InRedirects || Icmp6OutRedirects))) { do_icmp_redir = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpredir"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects" - , "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_Icmp6InRedirects = NULL, + *rd_Icmp6OutRedirects = NULL; - rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmpredir" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Redirects" + , "redirects/s" + , "proc" + , "net/snmp6" + , 10050 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_Icmp6InRedirects = rrddim_add(st, "InRedirects", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_Icmp6OutRedirects = rrddim_add(st, "OutRedirects", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Icmp6InRedirects); - rrddim_set(st, "received", Icmp6OutRedirects); + rrddim_set_by_pointer(st, rd_Icmp6InRedirects, Icmp6InRedirects); + rrddim_set_by_pointer(st, rd_Icmp6OutRedirects, Icmp6OutRedirects); rrdset_done(st); } @@ -642,37 +862,60 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutParmProblems ))) { do_icmp_errors = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmperrors"); + static RRDSET *st = NULL; + static RRDDIM *rd_InErrors = NULL, + *rd_OutErrors = NULL, + *rd_InCsumErrors = NULL, + *rd_InDestUnreachs = NULL, + *rd_InPktTooBigs = NULL, + *rd_InTimeExcds = NULL, + *rd_InParmProblems = NULL, + *rd_OutDestUnreachs = NULL, + *rd_OutPktTooBigs = NULL, + *rd_OutTimeExcds = NULL, + *rd_OutParmProblems = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors" - , "errors/s", 10100, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutPktTooBigs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmperrors" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Errors" + , "errors/s" + , "proc" + , "net/snmp6" + , 10100 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutErrors = rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InDestUnreachs = rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InPktTooBigs = rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InTimeExcds = rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InParmProblems = rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutDestUnreachs = rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutPktTooBigs = rrddim_add(st, "OutPktTooBigs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutTimeExcds = rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutParmProblems = rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InErrors", Icmp6InErrors); - rrddim_set(st, "OutErrors", Icmp6OutErrors); - rrddim_set(st, "InCsumErrors", Icmp6InCsumErrors); - rrddim_set(st, "InDestUnreachs", Icmp6InDestUnreachs); - rrddim_set(st, "InPktTooBigs", Icmp6InPktTooBigs); - rrddim_set(st, "InTimeExcds", Icmp6InTimeExcds); - rrddim_set(st, "InParmProblems", Icmp6InParmProblems); - rrddim_set(st, "OutDestUnreachs", Icmp6OutDestUnreachs); - rrddim_set(st, "OutPktTooBigs", Icmp6OutPktTooBigs); - rrddim_set(st, "OutTimeExcds", Icmp6OutTimeExcds); - rrddim_set(st, "OutParmProblems", Icmp6OutParmProblems); + rrddim_set_by_pointer(st, rd_InErrors, Icmp6InErrors); + rrddim_set_by_pointer(st, rd_OutErrors, Icmp6OutErrors); + rrddim_set_by_pointer(st, rd_InCsumErrors, Icmp6InCsumErrors); + rrddim_set_by_pointer(st, rd_InDestUnreachs, Icmp6InDestUnreachs); + rrddim_set_by_pointer(st, rd_InPktTooBigs, Icmp6InPktTooBigs); + rrddim_set_by_pointer(st, rd_InTimeExcds, Icmp6InTimeExcds); + rrddim_set_by_pointer(st, rd_InParmProblems, Icmp6InParmProblems); + rrddim_set_by_pointer(st, rd_OutDestUnreachs, Icmp6OutDestUnreachs); + rrddim_set_by_pointer(st, rd_OutPktTooBigs, Icmp6OutPktTooBigs); + rrddim_set_by_pointer(st, rd_OutTimeExcds, Icmp6OutTimeExcds); + rrddim_set_by_pointer(st, rd_OutParmProblems, Icmp6OutParmProblems); rrdset_done(st); } @@ -686,22 +929,39 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutEchoReplies ))) { do_icmp_echos = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpechos"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo" - , "messages/s", 10200, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InEchos = NULL, + *rd_OutEchos = NULL, + *rd_InEchoReplies = NULL, + *rd_OutEchoReplies = NULL; - rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmpechos" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Echo" + , "messages/s" + , "proc" + , "net/snmp6" + , 10200 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InEchos = rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutEchos = rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InEchoReplies = rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutEchoReplies = rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InEchos", Icmp6InEchos); - rrddim_set(st, "OutEchos", Icmp6OutEchos); - rrddim_set(st, "InEchoReplies", Icmp6InEchoReplies); - rrddim_set(st, "OutEchoReplies", Icmp6OutEchoReplies); + rrddim_set_by_pointer(st, rd_InEchos, Icmp6InEchos); + rrddim_set_by_pointer(st, rd_OutEchos, Icmp6OutEchos); + rrddim_set_by_pointer(st, rd_InEchoReplies, Icmp6InEchoReplies); + rrddim_set_by_pointer(st, rd_OutEchoReplies, Icmp6OutEchoReplies); rrdset_done(st); } @@ -717,27 +977,44 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutGroupMembReductions ))) { do_icmp_groupmemb = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".groupmemb"); + static RRDSET *st = NULL; + static RRDDIM *rd_InQueries = NULL, + *rd_OutQueries = NULL, + *rd_InResponses = NULL, + *rd_OutResponses = NULL, + *rd_InReductions = NULL, + *rd_OutReductions = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "groupmemb", NULL, "icmp", NULL - , "IPv6 ICMP Group Membership", "messages/s", 10300, update_every - , RRDSET_TYPE_LINE); - - rrddim_add(st, "InQueries", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutQueries", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InResponses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutResponses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InReductions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutReductions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "groupmemb" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Group Membership" + , "messages/s" + , "proc" + , "net/snmp6" + , 10300 + , update_every + , RRDSET_TYPE_LINE); + + rd_InQueries = rrddim_add(st, "InQueries", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutQueries = rrddim_add(st, "OutQueries", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InResponses = rrddim_add(st, "InResponses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutResponses = rrddim_add(st, "OutResponses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InReductions = rrddim_add(st, "InReductions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutReductions = rrddim_add(st, "OutReductions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InQueries", Icmp6InGroupMembQueries); - rrddim_set(st, "OutQueries", Icmp6OutGroupMembQueries); - rrddim_set(st, "InResponses", Icmp6InGroupMembResponses); - rrddim_set(st, "OutResponses", Icmp6OutGroupMembResponses); - rrddim_set(st, "InReductions", Icmp6InGroupMembReductions); - rrddim_set(st, "OutReductions", Icmp6OutGroupMembReductions); + rrddim_set_by_pointer(st, rd_InQueries, Icmp6InGroupMembQueries); + rrddim_set_by_pointer(st, rd_OutQueries, Icmp6OutGroupMembQueries); + rrddim_set_by_pointer(st, rd_InResponses, Icmp6InGroupMembResponses); + rrddim_set_by_pointer(st, rd_OutResponses, Icmp6OutGroupMembResponses); + rrddim_set_by_pointer(st, rd_InReductions, Icmp6InGroupMembReductions); + rrddim_set_by_pointer(st, rd_OutReductions, Icmp6OutGroupMembReductions); rrdset_done(st); } @@ -751,22 +1028,39 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutRouterAdvertisements ))) { do_icmp_router = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmprouter"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages" - , "messages/s", 10400, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InSolicits = NULL, + *rd_OutSolicits = NULL, + *rd_InAdvertisements = NULL, + *rd_OutAdvertisements = NULL; - rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmprouter" + , NULL + , "icmp6" + , NULL + , "IPv6 Router Messages" + , "messages/s" + , "proc" + , "net/snmp6" + , 10400 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InSolicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutSolicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InAdvertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutAdvertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InSolicits", Icmp6InRouterSolicits); - rrddim_set(st, "OutSolicits", Icmp6OutRouterSolicits); - rrddim_set(st, "InAdvertisements", Icmp6InRouterAdvertisements); - rrddim_set(st, "OutAdvertisements", Icmp6OutRouterAdvertisements); + rrddim_set_by_pointer(st, rd_InSolicits, Icmp6InRouterSolicits); + rrddim_set_by_pointer(st, rd_OutSolicits, Icmp6OutRouterSolicits); + rrddim_set_by_pointer(st, rd_InAdvertisements, Icmp6InRouterAdvertisements); + rrddim_set_by_pointer(st, rd_OutAdvertisements, Icmp6OutRouterAdvertisements); rrdset_done(st); } @@ -780,23 +1074,39 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutNeighborAdvertisements ))) { do_icmp_neighbor = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpneighbor"); + static RRDSET *st = NULL; + static RRDDIM *rd_InSolicits = NULL, + *rd_OutSolicits = NULL, + *rd_InAdvertisements = NULL, + *rd_OutAdvertisements = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpneighbor", NULL, "icmp", NULL - , "IPv6 Neighbor Messages", "messages/s", 10500, update_every - , RRDSET_TYPE_LINE); - - rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmpneighbor" + , NULL + , "icmp6" + , NULL + , "IPv6 Neighbor Messages" + , "messages/s" + , "proc" + , "net/snmp6" + , 10500 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InSolicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutSolicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InAdvertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutAdvertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InSolicits", Icmp6InNeighborSolicits); - rrddim_set(st, "OutSolicits", Icmp6OutNeighborSolicits); - rrddim_set(st, "InAdvertisements", Icmp6InNeighborAdvertisements); - rrddim_set(st, "OutAdvertisements", Icmp6OutNeighborAdvertisements); + rrddim_set_by_pointer(st, rd_InSolicits, Icmp6InNeighborSolicits); + rrddim_set_by_pointer(st, rd_OutSolicits, Icmp6OutNeighborSolicits); + rrddim_set_by_pointer(st, rd_InAdvertisements, Icmp6InNeighborAdvertisements); + rrddim_set_by_pointer(st, rd_OutAdvertisements, Icmp6OutNeighborAdvertisements); rrdset_done(st); } @@ -804,18 +1114,33 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { if(do_icmp_mldv2 == CONFIG_BOOLEAN_YES || (do_icmp_mldv2 == CONFIG_BOOLEAN_AUTO && (Icmp6InMLDv2Reports || Icmp6OutMLDv2Reports))) { do_icmp_mldv2 = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpmldv2"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpmldv2", NULL, "icmp", NULL, "IPv6 ICMP MLDv2 Reports" - , "reports/s", 10600, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InMLDv2Reports = NULL, + *rd_OutMLDv2Reports = NULL; - rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmpmldv2" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP MLDv2 Reports" + , "reports/s" + , "proc" + , "net/snmp6" + , 10600 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InMLDv2Reports = rrddim_add(st, "InMLDv2Reports", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutMLDv2Reports = rrddim_add(st, "OutMLDv2Reports", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "sent", Icmp6InMLDv2Reports); - rrddim_set(st, "received", Icmp6OutMLDv2Reports); + rrddim_set_by_pointer(st, rd_InMLDv2Reports, Icmp6InMLDv2Reports); + rrddim_set_by_pointer(st, rd_OutMLDv2Reports, Icmp6OutMLDv2Reports); rrdset_done(st); } @@ -835,34 +1160,57 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutType143 ))) { do_icmp_types = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmptypes"); + static RRDSET *st = NULL; + static RRDDIM *rd_InType1 = NULL, + *rd_InType128 = NULL, + *rd_InType129 = NULL, + *rd_InType136 = NULL, + *rd_OutType1 = NULL, + *rd_OutType128 = NULL, + *rd_OutType129 = NULL, + *rd_OutType133 = NULL, + *rd_OutType135 = NULL, + *rd_OutType143 = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types" - , "messages/s", 10700, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmptypes" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Types" + , "messages/s" + , "proc" + , "net/snmp6" + , 10700 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InType1 = rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InType128 = rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InType129 = rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InType136 = rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutType1 = rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutType128 = rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutType129 = rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutType133 = rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutType135 = rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutType143 = rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InType1", Icmp6InType1); - rrddim_set(st, "InType128", Icmp6InType128); - rrddim_set(st, "InType129", Icmp6InType129); - rrddim_set(st, "InType136", Icmp6InType136); - rrddim_set(st, "OutType1", Icmp6OutType1); - rrddim_set(st, "OutType128", Icmp6OutType128); - rrddim_set(st, "OutType129", Icmp6OutType129); - rrddim_set(st, "OutType133", Icmp6OutType133); - rrddim_set(st, "OutType135", Icmp6OutType135); - rrddim_set(st, "OutType143", Icmp6OutType143); + rrddim_set_by_pointer(st, rd_InType1, Icmp6InType1); + rrddim_set_by_pointer(st, rd_InType128, Icmp6InType128); + rrddim_set_by_pointer(st, rd_InType129, Icmp6InType129); + rrddim_set_by_pointer(st, rd_InType136, Icmp6InType136); + rrddim_set_by_pointer(st, rd_OutType1, Icmp6OutType1); + rrddim_set_by_pointer(st, rd_OutType128, Icmp6OutType128); + rrddim_set_by_pointer(st, rd_OutType129, Icmp6OutType129); + rrddim_set_by_pointer(st, rd_OutType133, Icmp6OutType133); + rrddim_set_by_pointer(st, rd_OutType135, Icmp6OutType135); + rrddim_set_by_pointer(st, rd_OutType143, Icmp6OutType143); rrdset_done(st); } @@ -876,22 +1224,39 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Ip6InCEPkts ))) { do_ect = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".ect"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "ect", NULL, "packets", NULL, "IPv6 ECT Packets" - , "packets/s", 10800, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_InNoECTPkts = NULL, + *rd_InECT1Pkts = NULL, + *rd_InECT0Pkts = NULL, + *rd_InCEPkts = NULL; - rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InECT1Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InECT0Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InCEPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "ect" + , NULL + , "packets" + , NULL + , "IPv6 ECT Packets" + , "packets/s" + , "proc" + , "net/snmp6" + , 10800 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InNoECTPkts = rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InECT1Pkts = rrddim_add(st, "InECT1Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InECT0Pkts = rrddim_add(st, "InECT0Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_InCEPkts = rrddim_add(st, "InCEPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "InNoECTPkts", Ip6InNoECTPkts); - rrddim_set(st, "InECT1Pkts", Ip6InECT1Pkts); - rrddim_set(st, "InECT0Pkts", Ip6InECT0Pkts); - rrddim_set(st, "InCEPkts", Ip6InCEPkts); + rrddim_set_by_pointer(st, rd_InNoECTPkts, Ip6InNoECTPkts); + rrddim_set_by_pointer(st, rd_InECT1Pkts, Ip6InECT1Pkts); + rrddim_set_by_pointer(st, rd_InECT0Pkts, Ip6InECT0Pkts); + rrddim_set_by_pointer(st, rd_InCEPkts, Ip6InCEPkts); rrdset_done(st); } diff --git a/src/proc_net_sockstat.c b/src/proc_net_sockstat.c new file mode 100644 index 00000000..2ca4061b --- /dev/null +++ b/src/proc_net_sockstat.c @@ -0,0 +1,514 @@ +#include "common.h" + +static struct proc_net_sockstat { + kernel_uint_t sockets_used; + + kernel_uint_t tcp_inuse; + kernel_uint_t tcp_orphan; + kernel_uint_t tcp_tw; + kernel_uint_t tcp_alloc; + kernel_uint_t tcp_mem; + + kernel_uint_t udp_inuse; + kernel_uint_t udp_mem; + + kernel_uint_t udplite_inuse; + + kernel_uint_t raw_inuse; + + kernel_uint_t frag_inuse; + kernel_uint_t frag_memory; +} sockstat_root = { 0 }; + + +static int read_tcp_mem(void) { + static char *filename = NULL; + static RRDVAR *tcp_mem_low_threshold = NULL, + *tcp_mem_pressure_threshold = NULL, + *tcp_mem_high_threshold = NULL; + + if(unlikely(!tcp_mem_low_threshold)) { + tcp_mem_low_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_low"); + tcp_mem_pressure_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_pressure"); + tcp_mem_high_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_high"); + } + + if(unlikely(!filename)) { + char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%s/proc/sys/net/ipv4/tcp_mem", netdata_configured_host_prefix); + filename = strdupz(buffer); + } + + char buffer[200 + 1], *start, *end; + if(read_file(filename, buffer, 200) != 0) return 1; + buffer[200] = '\0'; + + unsigned long long low = 0, pressure = 0, high = 0; + + start = buffer; + low = strtoull(start, &end, 10); + + start = end; + pressure = strtoull(start, &end, 10); + + start = end; + high = strtoull(start, &end, 10); + + // fprintf(stderr, "TCP MEM low = %llu, pressure = %llu, high = %llu\n", low, pressure, high); + + rrdvar_custom_host_variable_set(localhost, tcp_mem_low_threshold, low * sysconf(_SC_PAGESIZE) / 1024); + rrdvar_custom_host_variable_set(localhost, tcp_mem_pressure_threshold, pressure * sysconf(_SC_PAGESIZE) / 1024); + rrdvar_custom_host_variable_set(localhost, tcp_mem_high_threshold, high * sysconf(_SC_PAGESIZE) / 1024); + + return 0; +} + +static kernel_uint_t read_tcp_max_orphans(void) { + static char *filename = NULL; + static RRDVAR *tcp_max_orphans_var = NULL; + + if(unlikely(!filename)) { + char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%s/proc/sys/net/ipv4/tcp_max_orphans", netdata_configured_host_prefix); + filename = strdupz(buffer); + } + + unsigned long long tcp_max_orphans = 0; + if(read_single_number_file(filename, &tcp_max_orphans) == 0) { + + if(unlikely(!tcp_max_orphans_var)) + tcp_max_orphans_var = rrdvar_custom_host_variable_create(localhost, "tcp_max_orphans"); + + rrdvar_custom_host_variable_set(localhost, tcp_max_orphans_var, tcp_max_orphans); + return tcp_max_orphans; + } + + return 0; +} + +int do_proc_net_sockstat(int update_every, usec_t dt) { + (void)dt; + + static procfile *ff = NULL; + + static uint32_t hash_sockets = 0, + hash_raw = 0, + hash_frag = 0, + hash_tcp = 0, + hash_udp = 0, + hash_udplite = 0; + + static long long update_constants_every = 60, update_constants_count = 0; + + static ARL_BASE *arl_sockets = NULL; + static ARL_BASE *arl_tcp = NULL; + static ARL_BASE *arl_udp = NULL; + static ARL_BASE *arl_udplite = NULL; + static ARL_BASE *arl_raw = NULL; + static ARL_BASE *arl_frag = NULL; + + static int do_sockets = -1, do_tcp_sockets = -1, do_tcp_mem = -1, do_udp_sockets = -1, do_udp_mem = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1, do_frag_mem = -1; + + static char *keys[7] = { NULL }; + static uint32_t hashes[7] = { 0 }; + static ARL_BASE *bases[7] = { NULL }; + + if(unlikely(!arl_sockets)) { + do_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 sockets", CONFIG_BOOLEAN_AUTO); + do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 TCP sockets", CONFIG_BOOLEAN_AUTO); + do_tcp_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 TCP memory", CONFIG_BOOLEAN_AUTO); + do_udp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDP sockets", CONFIG_BOOLEAN_AUTO); + do_udp_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDP memory", CONFIG_BOOLEAN_AUTO); + do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDPLITE sockets", CONFIG_BOOLEAN_AUTO); + do_raw_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 RAW sockets", CONFIG_BOOLEAN_AUTO); + do_frag_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 FRAG sockets", CONFIG_BOOLEAN_AUTO); + do_frag_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 FRAG memory", CONFIG_BOOLEAN_AUTO); + + update_constants_every = config_get_number("plugin:proc:/proc/net/sockstat", "update constants every", update_constants_every); + update_constants_count = update_constants_every; + + arl_sockets = arl_create("sockstat/sockets", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_sockets, "used", &sockstat_root.sockets_used); + + arl_tcp = arl_create("sockstat/TCP", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_tcp, "inuse", &sockstat_root.tcp_inuse); + arl_expect(arl_tcp, "orphan", &sockstat_root.tcp_orphan); + arl_expect(arl_tcp, "tw", &sockstat_root.tcp_tw); + arl_expect(arl_tcp, "alloc", &sockstat_root.tcp_alloc); + arl_expect(arl_tcp, "mem", &sockstat_root.tcp_mem); + + arl_udp = arl_create("sockstat/UDP", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_udp, "inuse", &sockstat_root.udp_inuse); + arl_expect(arl_udp, "mem", &sockstat_root.udp_mem); + + arl_udplite = arl_create("sockstat/UDPLITE", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_udplite, "inuse", &sockstat_root.udplite_inuse); + + arl_raw = arl_create("sockstat/RAW", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_raw, "inuse", &sockstat_root.raw_inuse); + + arl_frag = arl_create("sockstat/FRAG", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_frag, "inuse", &sockstat_root.frag_inuse); + arl_expect(arl_frag, "memory", &sockstat_root.frag_memory); + + hash_sockets = simple_hash("sockets"); + hash_tcp = simple_hash("TCP"); + hash_udp = simple_hash("UDP"); + hash_udplite = simple_hash("UDPLITE"); + hash_raw = simple_hash("RAW"); + hash_frag = simple_hash("FRAG"); + + keys[0] = "sockets"; hashes[0] = hash_sockets; bases[0] = arl_sockets; + keys[1] = "TCP"; hashes[1] = hash_tcp; bases[1] = arl_tcp; + keys[2] = "UDP"; hashes[2] = hash_udp; bases[2] = arl_udp; + keys[3] = "UDPLITE"; hashes[3] = hash_udplite; bases[3] = arl_udplite; + keys[4] = "RAW"; hashes[4] = hash_raw; bases[4] = arl_raw; + keys[5] = "FRAG"; hashes[5] = hash_frag; bases[5] = arl_frag; + keys[6] = NULL; // terminator + } + + update_constants_count += update_every; + if(unlikely(update_constants_count > update_constants_every)) { + read_tcp_max_orphans(); + read_tcp_mem(); + update_constants_count = 0; + } + + if(unlikely(!ff)) { + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat"); + ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) return 1; + } + + ff = procfile_readall(ff); + if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time + + size_t lines = procfile_lines(ff), l; + + for(l = 0; l < lines ;l++) { + size_t words = procfile_linewords(ff, l); + char *key = procfile_lineword(ff, l, 0); + uint32_t hash = simple_hash(key); + + int k; + for(k = 0; keys[k] ; k++) { + if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) { + // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words); + ARL_BASE *arl = bases[k]; + arl_begin(arl); + size_t w = 1; + + while(w + 1 < words) { + char *name = procfile_lineword(ff, l, w); w++; + char *value = procfile_lineword(ff, l, w); w++; + // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words); + if(unlikely(arl_check(arl, name, value) != 0)) + break; + } + + break; + } + } + } + + // ------------------------------------------------------------------------ + + if(do_sockets == CONFIG_BOOLEAN_YES || (do_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.sockets_used)) { + do_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_used = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_sockets" + , NULL + , "sockets" + , NULL + , "IPv4 Sockets Used" + , "sockets" + , "proc" + , "net/sockstat" + , 2400 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_used = rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_used, (collected_number)sockstat_root.sockets_used); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && (sockstat_root.tcp_inuse || sockstat_root.tcp_orphan || sockstat_root.tcp_tw || sockstat_root.tcp_alloc))) { + do_tcp_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL, + *rd_orphan = NULL, + *rd_timewait = NULL, + *rd_alloc = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_tcp_sockets" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Sockets" + , "sockets" + , "proc" + , "net/sockstat" + , 2500 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_alloc = rrddim_add(st, "alloc", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_orphan = rrddim_add(st, "orphan", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_timewait = rrddim_add(st, "timewait", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.tcp_inuse); + rrddim_set_by_pointer(st, rd_orphan, (collected_number)sockstat_root.tcp_orphan); + rrddim_set_by_pointer(st, rd_timewait, (collected_number)sockstat_root.tcp_tw); + rrddim_set_by_pointer(st, rd_alloc, (collected_number)sockstat_root.tcp_alloc); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_tcp_mem == CONFIG_BOOLEAN_YES || (do_tcp_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.tcp_mem)) { + do_tcp_mem = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_mem = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_tcp_mem" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Sockets Memory" + , "KB" + , "proc" + , "net/sockstat" + , 2540 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_mem = rrddim_add(st, "mem", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.tcp_mem); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.udp_inuse)) { + do_udp_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_udp_sockets" + , NULL + , "udp" + , NULL + , "IPv4 UDP Sockets" + , "sockets" + , "proc" + , "net/sockstat" + , 2600 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.udp_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_udp_mem == CONFIG_BOOLEAN_YES || (do_udp_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.udp_mem)) { + do_udp_mem = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_mem = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_udp_mem" + , NULL + , "udp" + , NULL + , "IPv4 UDP Sockets Memory" + , "KB" + , "proc" + , "net/sockstat" + , 2603 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_mem = rrddim_add(st, "mem", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.udp_mem); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.udplite_inuse)) { + do_udplite_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_udplite_sockets" + , NULL + , "udplite" + , NULL + , "IPv4 UDPLITE Sockets" + , "sockets" + , "proc" + , "net/sockstat" + , 2602 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.udplite_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.raw_inuse)) { + do_raw_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_raw_sockets" + , NULL + , "raw" + , NULL + , "IPv4 RAW Sockets" + , "sockets" + , "proc" + , "net/sockstat" + , 3010 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.raw_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.frag_inuse)) { + do_frag_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_frag_sockets" + , NULL + , "fragments" + , NULL + , "IPv4 FRAG Sockets" + , "fragments" + , "proc" + , "net/sockstat" + , 3010 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.frag_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_frag_mem == CONFIG_BOOLEAN_YES || (do_frag_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.frag_memory)) { + do_frag_mem = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_mem = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv4" + , "sockstat_frag_mem" + , NULL + , "fragments" + , NULL + , "IPv4 FRAG Sockets Memory" + , "KB" + , "proc" + , "net/sockstat" + , 3020 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_mem = rrddim_add(st, "mem", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.frag_memory); + rrdset_done(st); + } + + return 0; +} + diff --git a/src/proc_net_sockstat6.c b/src/proc_net_sockstat6.c new file mode 100644 index 00000000..97175ccf --- /dev/null +++ b/src/proc_net_sockstat6.c @@ -0,0 +1,269 @@ +#include "common.h" + +static struct proc_net_sockstat6 { + kernel_uint_t tcp6_inuse; + kernel_uint_t udp6_inuse; + kernel_uint_t udplite6_inuse; + kernel_uint_t raw6_inuse; + kernel_uint_t frag6_inuse; +} sockstat6_root = { 0 }; + +int do_proc_net_sockstat6(int update_every, usec_t dt) { + (void)dt; + + static procfile *ff = NULL; + + static uint32_t hash_raw = 0, + hash_frag = 0, + hash_tcp = 0, + hash_udp = 0, + hash_udplite = 0; + + static ARL_BASE *arl_tcp = NULL; + static ARL_BASE *arl_udp = NULL; + static ARL_BASE *arl_udplite = NULL; + static ARL_BASE *arl_raw = NULL; + static ARL_BASE *arl_frag = NULL; + + static int do_tcp_sockets = -1, do_udp_sockets = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1; + + static char *keys[6] = { NULL }; + static uint32_t hashes[6] = { 0 }; + static ARL_BASE *bases[6] = { NULL }; + + if(unlikely(!arl_tcp)) { + do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 TCP sockets", CONFIG_BOOLEAN_AUTO); + do_udp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDP sockets", CONFIG_BOOLEAN_AUTO); + do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDPLITE sockets", CONFIG_BOOLEAN_AUTO); + do_raw_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 RAW sockets", CONFIG_BOOLEAN_AUTO); + do_frag_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 FRAG sockets", CONFIG_BOOLEAN_AUTO); + + arl_tcp = arl_create("sockstat6/TCP6", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_tcp, "inuse", &sockstat6_root.tcp6_inuse); + + arl_udp = arl_create("sockstat6/UDP6", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_udp, "inuse", &sockstat6_root.udp6_inuse); + + arl_udplite = arl_create("sockstat6/UDPLITE6", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_udplite, "inuse", &sockstat6_root.udplite6_inuse); + + arl_raw = arl_create("sockstat6/RAW6", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_raw, "inuse", &sockstat6_root.raw6_inuse); + + arl_frag = arl_create("sockstat6/FRAG6", arl_callback_str2kernel_uint_t, 60); + arl_expect(arl_frag, "inuse", &sockstat6_root.frag6_inuse); + + hash_tcp = simple_hash("TCP6"); + hash_udp = simple_hash("UDP6"); + hash_udplite = simple_hash("UDPLITE6"); + hash_raw = simple_hash("RAW6"); + hash_frag = simple_hash("FRAG6"); + + keys[0] = "TCP6"; hashes[0] = hash_tcp; bases[0] = arl_tcp; + keys[1] = "UDP6"; hashes[1] = hash_udp; bases[1] = arl_udp; + keys[2] = "UDPLITE6"; hashes[2] = hash_udplite; bases[2] = arl_udplite; + keys[3] = "RAW6"; hashes[3] = hash_raw; bases[3] = arl_raw; + keys[4] = "FRAG6"; hashes[4] = hash_frag; bases[4] = arl_frag; + keys[5] = NULL; // terminator + } + + if(unlikely(!ff)) { + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat6"); + ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat6", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) return 1; + } + + ff = procfile_readall(ff); + if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time + + size_t lines = procfile_lines(ff), l; + + for(l = 0; l < lines ;l++) { + size_t words = procfile_linewords(ff, l); + char *key = procfile_lineword(ff, l, 0); + uint32_t hash = simple_hash(key); + + int k; + for(k = 0; keys[k] ; k++) { + if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) { + // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words); + ARL_BASE *arl = bases[k]; + arl_begin(arl); + size_t w = 1; + + while(w + 1 < words) { + char *name = procfile_lineword(ff, l, w); w++; + char *value = procfile_lineword(ff, l, w); w++; + // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words); + if(unlikely(arl_check(arl, name, value) != 0)) + break; + } + + break; + } + } + } + + // ------------------------------------------------------------------------ + + if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && (sockstat6_root.tcp6_inuse))) { + do_tcp_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv6" + , "sockstat6_tcp_sockets" + , NULL + , "tcp6" + , NULL + , "IPv6 TCP Sockets" + , "sockets" + , "proc" + , "net/sockstat6" + , 3599 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.tcp6_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udp6_inuse)) { + do_udp_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv6" + , "sockstat6_udp_sockets" + , NULL + , "udp6" + , NULL + , "IPv6 UDP Sockets" + , "sockets" + , "proc" + , "net/sockstat6" + , 3600 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udp6_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udplite6_inuse)) { + do_udplite_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv6" + , "sockstat6_udplite_sockets" + , NULL + , "udplite6" + , NULL + , "IPv6 UDPLITE Sockets" + , "sockets" + , "proc" + , "net/sockstat6" + , 3601 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udplite6_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.raw6_inuse)) { + do_raw_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv6" + , "sockstat6_raw_sockets" + , NULL + , "raw6" + , NULL + , "IPv6 RAW Sockets" + , "sockets" + , "proc" + , "net/sockstat6" + , 3700 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.raw6_inuse); + rrdset_done(st); + } + + // ------------------------------------------------------------------------ + + if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.frag6_inuse)) { + do_frag_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_inuse = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "ipv6" + , "sockstat6_frag_sockets" + , NULL + , "fragments6" + , NULL + , "IPv6 FRAG Sockets" + , "fragments" + , "proc" + , "net/sockstat6" + , 3010 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + else rrdset_next(st); + + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.frag6_inuse); + rrdset_done(st); + } + + return 0; +} diff --git a/src/proc_net_softnet_stat.c b/src/proc_net_softnet_stat.c index b03a43c5..f3c117e1 100644 --- a/src/proc_net_softnet_stat.c +++ b/src/proc_net_softnet_stat.c @@ -79,8 +79,20 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { st = rrdset_find_bytype_localhost("system", "softnet_stat"); if(unlikely(!st)) { - st = rrdset_create_localhost("system", "softnet_stat", NULL, "softnet_stat", "system.softnet_stat", "System softnet_stat" - , "events/s", 955, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "system" + , "softnet_stat" + , NULL + , "softnet_stat" + , "system.softnet_stat" + , "System softnet_stat" + , "events/s" + , "proc" + , "net/softnet_stat" + , 955 + , update_every + , RRDSET_TYPE_LINE + ); for(w = 0; w < allocated_columns ;w++) if(unlikely(softnet_column_name(w))) rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -103,8 +115,20 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { char title[100+1]; snprintfz(title, 100, "CPU%zu softnet_stat", l); - st = rrdset_create_localhost("cpu", id, NULL, "softnet_stat", "cpu.softnet_stat", title, "events/s", 4101 + l - , update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + "cpu" + , id + , NULL + , "softnet_stat" + , "cpu.softnet_stat" + , title + , "events/s" + , "proc" + , "net/softnet_stat" + , 4101 + l + , update_every + , RRDSET_TYPE_LINE + ); for(w = 0; w < allocated_columns ;w++) if(unlikely(softnet_column_name(w))) rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); diff --git a/src/proc_net_stat_conntrack.c b/src/proc_net_stat_conntrack.c index e04b80a3..363fbc19 100644 --- a/src/proc_net_stat_conntrack.c +++ b/src/proc_net_stat_conntrack.c @@ -122,136 +122,225 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { unsigned long long max; if(likely(!read_single_number_file(nf_conntrack_max_filename, &max))) - rrdvar_custom_host_variable_set(rrdvar_max, max); + rrdvar_custom_host_variable_set(localhost, rrdvar_max, max); } - RRDSET *st; - // -------------------------------------------------------------------- if(do_sockets) { - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL - , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections" - , "active connections", 3000, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM *rd_connections = NULL; - rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_CONNTRACK "_sockets" + , NULL + , RRD_TYPE_NET_STAT_CONNTRACK + , NULL + , "Connection Tracker Connections" + , "active connections" + , "proc" + , "net/stat/nf_conntrack" + , 3000 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_connections = rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); - rrddim_set(st, "connections", aentries); + rrddim_set_by_pointer(st, rd_connections, aentries); rrdset_done(st); } // -------------------------------------------------------------------- if(do_new) { - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new"); - if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL - , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections" - , "connections/s", 3001, update_every, RRDSET_TYPE_LINE); + static RRDSET *st = NULL; + static RRDDIM + *rd_new = NULL, + *rd_ignore = NULL, + *rd_invalid = NULL; - rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "ignore", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_CONNTRACK "_new" + , NULL + , RRD_TYPE_NET_STAT_CONNTRACK + , NULL + , "Connection Tracker New Connections" + , "connections/s" + , "proc" + , "net/stat/nf_conntrack" + , 3001 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_new = rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ignore = rrddim_add(st, "ignore", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_invalid = rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "new", anew); - rrddim_set(st, "ignore", aignore); - rrddim_set(st, "invalid", ainvalid); + rrddim_set_by_pointer(st, rd_new, anew); + rrddim_set_by_pointer(st, rd_ignore, aignore); + rrddim_set_by_pointer(st, rd_invalid, ainvalid); rrdset_done(st); } // -------------------------------------------------------------------- if(do_changes) { - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes"); + static RRDSET *st = NULL; + static RRDDIM + *rd_inserted = NULL, + *rd_deleted = NULL, + *rd_delete_list = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL - , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s" - , 3002, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_CONNTRACK "_changes" + , NULL + , RRD_TYPE_NET_STAT_CONNTRACK + , NULL + , "Connection Tracker Changes" + , "changes/s" + , "proc" + , "net/stat/nf_conntrack" + , 3002 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "inserted", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "delete_list", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_inserted = rrddim_add(st, "inserted", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_deleted = rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_delete_list = rrddim_add(st, "delete_list", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "inserted", ainsert); - rrddim_set(st, "deleted", adelete); - rrddim_set(st, "delete_list", adelete_list); + rrddim_set_by_pointer(st, rd_inserted, ainsert); + rrddim_set_by_pointer(st, rd_deleted, adelete); + rrddim_set_by_pointer(st, rd_delete_list, adelete_list); rrdset_done(st); } // -------------------------------------------------------------------- if(do_expect) { - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect"); + static RRDSET *st = NULL; + static RRDDIM *rd_created = NULL, + *rd_deleted = NULL, + *rd_new = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL - , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations" - , "expectations/s", 3003, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_CONNTRACK "_expect" + , NULL + , RRD_TYPE_NET_STAT_CONNTRACK + , NULL + , "Connection Tracker Expectations" + , "expectations/s" + , "proc" + , "net/stat/nf_conntrack" + , 3003 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "created", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_created = rrddim_add(st, "created", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_deleted = rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_new = rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "created", aexpect_create); - rrddim_set(st, "deleted", aexpect_delete); - rrddim_set(st, "new", aexpect_new); + rrddim_set_by_pointer(st, rd_created, aexpect_create); + rrddim_set_by_pointer(st, rd_deleted, aexpect_delete); + rrddim_set_by_pointer(st, rd_new, aexpect_new); rrdset_done(st); } // -------------------------------------------------------------------- if(do_search) { - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search"); + static RRDSET *st = NULL; + static RRDDIM *rd_searched = NULL, + *rd_restarted = NULL, + *rd_found = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL - , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches" - , "searches/s", 3010, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_CONNTRACK "_search" + , NULL + , RRD_TYPE_NET_STAT_CONNTRACK + , NULL + , "Connection Tracker Searches" + , "searches/s" + , "proc" + , "net/stat/nf_conntrack" + , 3010 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "searched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "restarted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "found", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_searched = rrddim_add(st, "searched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_restarted = rrddim_add(st, "restarted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_found = rrddim_add(st, "found", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "searched", asearched); - rrddim_set(st, "restarted", asearch_restart); - rrddim_set(st, "found", afound); + rrddim_set_by_pointer(st, rd_searched, asearched); + rrddim_set_by_pointer(st, rd_restarted, asearch_restart); + rrddim_set_by_pointer(st, rd_found, afound); rrdset_done(st); } // -------------------------------------------------------------------- if(do_errors) { - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors"); + static RRDSET *st = NULL; + static RRDDIM *rd_icmp_error = NULL, + *rd_insert_failed = NULL, + *rd_drop = NULL, + *rd_early_drop = NULL; + if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL - , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s" - , 3005, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_CONNTRACK "_errors" + , NULL + , RRD_TYPE_NET_STAT_CONNTRACK + , NULL + , "Connection Tracker Errors" + , "events/s" + , "proc" + , "net/stat/nf_conntrack" + , 3005 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "icmp_error", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "insert_failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "early_drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_icmp_error = rrddim_add(st, "icmp_error", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_insert_failed = rrddim_add(st, "insert_failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_drop = rrddim_add(st, "drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_early_drop = rrddim_add(st, "early_drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); - rrddim_set(st, "icmp_error", aicmp_error); - rrddim_set(st, "insert_failed", ainsert_failed); - rrddim_set(st, "drop", adrop); - rrddim_set(st, "early_drop", aearly_drop); + rrddim_set_by_pointer(st, rd_icmp_error, aicmp_error); + rrddim_set_by_pointer(st, rd_insert_failed, ainsert_failed); + rrddim_set_by_pointer(st, rd_drop, adrop); + rrddim_set_by_pointer(st, rd_early_drop, aearly_drop); rrdset_done(st); } diff --git a/src/proc_net_stat_synproxy.c b/src/proc_net_stat_synproxy.c index 5a1fc30e..0d6f6ee0 100644 --- a/src/proc_net_stat_synproxy.c +++ b/src/proc_net_stat_synproxy.c @@ -53,18 +53,27 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { unsigned long long events = entries + syn_received + cookie_invalid + cookie_valid + cookie_retrans + conn_reopened; - RRDSET *st; - // -------------------------------------------------------------------- if((do_entries == CONFIG_BOOLEAN_AUTO && events) || do_entries == CONFIG_BOOLEAN_YES) { do_entries = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries"); + static RRDSET *st = NULL; if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL - , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 3304 - , update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_SYNPROXY "_entries" + , NULL + , RRD_TYPE_NET_STAT_SYNPROXY + , NULL + , "SYNPROXY Entries Used" + , "entries" + , "proc" + , "net/stat/synproxy" + , 3304 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "entries", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } @@ -79,11 +88,22 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { if((do_syns == CONFIG_BOOLEAN_AUTO && events) || do_syns == CONFIG_BOOLEAN_YES) { do_syns = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received"); + static RRDSET *st = NULL; if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL - , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s" - , 3301, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_SYNPROXY "_syn_received" + , NULL + , RRD_TYPE_NET_STAT_SYNPROXY + , NULL + , "SYNPROXY SYN Packets received" + , "SYN/s" + , "proc" + , "net/stat/synproxy" + , 3301 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } @@ -98,11 +118,22 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { if((do_reopened == CONFIG_BOOLEAN_AUTO && events) || do_reopened == CONFIG_BOOLEAN_YES) { do_reopened = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened"); + static RRDSET *st = NULL; if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL - , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened" - , "connections/s", 3303, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened" + , NULL + , RRD_TYPE_NET_STAT_SYNPROXY + , NULL + , "SYNPROXY Connections Reopened" + , "connections/s" + , "proc" + , "net/stat/synproxy" + , 3303 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "reopened", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } @@ -117,11 +148,22 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { if((do_cookies == CONFIG_BOOLEAN_AUTO && events) || do_cookies == CONFIG_BOOLEAN_YES) { do_cookies = CONFIG_BOOLEAN_YES; - st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies"); + static RRDSET *st = NULL; if(unlikely(!st)) { - st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL - , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 3302 - , update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost( + RRD_TYPE_NET_STAT_NETFILTER + , RRD_TYPE_NET_STAT_SYNPROXY "_cookies" + , NULL + , RRD_TYPE_NET_STAT_SYNPROXY + , NULL + , "SYNPROXY TCP Cookies" + , "cookies/s" + , "proc" + , "net/stat/synproxy" + , 3302 + , update_every + , RRDSET_TYPE_LINE + ); rrddim_add(st, "valid", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); diff --git a/src/proc_softirqs.c b/src/proc_softirqs.c index 352407a4..a1b9947e 100644 --- a/src/proc_softirqs.c +++ b/src/proc_softirqs.c @@ -136,6 +136,8 @@ int do_proc_softirqs(int update_every, usec_t dt) { , NULL , "System softirqs" , "softirqs/s" + , "proc" + , "softirqs" , 950 , update_every , RRDSET_TYPE_STACKED @@ -212,6 +214,8 @@ int do_proc_softirqs(int update_every, usec_t dt) { , "cpu.softirqs" , title , "softirqs/s" + , "proc" + , "softirqs" , 3000 + c , update_every , RRDSET_TYPE_STACKED diff --git a/src/proc_spl_kstat_zfs.c b/src/proc_spl_kstat_zfs.c index dee7a6b3..9d489d8e 100644 --- a/src/proc_spl_kstat_zfs.c +++ b/src/proc_spl_kstat_zfs.c @@ -3,7 +3,7 @@ #define ZFS_PROC_ARCSTATS "/proc/spl/kstat/zfs/arcstats" -struct arcstats arcstats = { 0 }; +extern struct arcstats arcstats; int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt) { (void)dt; @@ -11,7 +11,7 @@ int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt) { static procfile *ff = NULL; static ARL_BASE *arl_base = NULL; - l2exist = -1; + arcstats.l2exist = -1; if(unlikely(!arl_base)) { arl_base = arl_create("arcstats", NULL, 60); @@ -135,19 +135,19 @@ int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt) { const char *key = procfile_lineword(ff, l, 0); const char *value = procfile_lineword(ff, l, 2); - if(unlikely(l2exist == -1)) { + if(unlikely(arcstats.l2exist == -1)) { if(key[0] == 'l' && key[1] == '2' && key[2] == '_') - l2exist = 1; + arcstats.l2exist = 1; } if(unlikely(arl_check(arl_base, key, value))) break; } - if(unlikely(l2exist == -1)) - l2exist = 0; + if(unlikely(arcstats.l2exist == -1)) + arcstats.l2exist = 0; - generate_charts_arcstats(update_every); - generate_charts_arc_summary(update_every); + generate_charts_arcstats("proc", update_every); + generate_charts_arc_summary("proc", update_every); return 0; } diff --git a/src/proc_stat.c b/src/proc_stat.c index 40bf5cfa..907b659d 100644 --- a/src/proc_stat.c +++ b/src/proc_stat.c @@ -287,6 +287,8 @@ int do_proc_stat(int update_every, usec_t dt) { , context , title , "percentage" + , "proc" + , "stat" , priority , update_every , RRDSET_TYPE_STACKED @@ -337,6 +339,8 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "CPU Interrupts" , "interrupts/s" + , "proc" + , "stat" , 900 , update_every , RRDSET_TYPE_LINE @@ -367,6 +371,8 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "CPU Context Switches" , "context switches/s" + , "proc" + , "stat" , 800 , update_every , RRDSET_TYPE_LINE @@ -406,6 +412,8 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "Started Processes" , "processes/s" + , "proc" + , "stat" , 700 , update_every , RRDSET_TYPE_LINE @@ -436,6 +444,8 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "System Processes" , "processes" + , "proc" + , "stat" , 600 , update_every , RRDSET_TYPE_LINE @@ -468,6 +478,8 @@ int do_proc_stat(int update_every, usec_t dt) { , "cpu.core_throttling" , "Core Thermal Throttling Events" , "events/s" + , "proc" + , "stat" , 5001 , update_every , RRDSET_TYPE_LINE @@ -496,6 +508,8 @@ int do_proc_stat(int update_every, usec_t dt) { , "cpu.package_throttling" , "Package Thermal Throttling Events" , "events/s" + , "proc" + , "stat" , 5002 , update_every , RRDSET_TYPE_LINE @@ -524,6 +538,8 @@ int do_proc_stat(int update_every, usec_t dt) { , "cpu.scaling_cur_freq" , "Per CPU Core, Current CPU Scaling Frequency" , "MHz" + , "proc" + , "stat" , 5003 , update_every , RRDSET_TYPE_LINE diff --git a/src/proc_sys_kernel_random_entropy_avail.c b/src/proc_sys_kernel_random_entropy_avail.c index 267ea271..ca4d7657 100644 --- a/src/proc_sys_kernel_random_entropy_avail.c +++ b/src/proc_sys_kernel_random_entropy_avail.c @@ -29,6 +29,8 @@ int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) { , NULL , "Available Entropy" , "entropy" + , "proc" + , "sys/kernel/random/entropy_avail" , 1000 , update_every , RRDSET_TYPE_LINE diff --git a/src/proc_uptime.c b/src/proc_uptime.c index fb05b5cb..8f4b9029 100644 --- a/src/proc_uptime.c +++ b/src/proc_uptime.c @@ -50,6 +50,8 @@ int do_proc_uptime(int update_every, usec_t dt) { , NULL , "System Uptime" , "seconds" + , "proc" + , "uptime" , 1000 , update_every , RRDSET_TYPE_LINE diff --git a/src/proc_vmstat.c b/src/proc_vmstat.c index 2382116f..72ca3818 100644 --- a/src/proc_vmstat.c +++ b/src/proc_vmstat.c @@ -102,6 +102,8 @@ int do_proc_vmstat(int update_every, usec_t dt) { , NULL , "Swap I/O" , "kilobytes/s" + , "proc" + , "vmstat" , 250 , update_every , RRDSET_TYPE_AREA @@ -126,13 +128,15 @@ int do_proc_vmstat(int update_every, usec_t dt) { if(unlikely(!st_io)) { st_io = rrdset_create_localhost( "system" - , "io" + , "pgpgio" , NULL , "disk" , NULL - , "Disk I/O" + , "Memory Paged from/to disk" , "kilobytes/s" - , 150 + , "proc" + , "vmstat" + , 151 , update_every , RRDSET_TYPE_AREA ); @@ -162,6 +166,8 @@ int do_proc_vmstat(int update_every, usec_t dt) { , NULL , "Memory Page Faults" , "page faults/s" + , "proc" + , "vmstat" , 500 , update_every , RRDSET_TYPE_LINE @@ -205,6 +211,8 @@ int do_proc_vmstat(int update_every, usec_t dt) { , NULL , "NUMA events" , "events/s" + , "proc" + , "vmstat" , 800 , update_every , RRDSET_TYPE_LINE diff --git a/src/registry.c b/src/registry.c index 76e3fa4d..9d382e86 100644 --- a/src/registry.c +++ b/src/registry.c @@ -323,11 +323,21 @@ void registry_statistics(void) { static RRDSET *sts = NULL, *stc = NULL, *stm = NULL; - if(!sts) sts = rrdset_find_localhost("netdata.registry_sessions"); - if(!sts) { - sts = rrdset_create_localhost("netdata", "registry_sessions", NULL, "registry", NULL - , "NetData Registry Sessions", "session", 131000, localhost->rrd_update_every - , RRDSET_TYPE_LINE); + if(unlikely(!sts)) { + sts = rrdset_create_localhost( + "netdata" + , "registry_sessions" + , NULL + , "registry" + , NULL + , "NetData Registry Sessions" + , "session" + , "registry" + , "stats" + , 131000 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); rrddim_add(sts, "sessions", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } @@ -338,10 +348,21 @@ void registry_statistics(void) { // ------------------------------------------------------------------------ - if(!stc) stc = rrdset_find_localhost("netdata.registry_entries"); - if(!stc) { - stc = rrdset_create_localhost("netdata", "registry_entries", NULL, "registry", NULL, "NetData Registry Entries" - , "entries", 131100, localhost->rrd_update_every, RRDSET_TYPE_LINE); + if(unlikely(!stc)) { + stc = rrdset_create_localhost( + "netdata" + , "registry_entries" + , NULL + , "registry" + , NULL + , "NetData Registry Entries" + , "entries" + , "registry" + , "stats" + , 131100 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); rrddim_add(stc, "persons", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stc, "machines", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -360,10 +381,21 @@ void registry_statistics(void) { // ------------------------------------------------------------------------ - if(!stm) stm = rrdset_find_localhost("netdata.registry_mem"); - if(!stm) { - stm = rrdset_create_localhost("netdata", "registry_mem", NULL, "registry", NULL, "NetData Registry Memory", "KB" - , 131300, localhost->rrd_update_every, RRDSET_TYPE_STACKED); + if(unlikely(!stm)) { + stm = rrdset_create_localhost( + "netdata" + , "registry_mem" + , NULL + , "registry" + , NULL + , "NetData Registry Memory" + , "KB" + , "registry" + , "stats" + , 131300 + , localhost->rrd_update_every + , RRDSET_TYPE_STACKED + ); rrddim_add(stm, "persons", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(stm, "machines", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); @@ -87,7 +87,7 @@ struct rrdfamily { size_t use_count; - avl_tree_lock variables_root_index; + avl_tree_lock rrdvar_root_index; }; typedef struct rrdfamily RRDFAMILY; @@ -266,9 +266,9 @@ struct rrdset { char *units; // units of measurement char *context; // the template of this data set - uint32_t hash_context; + uint32_t hash_context; // the hash of the chart's context - RRDSET_TYPE chart_type; + RRDSET_TYPE chart_type; // line, area, stacked int update_every; // every how many seconds is this updated? @@ -282,7 +282,7 @@ struct rrdset { int gap_when_lost_iterations_above; // after how many lost iterations a gap should be stored // netdata will interpolate values for gaps lower than this - long priority; + long priority; // the sorting priority of this chart // ------------------------------------------------------------------------ @@ -300,7 +300,11 @@ struct rrdset { time_t last_accessed_time; // the last time this RRDSET has been accessed time_t upstream_resync_time; // the timestamp up to which we should resync clock upstream - size_t unused[8]; + + char *plugin_name; // the name of the plugin that generated this + char *module_name; // the name of the plugin module that generated this + + size_t unused[6]; uint32_t hash; // a simple hash on the id, to speed up searching // we first compare hashes, and only if the hashes are equal we do string comparisons @@ -315,20 +319,20 @@ struct rrdset { total_number collected_total; // used internally to calculate percentages total_number last_collected_total; // used internally to calculate percentages - RRDFAMILY *rrdfamily; - struct rrdhost *rrdhost; + RRDFAMILY *rrdfamily; // pointer to RRDFAMILY this chart belongs to + struct rrdhost *rrdhost; // pointer to RRDHOST this chart belongs to struct rrdset *next; // linking of rrdsets // ------------------------------------------------------------------------ // local variables - calculated_number green; - calculated_number red; + calculated_number green; // green threshold for this chart + calculated_number red; // red threshold for this chart - avl_tree_lock variables_root_index; - RRDSETVAR *variables; - RRDCALC *alarms; + avl_tree_lock rrdvar_root_index; // RRDVAR index for this chart + RRDSETVAR *variables; // RRDSETVAR linked list for this chart (one RRDSETVAR, many RRDVARs) + RRDCALC *alarms; // RRDCALC linked list for this chart // ------------------------------------------------------------------------ // members for checking the data when loading from disk @@ -368,9 +372,9 @@ typedef struct rrdset RRDSET; // and may lead to missing information. typedef enum rrdhost_flags { - RRDHOST_ORPHAN = 1 << 0, // this host is orphan (not receiving data) - RRDHOST_DELETE_OBSOLETE_CHARTS = 1 << 1, // delete files of obsolete charts - RRDHOST_DELETE_ORPHAN_HOST = 1 << 2 // delete the entire host when orphan + RRDHOST_FLAG_ORPHAN = 1 << 0, // this host is orphan (not receiving data) + RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS = 1 << 1, // delete files of obsolete charts + RRDHOST_FLAG_DELETE_ORPHAN_HOST = 1 << 2 // delete the entire host when orphan } RRDHOST_FLAGS; #ifdef HAVE_C___ATOMIC @@ -410,6 +414,7 @@ struct rrdhost { const char *os; // the O/S type of the host const char *tags; // tags for this host + const char *timezone; // the timezone of the host uint32_t flags; // flags about this RRDHOST @@ -424,17 +429,26 @@ struct rrdhost { // ------------------------------------------------------------------------ // streaming of data to remote hosts - rrdpush - int rrdpush_enabled:1; // 1 when this host sends metrics to another netdata - char *rrdpush_destination; // where to send metrics to - char *rrdpush_api_key; // the api key at the receiving netdata - volatile int rrdpush_connected:1; // 1 when the sender is ready to push metrics - volatile int rrdpush_spawn:1; // 1 when the sender thread has been spawn - volatile int rrdpush_error_shown:1; // 1 when we have logged a communication error - int rrdpush_socket; // the fd of the socket to the remote host, or -1 - pthread_t rrdpush_thread; // the sender thread - netdata_mutex_t rrdpush_mutex; // exclusive access to rrdpush_buffer - int rrdpush_pipe[2]; // collector to sender thread communication - BUFFER *rrdpush_buffer; // collector fills it, sender sends them + int rrdpush_send_enabled:1; // 1 when this host sends metrics to another netdata + char *rrdpush_send_destination; // where to send metrics to + char *rrdpush_send_api_key; // the api key at the receiving netdata + + // the following are state information for the threading + // streaming metrics from this netdata to an upstream netdata + volatile int rrdpush_sender_spawn:1; // 1 when the sender thread has been spawn + pthread_t rrdpush_sender_thread; // the sender thread + + volatile int rrdpush_sender_connected:1; // 1 when the sender is ready to push metrics + int rrdpush_sender_socket; // the fd of the socket to the remote host, or -1 + + volatile int rrdpush_sender_error_shown:1; // 1 when we have logged a communication error + volatile int rrdpush_sender_join:1; // 1 when we have to join the sending thread + + // metrics may be collected asynchronously + // these synchronize all the threads willing the write to our sending buffer + netdata_mutex_t rrdpush_sender_buffer_mutex; // exclusive access to rrdpush_sender_buffer + int rrdpush_sender_pipe[2]; // collector to sender thread signaling + BUFFER *rrdpush_sender_buffer; // collector fills it, sender sends it // ------------------------------------------------------------------------ @@ -483,11 +497,14 @@ struct rrdhost { netdata_rwlock_t rrdhost_rwlock; // lock for this RRDHOST (protects rrdset_root linked list) + // ------------------------------------------------------------------------ + // indexes + avl_tree_lock rrdset_root_index; // the host's charts index (by id) avl_tree_lock rrdset_root_index_name; // the host's charts index (by name) avl_tree_lock rrdfamily_root_index; // the host's chart families index - avl_tree_lock variables_root_index; // the host's chart variables index + avl_tree_lock rrdvar_root_index; // the host's chart variables index struct rrdhost *next; }; @@ -532,6 +549,7 @@ extern RRDHOST *rrdhost_find_or_create( , const char *registry_hostname , const char *guid , const char *os + , const char *timezone , const char *tags , int update_every , long history @@ -560,8 +578,8 @@ extern void __rrd_check_wrlock(const char *file, const char *function, const uns #else #define rrdhost_check_rdlock(host) (void)0 #define rrdhost_check_wrlock(host) (void)0 -#define rrdset_check_rdlock(host) (void)0 -#define rrdset_check_wrlock(host) (void)0 +#define rrdset_check_rdlock(st) (void)0 +#define rrdset_check_wrlock(st) (void)0 #define rrd_check_rdlock() (void)0 #define rrd_check_wrlock() (void)0 #endif @@ -569,7 +587,7 @@ extern void __rrd_check_wrlock(const char *file, const char *function, const uns // ---------------------------------------------------------------------------- // RRDSET functions -extern void rrdset_set_name(RRDSET *st, const char *name); +extern int rrdset_set_name(RRDSET *st, const char *name); extern RRDSET *rrdset_create_custom(RRDHOST *host , const char *type @@ -579,26 +597,30 @@ extern RRDSET *rrdset_create_custom(RRDHOST *host , const char *context , const char *title , const char *units + , const char *plugin + , const char *module , long priority , int update_every , RRDSET_TYPE chart_type , RRD_MEMORY_MODE memory_mode , long history_entries); -#define rrdset_create(host, type, id, name, family, context, title, units, priority, update_every, chart_type) \ - rrdset_create_custom(host, type, id, name, family, context, title, units, priority, update_every, chart_type, (host)->rrd_memory_mode, (host)->rrd_history_entries) +#define rrdset_create(host, type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type) \ + rrdset_create_custom(host, type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type, (host)->rrd_memory_mode, (host)->rrd_history_entries) -#define rrdset_create_localhost(type, id, name, family, context, title, units, priority, update_every, chart_type) \ - rrdset_create(localhost, type, id, name, family, context, title, units, priority, update_every, chart_type) +#define rrdset_create_localhost(type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type) \ + rrdset_create(localhost, type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type) extern void rrdhost_free_all(void); extern void rrdhost_save_all(void); extern void rrdhost_cleanup_all(void); -extern void rrdhost_cleanup_orphan_hosts(RRDHOST *protected); +extern void rrdhost_cleanup_orphan_hosts_nolock(RRDHOST *protected); extern void rrdhost_free(RRDHOST *host); -extern void rrdhost_save(RRDHOST *host); -extern void rrdhost_delete(RRDHOST *host); +extern void rrdhost_save_charts(RRDHOST *host); +extern void rrdhost_delete_charts(RRDHOST *host); + +extern int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected, time_t now); extern void rrdset_update_heterogeneous_flag(RRDSET *st); @@ -678,7 +700,6 @@ extern collected_number rrddim_set(RRDSET *st, const char *id, collected_number extern long align_entries_to_pagesize(RRD_MEMORY_MODE mode, long entries); - // ---------------------------------------------------------------------------- // RRD internal functions diff --git a/src/rrd2json.c b/src/rrd2json.c index 84d90448..00d7a552 100644 --- a/src/rrd2json.c +++ b/src/rrd2json.c @@ -13,6 +13,8 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions "\t\t\t\"context\": \"%s\",\n" "\t\t\t\"title\": \"%s (%s)\",\n" "\t\t\t\"priority\": %ld,\n" + "\t\t\t\"plugin\": \"%s\",\n" + "\t\t\t\"module\": \"%s\",\n" "\t\t\t\"enabled\": %s,\n" "\t\t\t\"units\": \"%s\",\n" "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n" @@ -29,6 +31,8 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions , st->context , st->title, st->name , st->priority + , st->plugin_name?st->plugin_name:"" + , st->module_name?st->module_name:"" , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?"true":"false" , st->units , st->name @@ -48,13 +52,14 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions memory += rd->memsize; - buffer_sprintf(wb, - "%s" - "\t\t\t\t\"%s\": { \"name\": \"%s\" }" - , dimensions?",\n":"" - , rd->id - , rd->name - ); + buffer_sprintf( + wb + , "%s" + "\t\t\t\t\"%s\": { \"name\": \"%s\" }" + , dimensions ? ",\n" : "" + , rd->id + , rd->name + ); dimensions++; } @@ -67,8 +72,33 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions buffer_strcat(wb, ",\n\t\t\t\"red\": "); buffer_rrd_value(wb, st->red); + buffer_strcat(wb, ",\n\t\t\t\"alarms\": {\n"); + size_t alarms = 0; + RRDCALC *rc; + for(rc = st->alarms; rc ; rc = rc->rrdset_next) { + + buffer_sprintf( + wb + , "%s" + "\t\t\t\t\"%s\": {\n" + "\t\t\t\t\t\"id\": %u,\n" + "\t\t\t\t\t\"status\": \"%s\",\n" + "\t\t\t\t\t\"units\": \"%s\",\n" + "\t\t\t\t\t\"update_every\": %d\n" + "\t\t\t\t}" + , (alarms) ? ",\n" : "" + , rc->name + , rc->id + , rrdcalc_status2string(rc->status) + , rc->units + , rc->update_every + ); + + alarms++; + } + buffer_sprintf(wb, - "\n\t\t}" + "\n\t\t\t}\n\t\t}" ); rrdset_unlock(st); @@ -92,6 +122,7 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) { "\t\"hostname\": \"%s\"" ",\n\t\"version\": \"%s\"" ",\n\t\"os\": \"%s\"" + ",\n\t\"timezone\": \"%s\"" ",\n\t\"update_every\": %d" ",\n\t\"history\": %ld" ",\n\t\"custom_info\": \"%s\"" @@ -99,6 +130,7 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) { , host->hostname , program_version , host->os + , host->timezone , host->rrd_update_every , host->rrd_history_entries , custom_dashboard_info_js_filename @@ -126,7 +158,8 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) { } rrdhost_unlock(host); - buffer_sprintf(wb, "\n\t}" + buffer_sprintf(wb + , "\n\t}" ",\n\t\"charts_count\": %zu" ",\n\t\"dimensions_count\": %zu" ",\n\t\"alarms_count\": %zu" @@ -142,24 +175,31 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) { if(unlikely(rrd_hosts_available > 1)) { rrd_rdlock(); + + size_t found = 0; RRDHOST *h; rrdhost_foreach_read(h) { - buffer_sprintf(wb, - "%s\n\t\t{" - "\n\t\t\t\"hostname\": \"%s\"" - "\n\t\t}" - , (h != localhost) ? "," : "" - , h->hostname - ); + if(!rrdhost_should_be_removed(h, host, now)) { + buffer_sprintf(wb + , "%s\n\t\t{" + "\n\t\t\t\"hostname\": \"%s\"" + "\n\t\t}" + , (found > 0) ? "," : "" + , h->hostname + ); + + found++; + } } + rrd_unlock(); } else { - buffer_sprintf(wb, - "\n\t\t{" - "\n\t\t\t\"hostname\": \"%s\"" - "\n\t\t}" - , host->hostname + buffer_sprintf(wb + , "\n\t\t{" + "\n\t\t\t\"hostname\": \"%s\"" + "\n\t\t}" + , host->hostname ); } diff --git a/src/rrd2json.h b/src/rrd2json.h index a3b9c950..7212c0b3 100644 --- a/src/rrd2json.h +++ b/src/rrd2json.h @@ -61,6 +61,7 @@ #define RRDR_OPTION_LABEL_QUOTES 0x00000400 // in CSV output, wrap header labels in double quotes #define RRDR_OPTION_PERCENTAGE 0x00000800 // give values as percentage of total #define RRDR_OPTION_NOT_ALIGNED 0x00001000 // do not align charts for persistant timeframes +#define RRDR_OPTION_DISPLAY_ABS 0x00002000 // for badges, display the absolute value, but calculate colors with sign extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb); extern void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb); diff --git a/src/rrdcalc.c b/src/rrdcalc.c index bb90a4c6..4177733b 100644 --- a/src/rrdcalc.c +++ b/src/rrdcalc.c @@ -4,7 +4,7 @@ // ---------------------------------------------------------------------------- // RRDCALC management -inline const char *rrdcalc_status2string(int status) { +inline const char *rrdcalc_status2string(RRDCALC_STATUS status) { switch(status) { case RRDCALC_STATUS_REMOVED: return "REMOVED"; @@ -62,15 +62,15 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) { st->red = rc->red; } - rc->local = rrdvar_create_and_index("local", &st->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); - rc->family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); char fullname[RRDVAR_MAX_LENGTH + 1]; snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rc->name); - rc->hostid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->hostid = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name); - rc->hostname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->hostname = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); if(!rc->units) rc->units = strdupz(st->units); @@ -173,16 +173,16 @@ inline void rrdsetcalc_unlink(RRDCALC *rc) { rc->rrdset_prev = rc->rrdset_next = NULL; - rrdvar_free(st->rrdhost, &st->variables_root_index, rc->local); + rrdvar_free(st->rrdhost, &st->rrdvar_root_index, rc->local); rc->local = NULL; - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rc->family); + rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rc->family); rc->family = NULL; - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rc->hostid); + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rc->hostid); rc->hostid = NULL; - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rc->hostname); + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rc->hostname); rc->hostname = NULL; rc->rrdset = NULL; @@ -375,8 +375,27 @@ inline RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *c return rc; } -void rrdcalc_free(RRDHOST *host, RRDCALC *rc) { - if(!rc) return; +void rrdcalc_free(RRDCALC *rc) { + if(unlikely(!rc)) return; + + expression_free(rc->calculation); + expression_free(rc->warning); + expression_free(rc->critical); + + freez(rc->name); + freez(rc->chart); + freez(rc->family); + freez(rc->dimensions); + freez(rc->exec); + freez(rc->recipient); + freez(rc->source); + freez(rc->units); + freez(rc->info); + freez(rc); +} + +void rrdcalc_unlink_and_free(RRDHOST *host, RRDCALC *rc) { + if(unlikely(!rc)) return; debug(D_HEALTH, "Health removing alarm '%s.%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); @@ -398,18 +417,5 @@ void rrdcalc_free(RRDHOST *host, RRDCALC *rc) { error("Cannot unlink alarm '%s.%s' from host '%s': not found", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); } - expression_free(rc->calculation); - expression_free(rc->warning); - expression_free(rc->critical); - - freez(rc->name); - freez(rc->chart); - freez(rc->family); - freez(rc->dimensions); - freez(rc->exec); - freez(rc->recipient); - freez(rc->source); - freez(rc->units); - freez(rc->info); - freez(rc); + rrdcalc_free(rc); } diff --git a/src/rrdcalctemplate.c b/src/rrdcalctemplate.c index b5d2c7d6..4ec24cd2 100644 --- a/src/rrdcalctemplate.c +++ b/src/rrdcalctemplate.c @@ -22,25 +22,9 @@ void rrdcalctemplate_link_matching(RRDSET *st) { } } -inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) { +inline void rrdcalctemplate_free(RRDCALCTEMPLATE *rt) { if(unlikely(!rt)) return; - debug(D_HEALTH, "Health removing template '%s' of host '%s'", rt->name, host->hostname); - - if(host->templates == rt) { - host->templates = rt->next; - } - else { - RRDCALCTEMPLATE *t; - for (t = host->templates; t && t->next != rt; t = t->next ) ; - if(t) { - t->next = rt->next; - rt->next = NULL; - } - else - error("Cannot find RRDCALCTEMPLATE '%s' linked in host '%s'", rt->name, host->hostname); - } - expression_free(rt->calculation); expression_free(rt->warning); expression_free(rt->critical); @@ -59,4 +43,26 @@ inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) { freez(rt); } +inline void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt) { + if(unlikely(!rt)) return; + + debug(D_HEALTH, "Health removing template '%s' of host '%s'", rt->name, host->hostname); + + if(host->templates == rt) { + host->templates = rt->next; + } + else { + RRDCALCTEMPLATE *t; + for (t = host->templates; t && t->next != rt; t = t->next ) ; + if(t) { + t->next = rt->next; + rt->next = NULL; + } + else + error("Cannot find RRDCALCTEMPLATE '%s' linked in host '%s'", rt->name, host->hostname); + } + + rrdcalctemplate_free(rt); +} + diff --git a/src/rrddim.c b/src/rrddim.c index 8df54839..6477a1cb 100644 --- a/src/rrddim.c +++ b/src/rrddim.c @@ -155,7 +155,7 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte reset = 1; } else if(dt_usec(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * USEC_PER_SEC)) { - error("File %s is too old (last collected %llu seconds ago, but the database is %ld seconds). Clearing it.", fullfilename, dt_usec(&now, &rd->last_collected_time) / USEC_PER_SEC, rd->entries * rd->update_every); + info("File %s is too old (last collected %llu seconds ago, but the database is %ld seconds). Clearing it.", fullfilename, dt_usec(&now, &rd->last_collected_time) / USEC_PER_SEC, rd->entries * rd->update_every); memset(rd, 0, size); reset = 1; } @@ -262,9 +262,9 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte } if(st->rrdhost->health_enabled) { - rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->last_stored_value, 0); - rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->last_collected_value, 0); - rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, 0); + rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->last_stored_value, RRDVAR_OPTION_DEFAULT); + rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->last_collected_value, RRDVAR_OPTION_DEFAULT); + rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT); } rrdset_unlock(st); diff --git a/src/rrddimvar.c b/src/rrddimvar.c index f6eb6d8e..0d20815b 100644 --- a/src/rrddimvar.c +++ b/src/rrddimvar.c @@ -13,38 +13,38 @@ static inline void rrddimvar_free_variables(RRDDIMVAR *rs) { // CHART VARIABLES FOR THIS DIMENSION - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_id); + rrdvar_free(st->rrdhost, &st->rrdvar_root_index, rs->var_local_id); rs->var_local_id = NULL; - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_name); + rrdvar_free(st->rrdhost, &st->rrdvar_root_index, rs->var_local_name); rs->var_local_name = NULL; // FAMILY VARIABLES FOR THIS DIMENSION - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_id); + rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family_id); rs->var_family_id = NULL; - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); + rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family_name); rs->var_family_name = NULL; - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextid); + rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family_contextid); rs->var_family_contextid = NULL; - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextname); + rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family_contextname); rs->var_family_contextname = NULL; // HOST VARIABLES FOR THIS DIMENSION - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidid); + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host_chartidid); rs->var_host_chartidid = NULL; - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidname); + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host_chartidname); rs->var_host_chartidname = NULL; - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnameid); + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host_chartnameid); rs->var_host_chartnameid = NULL; - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnamename); + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host_chartnamename); rs->var_host_chartnamename = NULL; // KEYS @@ -115,8 +115,8 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { // - $id // - $name - rs->var_local_id = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_id, rs->type, rs->value); - rs->var_local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_name, rs->type, rs->value); + rs->var_local_id = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_id, rs->type, rs->value); + rs->var_local_name = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_name, rs->type, rs->value); // FAMILY VARIABLES FOR THIS DIMENSION // ----------------------------------- @@ -127,10 +127,10 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { // - $chart-context.id // - $chart-context.name - rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_id, rs->type, rs->value); - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_name, rs->type, rs->value); - rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextid, rs->type, rs->value); - rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextname, rs->type, rs->value); + rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_id, rs->type, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_name, rs->type, rs->value); + rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextid, rs->type, rs->value); + rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextname, rs->type, rs->value); // HOST VARIABLES FOR THIS DIMENSION // ----------------------------------- @@ -141,13 +141,13 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { // - $chart-name.id // - $chart-name.name - rs->var_host_chartidid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidid, rs->type, rs->value); - rs->var_host_chartidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidname, rs->type, rs->value); - rs->var_host_chartnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnameid, rs->type, rs->value); - rs->var_host_chartnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnamename, rs->type, rs->value); + rs->var_host_chartidid = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullidid, rs->type, rs->value); + rs->var_host_chartidname = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullidname, rs->type, rs->value); + rs->var_host_chartnameid = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullnameid, rs->type, rs->value); + rs->var_host_chartnamename = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullnamename, rs->type, rs->value); } -RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) { +RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, const char *suffix, void *value, RRDVAR_OPTIONS options) { RRDSET *st = rd->rrdset; debug(D_VARIABLES, "RRDDIMSET create for chart id '%s' name '%s', dimension id '%s', name '%s%s%s'", st->id, st->name, rd->id, (prefix)?prefix:"", rd->name, (suffix)?suffix:""); diff --git a/src/rrdfamily.c b/src/rrdfamily.c index fc203e91..905ae480 100644 --- a/src/rrdfamily.c +++ b/src/rrdfamily.c @@ -30,11 +30,11 @@ RRDFAMILY *rrdfamily_create(RRDHOST *host, const char *id) { rc->hash_family = simple_hash(rc->family); // initialize the variables index - avl_init_lock(&rc->variables_root_index, rrdvar_compare); + avl_init_lock(&rc->rrdvar_root_index, rrdvar_compare); RRDFAMILY *ret = rrdfamily_index_add(host, rc); if(ret != rc) - fatal("RRDFAMILY: INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE"); + error("RRDFAMILY: INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE"); } rc->use_count++; @@ -46,13 +46,14 @@ void rrdfamily_free(RRDHOST *host, RRDFAMILY *rc) { if(!rc->use_count) { RRDFAMILY *ret = rrdfamily_index_del(host, rc); if(ret != rc) - fatal("RRDFAMILY: INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE"); - - if(rc->variables_root_index.avl_tree.root != NULL) - fatal("RRDFAMILY: INTERNAL ERROR: Variables index of RRDFAMILY '%s' that is freed, is not empty.", rc->family); - - freez((void *)rc->family); - freez(rc); + error("RRDFAMILY: INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE"); + else { + debug(D_RRD_CALLS, "RRDFAMILY: Cleaning up remaining family variables for host '%s', family '%s'", host->hostname, rc->family); + rrdvar_free_remaining_variables(host, &rc->rrdvar_root_index); + + freez((void *) rc->family); + freez(rc); + } } } diff --git a/src/rrdhost.c b/src/rrdhost.c index ff8aa561..831cc46c 100644 --- a/src/rrdhost.c +++ b/src/rrdhost.c @@ -86,6 +86,15 @@ static inline void rrdhost_init_os(RRDHOST *host, const char *os) { freez(old); } +static inline void rrdhost_init_timezone(RRDHOST *host, const char *timezone) { + if(host->timezone && timezone && !strcmp(host->timezone, timezone)) + return; + + void *old = (void *)host->timezone; + host->timezone = strdupz((timezone && *timezone)?timezone:"unknown"); + freez(old); +} + static inline void rrdhost_init_machine_guid(RRDHOST *host, const char *machine_guid) { strncpy(host->machine_guid, machine_guid, GUID_LEN); host->machine_guid[GUID_LEN] = '\0'; @@ -100,6 +109,7 @@ RRDHOST *rrdhost_create(const char *hostname, const char *registry_hostname, const char *guid, const char *os, + const char *timezone, const char *tags, int update_every, long entries, @@ -120,33 +130,34 @@ RRDHOST *rrdhost_create(const char *hostname, host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries); host->rrd_memory_mode = memory_mode; host->health_enabled = (memory_mode == RRD_MEMORY_MODE_NONE)? 0 : health_enabled; - host->rrdpush_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key); - host->rrdpush_destination = (host->rrdpush_enabled)?strdupz(rrdpush_destination):NULL; - host->rrdpush_api_key = (host->rrdpush_enabled)?strdupz(rrdpush_api_key):NULL; + host->rrdpush_send_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key); + host->rrdpush_send_destination = (host->rrdpush_send_enabled)?strdupz(rrdpush_destination):NULL; + host->rrdpush_send_api_key = (host->rrdpush_send_enabled)?strdupz(rrdpush_api_key):NULL; - host->rrdpush_pipe[0] = -1; - host->rrdpush_pipe[1] = -1; - host->rrdpush_socket = -1; + host->rrdpush_sender_pipe[0] = -1; + host->rrdpush_sender_pipe[1] = -1; + host->rrdpush_sender_socket = -1; - netdata_mutex_init(&host->rrdpush_mutex); + netdata_mutex_init(&host->rrdpush_sender_buffer_mutex); netdata_rwlock_init(&host->rrdhost_rwlock); rrdhost_init_hostname(host, hostname); rrdhost_init_machine_guid(host, guid); rrdhost_init_os(host, os); + rrdhost_init_timezone(host, timezone); rrdhost_init_tags(host, tags); host->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname); avl_init_lock(&(host->rrdset_root_index), rrdset_compare); avl_init_lock(&(host->rrdset_root_index_name), rrdset_compare_name); avl_init_lock(&(host->rrdfamily_root_index), rrdfamily_compare); - avl_init_lock(&(host->variables_root_index), rrdvar_compare); + avl_init_lock(&(host->rrdvar_root_index), rrdvar_compare); if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete obsolete charts files", 1)) - rrdhost_flag_set(host, RRDHOST_DELETE_OBSOLETE_CHARTS); + rrdhost_flag_set(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS); if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete orphan hosts files", 1) && !is_localhost) - rrdhost_flag_set(host, RRDHOST_DELETE_ORPHAN_HOST); + rrdhost_flag_set(host, RRDHOST_FLAG_DELETE_ORPHAN_HOST); // ------------------------------------------------------------------------ @@ -251,7 +262,8 @@ RRDHOST *rrdhost_create(const char *hostname, } else { info("Host '%s' (at registry as '%s') with guid '%s' initialized" - ", os %s" + ", os '%s'" + ", timezone '%s'" ", tags '%s'" ", update every %d" ", memory mode %s" @@ -268,13 +280,14 @@ RRDHOST *rrdhost_create(const char *hostname, , host->registry_hostname , host->machine_guid , host->os + , host->timezone , (host->tags)?host->tags:"" , host->rrd_update_every , rrd_memory_mode_name(host->rrd_memory_mode) , host->rrd_history_entries - , host->rrdpush_enabled?"enabled":"disabled" - , host->rrdpush_destination?host->rrdpush_destination:"" - , host->rrdpush_api_key?host->rrdpush_api_key:"" + , host->rrdpush_send_enabled?"enabled":"disabled" + , host->rrdpush_send_destination?host->rrdpush_send_destination:"" + , host->rrdpush_send_api_key?host->rrdpush_send_api_key:"" , host->health_enabled?"enabled":"disabled" , host->cache_dir , host->varlib_dir @@ -294,6 +307,7 @@ RRDHOST *rrdhost_find_or_create( , const char *registry_hostname , const char *guid , const char *os + , const char *timezone , const char *tags , int update_every , long history @@ -313,6 +327,7 @@ RRDHOST *rrdhost_find_or_create( , registry_hostname , guid , os + , timezone , tags , update_every , history @@ -346,16 +361,18 @@ RRDHOST *rrdhost_find_or_create( // update host tags rrdhost_init_tags(host, tags); } - rrd_unlock(); - rrdhost_cleanup_orphan_hosts(host); + rrdhost_cleanup_orphan_hosts_nolock(host); + + rrd_unlock(); return host; } -static inline int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected, time_t now) { +inline int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected, time_t now) { if(host != protected && host != localhost + && rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN) && !host->connected_senders && host->senders_disconnected_time && host->senders_disconnected_time + rrdhost_free_orphan_time < now) @@ -364,11 +381,9 @@ static inline int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected, t return 0; } -void rrdhost_cleanup_orphan_hosts(RRDHOST *protected) { +void rrdhost_cleanup_orphan_hosts_nolock(RRDHOST *protected) { time_t now = now_realtime_sec(); - rrd_wrlock(); - RRDHOST *host; restart_after_removal: @@ -376,17 +391,15 @@ restart_after_removal: if(rrdhost_should_be_removed(host, protected, now)) { info("Host '%s' with machine guid '%s' is obsolete - cleaning up.", host->hostname, host->machine_guid); - if(rrdset_flag_check(host, RRDHOST_DELETE_ORPHAN_HOST) && rrdset_flag_check(host, RRDHOST_ORPHAN)) - rrdhost_delete(host); + if(rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_ORPHAN_HOST)) + rrdhost_delete_charts(host); else - rrdhost_save(host); + rrdhost_save_charts(host); rrdhost_free(host); goto restart_after_removal; } } - - rrd_unlock(); } // ---------------------------------------------------------------------------- @@ -406,6 +419,7 @@ void rrd_init(char *hostname) { , registry_get_this_machine_hostname() , registry_get_this_machine_guid() , os_type + , netdata_configured_timezone , config_get(CONFIG_SECTION_BACKEND, "host tags", "") , default_rrd_update_every , default_rrd_history_entries @@ -473,12 +487,19 @@ void rrdhost_free(RRDHOST *host) { // ------------------------------------------------------------------------ // release its children resources - while(host->rrdset_root) rrdset_free(host->rrdset_root); + while(host->rrdset_root) + rrdset_free(host->rrdset_root); - while(host->alarms) rrdcalc_free(host, host->alarms); - while(host->templates) rrdcalctemplate_free(host, host->templates); - health_alarm_log_free(host); + while(host->alarms) + rrdcalc_unlink_and_free(host, host->alarms); + while(host->templates) + rrdcalctemplate_unlink_and_free(host, host->templates); + + debug(D_RRD_CALLS, "RRDHOST: Cleaning up remaining host variables for host '%s'", host->hostname); + rrdvar_free_remaining_variables(host, &host->rrdvar_root_index); + + health_alarm_log_free(host); // ------------------------------------------------------------------------ // remove it from the indexes @@ -508,10 +529,11 @@ void rrdhost_free(RRDHOST *host) { freez((void *)host->tags); freez((void *)host->os); + freez((void *)host->timezone); freez(host->cache_dir); freez(host->varlib_dir); - freez(host->rrdpush_api_key); - freez(host->rrdpush_destination); + freez(host->rrdpush_send_api_key); + freez(host->rrdpush_send_destination); freez(host->health_default_exec); freez(host->health_default_recipient); freez(host->health_log_filename); @@ -534,7 +556,7 @@ void rrdhost_free_all(void) { // ---------------------------------------------------------------------------- // RRDHOST - save host files -void rrdhost_save(RRDHOST *host) { +void rrdhost_save_charts(RRDHOST *host) { if(!host) return; info("Saving/Closing database of host '%s'...", host->hostname); @@ -557,7 +579,7 @@ void rrdhost_save(RRDHOST *host) { // ---------------------------------------------------------------------------- // RRDHOST - delete host files -void rrdhost_delete(RRDHOST *host) { +void rrdhost_delete_charts(RRDHOST *host) { if(!host) return; info("Deleting database of host '%s'...", host->hostname); @@ -582,12 +604,13 @@ void rrdhost_delete(RRDHOST *host) { // ---------------------------------------------------------------------------- // RRDHOST - cleanup host files -void rrdhost_cleanup(RRDHOST *host) { +void rrdhost_cleanup_charts(RRDHOST *host) { if(!host) return; info("Cleaning up database of host '%s'...", host->hostname); RRDSET *st; + uint32_t rrdhost_delete_obsolete_charts = rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS); // we get a write lock // to ensure only one thread is saving the database @@ -596,7 +619,7 @@ void rrdhost_cleanup(RRDHOST *host) { rrdset_foreach_write(st, host) { rrdset_rdlock(st); - if(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE) && rrdhost_flag_check(host, RRDHOST_DELETE_OBSOLETE_CHARTS)) + if(rrdhost_delete_obsolete_charts && rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)) rrdset_delete(st); else rrdset_save(st); @@ -618,7 +641,7 @@ void rrdhost_save_all(void) { RRDHOST *host; rrdhost_foreach_read(host) - rrdhost_save(host); + rrdhost_save_charts(host); rrd_unlock(); } @@ -633,10 +656,10 @@ void rrdhost_cleanup_all(void) { RRDHOST *host; rrdhost_foreach_read(host) { - if(host != localhost && rrdhost_flag_check(host, RRDHOST_DELETE_OBSOLETE_CHARTS) && !host->connected_senders) - rrdhost_delete(host); + if(host != localhost && rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS) && !host->connected_senders) + rrdhost_delete_charts(host); else - rrdhost_cleanup(host); + rrdhost_cleanup_charts(host); } rrd_unlock(); @@ -651,6 +674,8 @@ void rrdhost_cleanup_obsolete_charts(RRDHOST *host) { RRDSET *st; + uint32_t rrdhost_delete_obsolete_charts = rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS); + restart_after_removal: rrdset_foreach_write(st, host) { if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE) @@ -661,7 +686,7 @@ restart_after_removal: rrdset_rdlock(st); - if(rrdhost_flag_check(host, RRDHOST_DELETE_OBSOLETE_CHARTS)) + if(rrdhost_delete_obsolete_charts) rrdset_delete(st); else rrdset_save(st); diff --git a/src/rrdpush.c b/src/rrdpush.c index c1d052fd..2d10c3ca 100644 --- a/src/rrdpush.c +++ b/src/rrdpush.c @@ -59,72 +59,100 @@ int rrdpush_init() { // this is for the first iterations of each chart unsigned int remote_clock_resync_iterations = 60; -#define rrdpush_lock(host) netdata_mutex_lock(&((host)->rrdpush_mutex)) -#define rrdpush_unlock(host) netdata_mutex_unlock(&((host)->rrdpush_mutex)) +#define rrdpush_buffer_lock(host) netdata_mutex_lock(&((host)->rrdpush_sender_buffer_mutex)) +#define rrdpush_buffer_unlock(host) netdata_mutex_unlock(&((host)->rrdpush_sender_buffer_mutex)) // checks if the current chart definition has been sent static inline int need_to_send_chart_definition(RRDSET *st) { + rrdset_check_rdlock(st); + if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_EXPOSED_UPSTREAM)))) return 1; RRDDIM *rd; rrddim_foreach_read(rd, st) - if(!rd->exposed) + if(unlikely(!rd->exposed)) return 1; return 0; } // sends the current chart definition -static inline void send_chart_definition(RRDSET *st) { +static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) { + RRDHOST *host = st->rrdhost; + rrdset_flag_set(st, RRDSET_FLAG_EXPOSED_UPSTREAM); - buffer_sprintf(st->rrdhost->rrdpush_buffer, "CHART \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %ld %d \"%s %s %s\"\n" - , st->id - , st->name - , st->title - , st->units - , st->family - , st->context - , rrdset_type_name(st->chart_type) - , st->priority - , st->update_every - , rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)?"obsolete":"" - , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?"detail":"" - , rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST)?"store_first":"" + // send the chart + buffer_sprintf( + host->rrdpush_sender_buffer + , "CHART \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %ld %d \"%s %s %s\" \"%s\" \"%s\"\n" + , st->id + , st->name + , st->title + , st->units + , st->family + , st->context + , rrdset_type_name(st->chart_type) + , st->priority + , st->update_every + , rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)?"obsolete":"" + , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?"detail":"" + , rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST)?"store_first":"" + , (st->plugin_name)?st->plugin_name:"" + , (st->module_name)?st->module_name:"" ); + // send the dimensions RRDDIM *rd; rrddim_foreach_read(rd, st) { - buffer_sprintf(st->rrdhost->rrdpush_buffer, "DIMENSION \"%s\" \"%s\" \"%s\" " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " \"%s %s\"\n" - , rd->id - , rd->name - , rrd_algorithm_name(rd->algorithm) - , rd->multiplier - , rd->divisor - , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?"hidden":"" - , rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)?"noreset":"" + buffer_sprintf( + host->rrdpush_sender_buffer + , "DIMENSION \"%s\" \"%s\" \"%s\" " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " \"%s %s\"\n" + , rd->id + , rd->name + , rrd_algorithm_name(rd->algorithm) + , rd->multiplier + , rd->divisor + , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?"hidden":"" + , rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)?"noreset":"" ); rd->exposed = 1; } + // send the chart local custom variables + RRDSETVAR *rs; + for(rs = st->variables; rs ;rs = rs->next) { + if(unlikely(rs->options && RRDVAR_OPTION_ALLOCATED)) { + calculated_number *value = (calculated_number *) rs->value; + + buffer_sprintf( + host->rrdpush_sender_buffer + , "VARIABLE CHART %s = " CALCULATED_NUMBER_FORMAT "\n" + , rs->variable + , *value + ); + } + } + st->upstream_resync_time = st->last_collected_time.tv_sec + (remote_clock_resync_iterations * st->update_every); } // sends the current chart dimensions -static inline void send_chart_metrics(RRDSET *st) { - buffer_sprintf(st->rrdhost->rrdpush_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->upstream_resync_time > st->last_collected_time.tv_sec)?st->usec_since_last_update:0); +static inline void rrdpush_send_chart_metrics_nolock(RRDSET *st) { + buffer_sprintf(st->rrdhost->rrdpush_sender_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->upstream_resync_time > st->last_collected_time.tv_sec)?st->usec_since_last_update:0); RRDDIM *rd; rrddim_foreach_read(rd, st) { if(rd->updated && rd->exposed) - buffer_sprintf(st->rrdhost->rrdpush_buffer, "SET \"%s\" = " COLLECTED_NUMBER_FORMAT "\n" - , rd->id - , rd->collected_value + buffer_sprintf(st->rrdhost->rrdpush_sender_buffer + , "SET \"%s\" = " COLLECTED_NUMBER_FORMAT "\n" + , rd->id + , rd->collected_value ); } - buffer_strcat(st->rrdhost->rrdpush_buffer, "END\n"); + buffer_strcat(st->rrdhost->rrdpush_sender_buffer, "END\n"); } static void rrdpush_sender_thread_spawn(RRDHOST *host); @@ -133,9 +161,9 @@ void rrdset_push_chart_definition(RRDSET *st) { RRDHOST *host = st->rrdhost; rrdset_rdlock(st); - rrdpush_lock(host); - send_chart_definition(st); - rrdpush_unlock(host); + rrdpush_buffer_lock(host); + rrdpush_send_chart_definition_nolock(st); + rrdpush_buffer_unlock(host); rrdset_unlock(st); } @@ -145,40 +173,81 @@ void rrdset_done_push(RRDSET *st) { if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_ENABLED))) return; - rrdpush_lock(host); + rrdpush_buffer_lock(host); - if(unlikely(host->rrdpush_enabled && !host->rrdpush_spawn)) + if(unlikely(host->rrdpush_send_enabled && !host->rrdpush_sender_spawn)) rrdpush_sender_thread_spawn(host); - if(unlikely(!host->rrdpush_buffer || !host->rrdpush_connected)) { - if(unlikely(!host->rrdpush_error_shown)) + if(unlikely(!host->rrdpush_sender_buffer || !host->rrdpush_sender_connected)) { + if(unlikely(!host->rrdpush_sender_error_shown)) error("STREAM %s [send]: not ready - discarding collected metrics.", host->hostname); - host->rrdpush_error_shown = 1; + host->rrdpush_sender_error_shown = 1; - rrdpush_unlock(host); + rrdpush_buffer_unlock(host); return; } - else if(unlikely(host->rrdpush_error_shown)) { - info("STREAM %s [send]: ready - sending metrics...", host->hostname); - host->rrdpush_error_shown = 0; + else if(unlikely(host->rrdpush_sender_error_shown)) { + info("STREAM %s [send]: sending metrics...", host->hostname); + host->rrdpush_sender_error_shown = 0; } if(need_to_send_chart_definition(st)) - send_chart_definition(st); + rrdpush_send_chart_definition_nolock(st); - send_chart_metrics(st); + rrdpush_send_chart_metrics_nolock(st); // signal the sender there are more data - if(write(host->rrdpush_pipe[PIPE_WRITE], " ", 1) == -1) + if(host->rrdpush_sender_pipe[PIPE_WRITE] != -1 && write(host->rrdpush_sender_pipe[PIPE_WRITE], " ", 1) == -1) error("STREAM %s [send]: cannot write to internal pipe", host->hostname); - rrdpush_unlock(host); + rrdpush_buffer_unlock(host); } // ---------------------------------------------------------------------------- // rrdpush sender thread +static inline void rrdpush_sender_add_host_variable_to_buffer_nolock(RRDHOST *host, RRDVAR *rv) { + calculated_number *value = (calculated_number *)rv->value; + + buffer_sprintf( + host->rrdpush_sender_buffer + , "VARIABLE HOST %s = " CALCULATED_NUMBER_FORMAT "\n" + , rv->name + , *value + ); + + debug(D_STREAM, "RRDVAR pushed HOST VARIABLE %s = " CALCULATED_NUMBER_FORMAT, rv->name, *value); +} + +void rrdpush_sender_send_this_host_variable_now(RRDHOST *host, RRDVAR *rv) { + if(host->rrdpush_send_enabled && host->rrdpush_sender_spawn && host->rrdpush_sender_connected) { + rrdpush_buffer_lock(host); + rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv); + rrdpush_buffer_unlock(host); + } +} + +static int rrdpush_sender_thread_custom_host_variables_callback(void *rrdvar_ptr, void *host_ptr) { + RRDVAR *rv = (RRDVAR *)rrdvar_ptr; + RRDHOST *host = (RRDHOST *)host_ptr; + + if(unlikely(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED)) { + rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv); + + // return 1, so that the traversal will return the number of variables sent + return 1; + } + + // returning a negative number will break the traversal + return 0; +} + +static void rrdpush_sender_thread_send_custom_host_variables(RRDHOST *host) { + int ret = rrdvar_callback_for_all_host_variables(host, rrdpush_sender_thread_custom_host_variables_callback, host); + debug(D_STREAM, "RRDVAR sent %d VARIABLES", ret); +} + // resets all the chart, so that their definitions // will be resent to the central netdata static void rrdpush_sender_thread_reset_all_charts(RRDHOST *host) { @@ -186,6 +255,7 @@ static void rrdpush_sender_thread_reset_all_charts(RRDHOST *host) { RRDSET *st; rrdset_foreach_read(st, host) { + rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM); st->upstream_resync_time = 0; @@ -202,68 +272,198 @@ static void rrdpush_sender_thread_reset_all_charts(RRDHOST *host) { } static inline void rrdpush_sender_thread_data_flush(RRDHOST *host) { - rrdpush_lock(host); + rrdpush_buffer_lock(host); - if(buffer_strlen(host->rrdpush_buffer)) - error("STREAM %s [send]: discarding %zu bytes of metrics already in the buffer.", host->hostname, buffer_strlen(host->rrdpush_buffer)); + if(buffer_strlen(host->rrdpush_sender_buffer)) + error("STREAM %s [send]: discarding %zu bytes of metrics already in the buffer.", host->hostname, buffer_strlen(host->rrdpush_sender_buffer)); - buffer_flush(host->rrdpush_buffer); + buffer_flush(host->rrdpush_sender_buffer); rrdpush_sender_thread_reset_all_charts(host); + rrdpush_sender_thread_send_custom_host_variables(host); - rrdpush_unlock(host); + rrdpush_buffer_unlock(host); } -static void rrdpush_sender_thread_cleanup_locked_all(RRDHOST *host) { - host->rrdpush_connected = 0; +void rrdpush_sender_thread_stop(RRDHOST *host) { + rrdpush_buffer_lock(host); + rrdhost_wrlock(host); + + pthread_t thr = 0; - if(host->rrdpush_socket != -1) { - close(host->rrdpush_socket); - host->rrdpush_socket = -1; + if(host->rrdpush_sender_spawn) { + info("STREAM %s [send]: signaling sending thread to stop...", host->hostname); + + // signal the thread that we want to join it + host->rrdpush_sender_join = 1; + + // copy the thread id, so that we will be waiting for the right one + // even if a new one has been spawn + thr = host->rrdpush_sender_thread; + + // signal it to cancel + int ret = pthread_cancel(host->rrdpush_sender_thread); + if(ret != 0) + error("STREAM %s [send]: pthread_cancel() returned error.", host->hostname); } - // close the pipe - if(host->rrdpush_pipe[PIPE_READ] != -1) { - close(host->rrdpush_pipe[PIPE_READ]); - host->rrdpush_pipe[PIPE_READ] = -1; + rrdhost_unlock(host); + rrdpush_buffer_unlock(host); + + if(thr != 0) { + info("STREAM %s [send]: waiting for the sending thread to stop...", host->hostname); + + void *result; + int ret = pthread_join(thr, &result); + if(ret != 0) + error("STREAM %s [send]: pthread_join() returned error.", host->hostname); + + info("STREAM %s [send]: sending thread has exited.", host->hostname); + } +} + +static inline void rrdpush_sender_thread_close_socket(RRDHOST *host) { + host->rrdpush_sender_connected = 0; + + if(host->rrdpush_sender_socket != -1) { + close(host->rrdpush_sender_socket); + host->rrdpush_sender_socket = -1; + } +} + +static int rrdpush_sender_thread_connect_to_master(RRDHOST *host, int default_port, int timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size) { + struct timeval tv = { + .tv_sec = timeout, + .tv_usec = 0 + }; + + // make sure the socket is closed + rrdpush_sender_thread_close_socket(host); + + debug(D_STREAM, "STREAM: Attempting to connect..."); + info("STREAM %s [send to %s]: connecting...", host->hostname, host->rrdpush_send_destination); + + host->rrdpush_sender_socket = connect_to_one_of( + host->rrdpush_send_destination + , default_port + , &tv + , reconnects_counter + , connected_to + , connected_to_size + ); + + if(unlikely(host->rrdpush_sender_socket == -1)) { + error("STREAM %s [send to %s]: failed to connect", host->hostname, host->rrdpush_send_destination); + return 0; + } + + info("STREAM %s [send to %s]: initializing communication...", host->hostname, connected_to); + + #define HTTP_HEADER_SIZE 8192 + char http[HTTP_HEADER_SIZE + 1]; + snprintfz(http, HTTP_HEADER_SIZE, + "STREAM key=%s&hostname=%s®istry_hostname=%s&machine_guid=%s&update_every=%d&os=%s&timezone=%s&tags=%s HTTP/1.1\r\n" + "User-Agent: netdata-push-service/%s\r\n" + "Accept: */*\r\n\r\n" + , host->rrdpush_send_api_key + , host->hostname + , host->registry_hostname + , host->machine_guid + , default_rrd_update_every + , host->os + , host->timezone + , (host->tags)?host->tags:"" + , program_version + ); + + if(send_timeout(host->rrdpush_sender_socket, http, strlen(http), 0, timeout) == -1) { + error("STREAM %s [send to %s]: failed to send HTTP header to remote netdata.", host->hostname, connected_to); + rrdpush_sender_thread_close_socket(host); + return 0; } - if(host->rrdpush_pipe[PIPE_WRITE] != -1) { - close(host->rrdpush_pipe[PIPE_WRITE]); - host->rrdpush_pipe[PIPE_WRITE] = -1; + info("STREAM %s [send to %s]: waiting response from remote netdata...", host->hostname, connected_to); + + if(recv_timeout(host->rrdpush_sender_socket, http, HTTP_HEADER_SIZE, 0, timeout) == -1) { + error("STREAM %s [send to %s]: remote netdata does not respond.", host->hostname, connected_to); + rrdpush_sender_thread_close_socket(host); + return 0; + } + + if(strncmp(http, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT)) != 0) { + error("STREAM %s [send to %s]: server is not replying properly (is it a netdata?).", host->hostname, connected_to); + rrdpush_sender_thread_close_socket(host); + return 0; } - buffer_free(host->rrdpush_buffer); - host->rrdpush_buffer = NULL; + info("STREAM %s [send to %s]: established communication - ready to send metrics...", host->hostname, connected_to); - host->rrdpush_spawn = 0; + if(sock_setnonblock(host->rrdpush_sender_socket) < 0) + error("STREAM %s [send to %s]: cannot set non-blocking mode for socket.", host->hostname, connected_to); + + if(sock_enlarge_out(host->rrdpush_sender_socket) < 0) + error("STREAM %s [send to %s]: cannot enlarge the socket buffer.", host->hostname, connected_to); + + debug(D_STREAM, "STREAM: Connected on fd %d...", host->rrdpush_sender_socket); + + return 1; } -void rrdpush_sender_thread_stop(RRDHOST *host) { - rrdpush_lock(host); +static void rrdpush_sender_thread_cleanup_callback(void *ptr) { + RRDHOST *host = (RRDHOST *)ptr; + + rrdpush_buffer_lock(host); rrdhost_wrlock(host); - if(host->rrdpush_spawn) { - info("STREAM %s [send]: stopping sending thread...", host->hostname); - pthread_cancel(host->rrdpush_thread); - rrdpush_sender_thread_cleanup_locked_all(host); + info("STREAM %s [send]: sending thread cleans up...", host->hostname); + + rrdpush_sender_thread_close_socket(host); + + // close the pipe + if(host->rrdpush_sender_pipe[PIPE_READ] != -1) { + close(host->rrdpush_sender_pipe[PIPE_READ]); + host->rrdpush_sender_pipe[PIPE_READ] = -1; + } + + if(host->rrdpush_sender_pipe[PIPE_WRITE] != -1) { + close(host->rrdpush_sender_pipe[PIPE_WRITE]); + host->rrdpush_sender_pipe[PIPE_WRITE] = -1; } + buffer_free(host->rrdpush_sender_buffer); + host->rrdpush_sender_buffer = NULL; + + if(!host->rrdpush_sender_join) { + info("STREAM %s [send]: sending thread detaches itself.", host->hostname); + if(pthread_detach(pthread_self())) + error("STREAM %s [send]: pthread_detach() failed.", host->hostname); + } + + host->rrdpush_sender_spawn = 0; + + info("STREAM %s [send]: sending thread now exits.", host->hostname); + rrdhost_unlock(host); - rrdpush_unlock(host); + rrdpush_buffer_unlock(host); } void *rrdpush_sender_thread(void *ptr) { RRDHOST *host = (RRDHOST *)ptr; - info("STREAM %s [send]: thread created (task id %d)", host->hostname, gettid()); + if(!host->rrdpush_send_enabled || !host->rrdpush_send_destination || !*host->rrdpush_send_destination || !host->rrdpush_send_api_key || !*host->rrdpush_send_api_key) { + error("STREAM %s [send]: thread created (task id %d), but host has streaming disabled.", host->hostname, gettid()); + pthread_exit(NULL); + return NULL; + } - if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) - error("STREAM %s [send]: cannot set pthread cancel type to DEFERRED.", host->hostname); + info("STREAM %s [send]: thread created (task id %d)", host->hostname, gettid()); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("STREAM %s [send]: cannot set pthread cancel state to ENABLE.", host->hostname); + if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) + error("STREAM %s [send]: cannot set pthread cancel type to DEFERRED.", host->hostname); + int timeout = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "timeout seconds", 60); int default_port = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "default port", 19999); size_t max_size = (size_t)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "buffer size bytes", 1024 * 1024); @@ -271,24 +471,17 @@ void *rrdpush_sender_thread(void *ptr) { remote_clock_resync_iterations = (unsigned int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "initial clock resync iterations", remote_clock_resync_iterations); char connected_to[CONNECTED_TO_SIZE + 1] = ""; - if(!host->rrdpush_enabled || !host->rrdpush_destination || !*host->rrdpush_destination || !host->rrdpush_api_key || !*host->rrdpush_api_key) - goto cleanup; - // initialize rrdpush globals - host->rrdpush_buffer = buffer_create(1); - host->rrdpush_connected = 0; - if(pipe(host->rrdpush_pipe) == -1) fatal("STREAM %s [send]: cannot create required pipe.", host->hostname); + host->rrdpush_sender_buffer = buffer_create(1); + host->rrdpush_sender_connected = 0; + if(pipe(host->rrdpush_sender_pipe) == -1) fatal("STREAM %s [send]: cannot create required pipe.", host->hostname); // initialize local variables size_t begin = 0; size_t reconnects_counter = 0; size_t sent_bytes = 0; - size_t sent_connection = 0; + size_t sent_bytes_on_this_connection = 0; - struct timeval tv = { - .tv_sec = timeout, - .tv_usec = 0 - }; time_t last_sent_t = 0; struct pollfd fds[2], *ifd, *ofd; @@ -297,260 +490,206 @@ void *rrdpush_sender_thread(void *ptr) { ifd = &fds[0]; ofd = &fds[1]; - for(; host->rrdpush_enabled && !netdata_exit ;) { - debug(D_STREAM, "STREAM: Checking if we need to timeout the connection..."); - if(host->rrdpush_socket != -1 && now_monotonic_sec() - last_sent_t > timeout) { - error("STREAM %s [send to %s]: could not send metrics for %d seconds - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, timeout, sent_connection); - close(host->rrdpush_socket); - host->rrdpush_socket = -1; - } + size_t not_connected_loops = 0; - if(unlikely(host->rrdpush_socket == -1)) { - debug(D_STREAM, "STREAM: Attempting to connect..."); + pthread_cleanup_push(rrdpush_sender_thread_cleanup_callback, host); - // stop appending data into rrdpush_buffer - // they will be lost, so there is no point to do it - host->rrdpush_connected = 0; + for(; host->rrdpush_send_enabled && !netdata_exit ;) { + // check for outstanding cancellation requests + pthread_testcancel(); - info("STREAM %s [send to %s]: connecting...", host->hostname, host->rrdpush_destination); - host->rrdpush_socket = connect_to_one_of(host->rrdpush_destination, default_port, &tv, &reconnects_counter, connected_to, CONNECTED_TO_SIZE); + // if we don't have socket open, lets wait a bit + if(unlikely(host->rrdpush_sender_socket == -1)) { + if(not_connected_loops == 0 && sent_bytes_on_this_connection > 0) { + // fast re-connection on first disconnect + sleep_usec(USEC_PER_MS * 500); // milliseconds + } + else { + // slow re-connection on repeating errors + sleep_usec(USEC_PER_SEC * reconnect_delay); // seconds + } - if(unlikely(host->rrdpush_socket == -1)) { - error("STREAM %s [send to %s]: failed to connect", host->hostname, host->rrdpush_destination); - sleep(reconnect_delay); - continue; - } + if(rrdpush_sender_thread_connect_to_master(host, default_port, timeout, &reconnects_counter, connected_to, CONNECTED_TO_SIZE)) { + last_sent_t = now_monotonic_sec(); - info("STREAM %s [send to %s]: initializing communication...", host->hostname, connected_to); + // reset the buffer, to properly send charts and metrics + rrdpush_sender_thread_data_flush(host); - #define HTTP_HEADER_SIZE 8192 - char http[HTTP_HEADER_SIZE + 1]; - snprintfz(http, HTTP_HEADER_SIZE, - "STREAM key=%s&hostname=%s®istry_hostname=%s&machine_guid=%s&update_every=%d&os=%s&tags=%s HTTP/1.1\r\n" - "User-Agent: netdata-push-service/%s\r\n" - "Accept: */*\r\n\r\n" - , host->rrdpush_api_key - , host->hostname - , host->registry_hostname - , host->machine_guid - , default_rrd_update_every - , host->os - , (host->tags)?host->tags:"" - , program_version - ); + // make sure the next reconnection will be immediate + not_connected_loops = 0; - if(send_timeout(host->rrdpush_socket, http, strlen(http), 0, timeout) == -1) { - close(host->rrdpush_socket); - host->rrdpush_socket = -1; - error("STREAM %s [send to %s]: failed to send http header to netdata", host->hostname, connected_to); - sleep(reconnect_delay); - continue; - } + // reset the bytes we have sent for this session + sent_bytes_on_this_connection = 0; - info("STREAM %s [send to %s]: waiting response from remote netdata...", host->hostname, connected_to); + // let the data collection threads know we are ready + host->rrdpush_sender_connected = 1; + } + else { + // increase the failed connections counter + not_connected_loops++; - if(recv_timeout(host->rrdpush_socket, http, HTTP_HEADER_SIZE, 0, timeout) == -1) { - close(host->rrdpush_socket); - host->rrdpush_socket = -1; - error("STREAM %s [send to %s]: failed to initialize communication", host->hostname, connected_to); - sleep(reconnect_delay); - continue; - } + // reset the number of bytes sent + sent_bytes_on_this_connection = 0; + } - if(strncmp(http, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT))) { - close(host->rrdpush_socket); - host->rrdpush_socket = -1; - error("STREAM %s [send to %s]: server is not replying properly.", host->hostname, connected_to); - sleep(reconnect_delay); + // loop through continue; } - - info("STREAM %s [send to %s]: established communication - sending metrics...", host->hostname, connected_to); - last_sent_t = now_monotonic_sec(); - - if(sock_setnonblock(host->rrdpush_socket) < 0) - error("STREAM %s [send to %s]: cannot set non-blocking mode for socket.", host->hostname, connected_to); - - if(sock_enlarge_out(host->rrdpush_socket) < 0) - error("STREAM %s [send to %s]: cannot enlarge the socket buffer.", host->hostname, connected_to); - - rrdpush_sender_thread_data_flush(host); - sent_connection = 0; - - // allow appending data into rrdpush_buffer - host->rrdpush_connected = 1; - - debug(D_STREAM, "STREAM: Connected on fd %d...", host->rrdpush_socket); - } - - ifd->fd = host->rrdpush_pipe[PIPE_READ]; - ifd->events = POLLIN; - ifd->revents = 0; - - ofd->fd = host->rrdpush_socket; - ofd->revents = 0; - if(ofd->fd != -1 && begin < buffer_strlen(host->rrdpush_buffer)) { - debug(D_STREAM, "STREAM: Requesting data output on streaming socket %d...", ofd->fd); - ofd->events = POLLOUT; - fdmax = 2; - } - else { - debug(D_STREAM, "STREAM: Not requesting data output on streaming socket %d (nothing to send now)...", ofd->fd); - ofd->events = 0; - fdmax = 1; - } - - debug(D_STREAM, "STREAM: Waiting for poll() events (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_buffer)); - if(netdata_exit) break; - int retval = poll(fds, fdmax, 1000); - if(netdata_exit) break; - - if(unlikely(retval == -1)) { - debug(D_STREAM, "STREAM: poll() failed (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_buffer)); - - if(errno == EAGAIN || errno == EINTR) { - debug(D_STREAM, "STREAM: poll() failed with EAGAIN or EINTR..."); - continue; + else if(unlikely(now_monotonic_sec() - last_sent_t > timeout)) { + error("STREAM %s [send to %s]: could not send metrics for %d seconds - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, timeout, sent_bytes_on_this_connection); + rrdpush_sender_thread_close_socket(host); } - error("STREAM %s [send to %s]: failed to poll().", host->hostname, connected_to); - close(host->rrdpush_socket); - host->rrdpush_socket = -1; - break; - } - else if(likely(retval)) { - if (ifd->revents & POLLIN || ifd->revents & POLLPRI) { - debug(D_STREAM, "STREAM: Data added to send buffer (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_buffer)); + ifd->fd = host->rrdpush_sender_pipe[PIPE_READ]; + ifd->events = POLLIN; + ifd->revents = 0; - char buffer[1000 + 1]; - if (read(host->rrdpush_pipe[PIPE_READ], buffer, 1000) == -1) - error("STREAM %s [send to %s]: cannot read from internal pipe.", host->hostname, connected_to); + ofd->fd = host->rrdpush_sender_socket; + ofd->revents = 0; + if(ofd->fd != -1 && begin < buffer_strlen(host->rrdpush_sender_buffer)) { + debug(D_STREAM, "STREAM: Requesting data output on streaming socket %d...", ofd->fd); + ofd->events = POLLOUT; + fdmax = 2; + } + else { + debug(D_STREAM, "STREAM: Not requesting data output on streaming socket %d (nothing to send now)...", ofd->fd); + ofd->events = 0; + fdmax = 1; } - if (ofd->revents & POLLOUT) { - if (begin < buffer_strlen(host->rrdpush_buffer)) { - debug(D_STREAM, "STREAM: Sending data (current buffer length %zu bytes, begin = %zu)...", buffer_strlen(host->rrdpush_buffer), begin); + debug(D_STREAM, "STREAM: Waiting for poll() events (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer)); + if(unlikely(netdata_exit)) break; + int retval = poll(fds, fdmax, 1000); + if(unlikely(netdata_exit)) break; - // BEGIN RRDPUSH LOCKED SESSION + if(unlikely(retval == -1)) { + debug(D_STREAM, "STREAM: poll() failed (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer)); - // during this session, data collectors - // will not be able to append data to our buffer - // but the socket is in non-blocking mode - // so, we will not block at send() + if(errno == EAGAIN || errno == EINTR) { + debug(D_STREAM, "STREAM: poll() failed with EAGAIN or EINTR..."); + } + else { + error("STREAM %s [send to %s]: failed to poll(). Closing socket.", host->hostname, connected_to); + rrdpush_sender_thread_close_socket(host); + } - if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0) - error("STREAM %s [send]: cannot set pthread cancel state to DISABLE.", host->hostname); + continue; + } + else if(likely(retval)) { + if (ifd->revents & POLLIN || ifd->revents & POLLPRI) { + debug(D_STREAM, "STREAM: Data added to send buffer (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer)); - debug(D_STREAM, "STREAM: Getting exclusive lock on host..."); - rrdpush_lock(host); + char buffer[1000 + 1]; + if (read(host->rrdpush_sender_pipe[PIPE_READ], buffer, 1000) == -1) + error("STREAM %s [send to %s]: cannot read from internal pipe.", host->hostname, connected_to); + } - debug(D_STREAM, "STREAM: Sending data, starting from %zu, size %zu...", begin, buffer_strlen(host->rrdpush_buffer)); - ssize_t ret = send(host->rrdpush_socket, &host->rrdpush_buffer->buffer[begin], buffer_strlen(host->rrdpush_buffer) - begin, MSG_DONTWAIT); - if (unlikely(ret == -1)) { - if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) { - debug(D_STREAM, "STREAM: Send failed - closing socket..."); - error("STREAM %s [send to %s]: failed to send metrics - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_connection); - close(host->rrdpush_socket); - host->rrdpush_socket = -1; - } - else { - debug(D_STREAM, "STREAM: Send failed - will retry..."); + if (ofd->revents & POLLOUT) { + if (begin < buffer_strlen(host->rrdpush_sender_buffer)) { + debug(D_STREAM, "STREAM: Sending data (current buffer length %zu bytes, begin = %zu)...", buffer_strlen(host->rrdpush_sender_buffer), begin); + + // BEGIN RRDPUSH LOCKED SESSION + + // during this session, data collectors + // will not be able to append data to our buffer + // but the socket is in non-blocking mode + // so, we will not block at send() + + if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0) + error("STREAM %s [send]: cannot set pthread cancel state to DISABLE.", host->hostname); + + debug(D_STREAM, "STREAM: Getting exclusive lock on host..."); + rrdpush_buffer_lock(host); + + debug(D_STREAM, "STREAM: Sending data, starting from %zu, size %zu...", begin, buffer_strlen(host->rrdpush_sender_buffer)); + ssize_t ret = send(host->rrdpush_sender_socket, &host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin, MSG_DONTWAIT); + if (unlikely(ret == -1)) { + if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) { + debug(D_STREAM, "STREAM: Send failed - closing socket..."); + error("STREAM %s [send to %s]: failed to send metrics - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_bytes_on_this_connection); + rrdpush_sender_thread_close_socket(host); + } + else { + debug(D_STREAM, "STREAM: Send failed - will retry..."); + } } - } - else if (likely(ret > 0)) { - // DEBUG - dump the scring to see it - //char c = host->rrdpush_buffer->buffer[begin + ret]; - //host->rrdpush_buffer->buffer[begin + ret] = '\0'; - //debug(D_STREAM, "STREAM: sent from %zu to %zd:\n%s\n", begin, ret, &host->rrdpush_buffer->buffer[begin]); - //host->rrdpush_buffer->buffer[begin + ret] = c; - - sent_connection += ret; - sent_bytes += ret; - begin += ret; - - if (begin == buffer_strlen(host->rrdpush_buffer)) { - // we send it all - - debug(D_STREAM, "STREAM: Sent %zd bytes (the whole buffer)...", ret); - buffer_flush(host->rrdpush_buffer); - begin = 0; + else if (likely(ret > 0)) { + // DEBUG - dump the string to see it + //char c = host->rrdpush_sender_buffer->buffer[begin + ret]; + //host->rrdpush_sender_buffer->buffer[begin + ret] = '\0'; + //debug(D_STREAM, "STREAM: sent from %zu to %zd:\n%s\n", begin, ret, &host->rrdpush_sender_buffer->buffer[begin]); + //host->rrdpush_sender_buffer->buffer[begin + ret] = c; + + sent_bytes_on_this_connection += ret; + sent_bytes += ret; + begin += ret; + + if (begin == buffer_strlen(host->rrdpush_sender_buffer)) { + // we send it all + + debug(D_STREAM, "STREAM: Sent %zd bytes (the whole buffer)...", ret); + buffer_flush(host->rrdpush_sender_buffer); + begin = 0; + } + else { + debug(D_STREAM, "STREAM: Sent %zd bytes (part of the data buffer)...", ret); + } + + last_sent_t = now_monotonic_sec(); } else { - debug(D_STREAM, "STREAM: Sent %zd bytes (part of the data buffer)...", ret); + debug(D_STREAM, "STREAM: send() returned %zd - closing the socket...", ret); + error("STREAM %s [send to %s]: failed to send metrics (send() returned %zd) - closing connection - we have sent %zu bytes on this connection.", + host->hostname, connected_to, ret, sent_bytes_on_this_connection); + rrdpush_sender_thread_close_socket(host); } - last_sent_t = now_monotonic_sec(); + debug(D_STREAM, "STREAM: Releasing exclusive lock on host..."); + rrdpush_buffer_unlock(host); + + if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) + error("STREAM %s [send]: cannot set pthread cancel state to ENABLE.", host->hostname); + + // END RRDPUSH LOCKED SESSION } else { - debug(D_STREAM, "STREAM: send() returned %zd - closing the socket...", ret); - error("STREAM %s [send to %s]: failed to send metrics (send() returned %zd) - closing connection - we have sent %zu bytes on this connection.", - host->hostname, connected_to, ret, sent_connection); - close(host->rrdpush_socket); - host->rrdpush_socket = -1; + debug(D_STREAM, "STREAM: we have sent the entire buffer, but we received POLLOUT..."); } - - debug(D_STREAM, "STREAM: Releasing exclusive lock on host..."); - rrdpush_unlock(host); - - if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) - error("STREAM %s [send]: cannot set pthread cancel state to ENABLE.", host->hostname); - - // END RRDPUSH LOCKED SESSION - } - else { - debug(D_STREAM, "STREAM: we have sent the entire buffer, but we received POLLOUT..."); } - } - if(unlikely(ofd->revents & POLLERR)) { - debug(D_STREAM, "STREAM: Send failed (POLLERR) - closing socket..."); - error("STREAM %s [send to %s]: connection reports errors (POLLERR), closing it - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_connection); - close(host->rrdpush_socket); - host->rrdpush_socket = -1; - } - else if(unlikely(ofd->revents & POLLHUP)) { - debug(D_STREAM, "STREAM: Send failed (POLLHUP) - closing socket..."); - error("STREAM %s [send to %s]: connection closed by remote end (POLLHUP) - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_connection); - close(host->rrdpush_socket); - host->rrdpush_socket = -1; + if(host->rrdpush_sender_socket != -1) { + char *error = NULL; + + if (unlikely(ofd->revents & POLLERR)) + error = "socket reports errors (POLLERR)"; + + else if (unlikely(ofd->revents & POLLHUP)) + error = "connection closed by remote end (POLLHUP)"; + + else if (unlikely(ofd->revents & POLLNVAL)) + error = "connection is invalid (POLLNVAL)"; + + if(unlikely(error)) { + debug(D_STREAM, "STREAM: %s - closing socket...", error); + error("STREAM %s [send to %s]: %s - reopening socket - we have sent %zu bytes on this connection.", host->hostname, connected_to, error, sent_bytes_on_this_connection); + rrdpush_sender_thread_close_socket(host); + } + } } - else if(unlikely(ofd->revents & POLLNVAL)) { - debug(D_STREAM, "STREAM: Send failed (POLLNVAL) - closing socket..."); - error("STREAM %s [send to %s]: connection is invalid (POLLNVAL), closing it - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_connection); - close(host->rrdpush_socket); - host->rrdpush_socket = -1; + else { + debug(D_STREAM, "STREAM: poll() timed out."); } - } - else { - debug(D_STREAM, "STREAM: poll() timed out."); - } - // protection from overflow - if(buffer_strlen(host->rrdpush_buffer) > max_size) { - debug(D_STREAM, "STREAM: Buffer is too big (%zu bytes), bigger than the max (%zu) - flushing it...", buffer_strlen(host->rrdpush_buffer), max_size); - errno = 0; - error("STREAM %s [send to %s]: too many data pending - buffer is %zu bytes long, %zu unsent - we have sent %zu bytes in total, %zu on this connection. Closing connection to flush the data.", host->hostname, connected_to, host->rrdpush_buffer->len, host->rrdpush_buffer->len - begin, sent_bytes, sent_connection); - if(host->rrdpush_socket != -1) { - close(host->rrdpush_socket); - host->rrdpush_socket = -1; + // protection from overflow + if(buffer_strlen(host->rrdpush_sender_buffer) > max_size) { + debug(D_STREAM, "STREAM: Buffer is too big (%zu bytes), bigger than the max (%zu) - flushing it...", buffer_strlen(host->rrdpush_sender_buffer), max_size); + errno = 0; + error("STREAM %s [send to %s]: too many data pending - buffer is %zu bytes long, %zu unsent - we have sent %zu bytes in total, %zu on this connection. Closing connection to flush the data.", host->hostname, connected_to, host->rrdpush_sender_buffer->len, host->rrdpush_sender_buffer->len - begin, sent_bytes, sent_bytes_on_this_connection); + rrdpush_sender_thread_close_socket(host); } } - } - -cleanup: - debug(D_WEB_CLIENT, "STREAM %s [send]: sending thread exits.", host->hostname); - - if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0) - error("STREAM %s [send]: cannot set pthread cancel state to DISABLE.", host->hostname); - - rrdpush_lock(host); - rrdhost_wrlock(host); - rrdpush_sender_thread_cleanup_locked_all(host); - rrdhost_unlock(host); - rrdpush_unlock(host); - if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) - error("STREAM %s [send]: cannot set pthread cancel state to ENABLE.", host->hostname); + pthread_cleanup_pop(1); pthread_exit(NULL); return NULL; @@ -560,7 +699,11 @@ cleanup: // ---------------------------------------------------------------------------- // rrdpush receiver thread -static int rrdpush_receive(int fd, const char *key, const char *hostname, const char *registry_hostname, const char *machine_guid, const char *os, const char *tags, int update_every, char *client_ip, char *client_port) { +static void log_stream_connection(const char *client_ip, const char *client_port, const char *api_key, const char *machine_guid, const char *host, const char *msg) { + log_access("STREAM: %d '[%s]:%s' '%s' host '%s' api key '%s' machine guid '%s'", gettid(), client_ip, client_port, msg, host, api_key, machine_guid); +} + +static int rrdpush_receive(int fd, const char *key, const char *hostname, const char *registry_hostname, const char *machine_guid, const char *os, const char *timezone, const char *tags, int update_every, char *client_ip, char *client_port) { RRDHOST *host; int history = default_rrd_history_entries; RRD_MEMORY_MODE mode = default_rrd_memory_mode; @@ -606,6 +749,7 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const , registry_hostname , machine_guid , os + , timezone , tags , update_every , history @@ -618,6 +762,7 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const if(!host) { close(fd); + log_stream_connection(client_ip, client_port, key, machine_guid, hostname, "FAILED - CANNOT ACQUIRE HOST"); error("STREAM %s [receive from [%s]:%s]: failed to find/create host structure.", hostname, client_ip, client_port); return 1; } @@ -656,6 +801,7 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const info("STREAM %s [receive from [%s]:%s]: initializing communication...", host->hostname, client_ip, client_port); if(send_timeout(fd, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT), 0, 60) != strlen(START_STREAMING_PROMPT)) { + log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "FAILED - CANNOT REPLY"); error("STREAM %s [receive from [%s]:%s]: cannot send ready command.", host->hostname, client_ip, client_port); close(fd); return 0; @@ -668,6 +814,7 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const // convert the socket to a FILE * FILE *fp = fdopen(fd, "r"); if(!fp) { + log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "FAILED - SOCKET ERROR"); error("STREAM %s [receive from [%s]:%s]: failed to get a FILE for FD %d.", host->hostname, client_ip, client_port, fd); close(fd); return 0; @@ -677,8 +824,9 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const if(host->connected_senders > 0) info("STREAM %s [receive from [%s]:%s]: multiple streaming connections for the same host detected. If multiple netdata are pushing metrics for the same charts, at the same time, the result is unexpected.", host->hostname, client_ip, client_port); + rrdhost_flag_clear(host, RRDHOST_FLAG_ORPHAN); host->connected_senders++; - rrdhost_flag_clear(host, RRDHOST_ORPHAN); + host->senders_disconnected_time = 0; if(health_enabled != CONFIG_BOOLEAN_NO) { if(alarms_delay > 0) { host->health_delay_up_to = now_realtime_sec() + alarms_delay; @@ -692,20 +840,25 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const // call the plugins.d processor to receive the metrics info("STREAM %s [receive from [%s]:%s]: receiving metrics...", host->hostname, client_ip, client_port); + log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "CONNECTED"); + size_t count = pluginsd_process(host, &cd, fp, 1); - error("STREAM %s [receive from [%s]:%s]: disconnected (completed updates %zu).", host->hostname, client_ip, client_port, count); + + log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "DISCONNECTED"); + error("STREAM %s [receive from [%s]:%s]: disconnected (completed %zu updates).", host->hostname, client_ip, client_port, count); rrdhost_wrlock(host); host->senders_disconnected_time = now_realtime_sec(); host->connected_senders--; if(!host->connected_senders) { - rrdhost_flag_set(host, RRDHOST_ORPHAN); + rrdhost_flag_set(host, RRDHOST_FLAG_ORPHAN); if(health_enabled == CONFIG_BOOLEAN_AUTO) host->health_enabled = 0; } rrdhost_unlock(host); - rrdpush_sender_thread_stop(host); + if(host->connected_senders == 0) + rrdpush_sender_thread_stop(host); // cleanup fclose(fp); @@ -720,6 +873,7 @@ struct rrdpush_thread { char *registry_hostname; char *machine_guid; char *os; + char *timezone; char *tags; char *client_ip; char *client_port; @@ -737,7 +891,7 @@ static void *rrdpush_receiver_thread(void *ptr) { info("STREAM %s [%s]:%s: receive thread created (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid()); - rrdpush_receive(rpt->fd, rpt->key, rpt->hostname, rpt->registry_hostname, rpt->machine_guid, rpt->os, rpt->tags, rpt->update_every, rpt->client_ip, rpt->client_port); + rrdpush_receive(rpt->fd, rpt->key, rpt->hostname, rpt->registry_hostname, rpt->machine_guid, rpt->os, rpt->timezone, rpt->tags, rpt->update_every, rpt->client_ip, rpt->client_port); info("STREAM %s [receive from [%s]:%s]: receive thread ended (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid()); freez(rpt->key); @@ -745,6 +899,7 @@ static void *rrdpush_receiver_thread(void *ptr) { freez(rpt->registry_hostname); freez(rpt->machine_guid); freez(rpt->os); + freez(rpt->timezone); freez(rpt->tags); freez(rpt->client_ip); freez(rpt->client_port); @@ -757,25 +912,30 @@ static void *rrdpush_receiver_thread(void *ptr) { static void rrdpush_sender_thread_spawn(RRDHOST *host) { rrdhost_wrlock(host); - if(!host->rrdpush_spawn) { - if(pthread_create(&host->rrdpush_thread, NULL, rrdpush_sender_thread, (void *) host)) + if(!host->rrdpush_sender_spawn) { + if(pthread_create(&host->rrdpush_sender_thread, NULL, rrdpush_sender_thread, (void *) host)) error("STREAM %s [send]: failed to create new thread for client.", host->hostname); - - else if(pthread_detach(host->rrdpush_thread)) - error("STREAM %s [send]: cannot request detach newly created thread.", host->hostname); - - host->rrdpush_spawn = 1; + else + host->rrdpush_sender_spawn = 1; } rrdhost_unlock(host); } +int rrdpush_receiver_permission_denied(struct web_client *w) { + // we always respond with the same message and error code + // to prevent an attacker from gaining info about the error + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "You are not permitted to access this. Check the logs for more info."); + return 401; +} + int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url) { (void)host; info("STREAM [receive from [%s]:%s]: new client connection.", w->client_ip, w->client_port); - char *key = NULL, *hostname = NULL, *registry_hostname = NULL, *machine_guid = NULL, *os = "unknown", *tags = NULL; + char *key = NULL, *hostname = NULL, *registry_hostname = NULL, *machine_guid = NULL, *os = "unknown", *timezone = "unknown", *tags = NULL; int update_every = default_rrd_update_every; char buf[GUID_LEN + 1]; @@ -799,6 +959,8 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url update_every = (int)strtoul(value, NULL, 0); else if(!strcmp(name, "os")) os = value; + else if(!strcmp(name, "timezone")) + timezone = value; else if(!strcmp(name, "tags")) tags = value; else @@ -806,52 +968,71 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url } if(!key || !*key) { + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO KEY"); error("STREAM [receive from [%s]:%s]: request without an API key. Forbidding access.", w->client_ip, w->client_port); - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "You need an API key for this request."); - return 401; + return rrdpush_receiver_permission_denied(w); } if(!hostname || !*hostname) { + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO HOSTNAME"); error("STREAM [receive from [%s]:%s]: request without a hostname. Forbidding access.", w->client_ip, w->client_port); - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "You need to send a hostname too."); - return 400; + return rrdpush_receiver_permission_denied(w); } if(!machine_guid || !*machine_guid) { + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO MACHINE GUID"); error("STREAM [receive from [%s]:%s]: request without a machine GUID. Forbidding access.", w->client_ip, w->client_port); - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "You need to send a machine GUID too."); - return 400; + return rrdpush_receiver_permission_denied(w); } if(regenerate_guid(key, buf) == -1) { + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - INVALID KEY"); error("STREAM [receive from [%s]:%s]: API key '%s' is not valid GUID (use the command uuidgen to generate one). Forbidding access.", w->client_ip, w->client_port, key); - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Your API key is invalid."); - return 401; + return rrdpush_receiver_permission_denied(w); } if(regenerate_guid(machine_guid, buf) == -1) { + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - INVALID MACHINE GUID"); error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not GUID. Forbidding access.", w->client_ip, w->client_port, machine_guid); - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Your machine GUID is invalid."); - return 404; + return rrdpush_receiver_permission_denied(w); } if(!appconfig_get_boolean(&stream_config, key, "enabled", 0)) { + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - KEY NOT ENABLED"); error("STREAM [receive from [%s]:%s]: API key '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, key); - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Your API key is not permitted access."); - return 401; + return rrdpush_receiver_permission_denied(w); + } + + { + SIMPLE_PATTERN *key_allow_from = simple_pattern_create(appconfig_get(&stream_config, key, "allow from", "*"), SIMPLE_PATTERN_EXACT); + if(key_allow_from) { + if(!simple_pattern_matches(key_allow_from, w->client_ip)) { + simple_pattern_free(key_allow_from); + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname) ? hostname : "-", "ACCESS DENIED - KEY NOT ALLOWED FROM THIS IP"); + error("STREAM [receive from [%s]:%s]: API key '%s' is not permitted from this IP. Forbidding access.", w->client_ip, w->client_port, key); + return rrdpush_receiver_permission_denied(w); + } + simple_pattern_free(key_allow_from); + } } if(!appconfig_get_boolean(&stream_config, machine_guid, "enabled", 1)) { + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - MACHINE GUID NOT ENABLED"); error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, machine_guid); - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Your machine guide is not permitted access."); - return 404; + return rrdpush_receiver_permission_denied(w); + } + + { + SIMPLE_PATTERN *machine_allow_from = simple_pattern_create(appconfig_get(&stream_config, machine_guid, "allow from", "*"), SIMPLE_PATTERN_EXACT); + if(machine_allow_from) { + if(!simple_pattern_matches(machine_allow_from, w->client_ip)) { + simple_pattern_free(machine_allow_from); + log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname) ? hostname : "-", "ACCESS DENIED - MACHINE GUID NOT ALLOWED FROM THIS IP"); + error("STREAM [receive from [%s]:%s]: Machine GUID '%s' is not permitted from this IP. Forbidding access.", w->client_ip, w->client_port, machine_guid); + return rrdpush_receiver_permission_denied(w); + } + simple_pattern_free(machine_allow_from); + } } struct rrdpush_thread *rpt = mallocz(sizeof(struct rrdpush_thread)); @@ -861,6 +1042,7 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url rpt->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname); rpt->machine_guid = strdupz(machine_guid); rpt->os = strdupz(os); + rpt->timezone = strdupz(timezone); rpt->tags = (tags)?strdupz(tags):NULL; rpt->client_ip = strdupz(w->client_ip); rpt->client_port = strdupz(w->client_port); diff --git a/src/rrdpush.h b/src/rrdpush.h index c3c7f4a5..bf3d9435 100644 --- a/src/rrdpush.h +++ b/src/rrdpush.h @@ -14,4 +14,6 @@ extern void *rrdpush_sender_thread(void *ptr); extern int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url); extern void rrdpush_sender_thread_stop(RRDHOST *host); +extern void rrdpush_sender_send_this_host_variable_now(RRDHOST *host, RRDVAR *rv); + #endif //NETDATA_RRDPUSH_H diff --git a/src/rrdset.c b/src/rrdset.c index c5168f02..8504d1cb 100644 --- a/src/rrdset.c +++ b/src/rrdset.c @@ -135,11 +135,11 @@ char *rrdset_strncpyz_name(char *to, const char *from, size_t length) { return to; } -void rrdset_set_name(RRDSET *st, const char *name) { +int rrdset_set_name(RRDSET *st, const char *name) { if(unlikely(st->name && !strcmp(st->name, name))) - return; + return 1; - debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name); + debug(D_RRD_CALLS, "rrdset_set_name() old: '%s', new: '%s'", st->name?st->name:"", name); char b[CONFIG_MAX_VALUE + 1]; char n[RRD_ID_LENGTH_MAX + 1]; @@ -147,6 +147,11 @@ void rrdset_set_name(RRDSET *st, const char *name) { snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name); rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE); + if(rrdset_index_find_name(st->rrdhost, b, 0)) { + error("RRDSET: chart name '%s' on host '%s' already exists.", b, st->rrdhost->hostname); + return 0; + } + if(st->name) { rrdset_index_del_name(st->rrdhost, st); st->name = config_set_default(st->config_section, "name", b); @@ -166,6 +171,8 @@ void rrdset_set_name(RRDSET *st, const char *name) { if(unlikely(rrdset_index_add_name(st->rrdhost, st) != st)) error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name); + + return 1; } inline void rrdset_is_obsolete(RRDSET *st) { @@ -175,7 +182,7 @@ inline void rrdset_is_obsolete(RRDSET *st) { // the chart will not get more updates (data collection) // so, we have to push its definition now - if(unlikely(st->rrdhost->rrdpush_enabled)) + if(unlikely(st->rrdhost->rrdpush_send_enabled)) rrdset_push_chart_definition(st); } } @@ -309,6 +316,9 @@ void rrdset_free(RRDSET *st) { rrdfamily_free(st->rrdhost, st->rrdfamily); + debug(D_RRD_CALLS, "RRDSET: Cleaning up remaining chart variables for host '%s', chart '%s'", st->rrdhost->hostname, st->id); + rrdvar_free_remaining_variables(st->rrdhost, &st->rrdvar_root_index); + // ------------------------------------------------------------------------ // unlink it from the host @@ -334,6 +344,8 @@ void rrdset_free(RRDSET *st) { // free directly allocated members freez(st->config_section); + freez(st->plugin_name); + freez(st->module_name); switch(st->rrd_memory_mode) { case RRD_MEMORY_MODE_SAVE: @@ -416,6 +428,8 @@ RRDSET *rrdset_create_custom( , const char *context , const char *title , const char *units + , const char *plugin + , const char *module , long priority , int update_every , RRDSET_TYPE chart_type @@ -423,12 +437,30 @@ RRDSET *rrdset_create_custom( , long history_entries ) { if(!type || !type[0]) { - fatal("Cannot create rrd stats without a type."); + fatal("Cannot create rrd stats without a type: id '%s', name '%s', family '%s', context '%s', title '%s', units '%s', plugin '%s', module '%s'." + , (id && *id)?id:"<unset>" + , (name && *name)?name:"<unset>" + , (family && *family)?family:"<unset>" + , (context && *context)?context:"<unset>" + , (title && *title)?title:"<unset>" + , (units && *units)?units:"<unset>" + , (plugin && *plugin)?plugin:"<unset>" + , (module && *module)?module:"<unset>" + ); return NULL; } if(!id || !id[0]) { - fatal("Cannot create rrd stats without an id."); + fatal("Cannot create rrd stats without an id: type '%s', name '%s', family '%s', context '%s', title '%s', units '%s', plugin '%s', module '%s'." + , type + , (name && *name)?name:"<unset>" + , (family && *family)?family:"<unset>" + , (context && *context)?context:"<unset>" + , (title && *title)?title:"<unset>" + , (units && *units)?units:"<unset>" + , (plugin && *plugin)?plugin:"<unset>" + , (module && *module)?module:"<unset>" + ); return NULL; } @@ -495,7 +527,7 @@ RRDSET *rrdset_create_custom( if(st) { memset(&st->avl, 0, sizeof(avl)); memset(&st->avlname, 0, sizeof(avl)); - memset(&st->variables_root_index, 0, sizeof(avl_tree_lock)); + memset(&st->rrdvar_root_index, 0, sizeof(avl_tree_lock)); memset(&st->dimensions_index, 0, sizeof(avl_tree_lock)); memset(&st->rrdset_rwlock, 0, sizeof(netdata_rwlock_t)); @@ -507,6 +539,8 @@ RRDSET *rrdset_create_custom( st->units = NULL; st->context = NULL; st->cache_dir = NULL; + st->plugin_name = NULL; + st->module_name = NULL; st->dimensions = NULL; st->rrdfamily = NULL; st->rrdhost = NULL; @@ -564,6 +598,9 @@ RRDSET *rrdset_create_custom( st->rrd_memory_mode = (memory_mode == RRD_MEMORY_MODE_NONE) ? RRD_MEMORY_MODE_NONE : RRD_MEMORY_MODE_ALLOC; } + st->plugin_name = plugin?strdup(plugin):NULL; + st->module_name = module?strdup(module):NULL; + st->config_section = strdup(config_section); st->rrdhost = host; st->memsize = size; @@ -624,12 +661,16 @@ RRDSET *rrdset_create_custom( st->upstream_resync_time = 0; avl_init_lock(&st->dimensions_index, rrddim_compare); - avl_init_lock(&st->variables_root_index, rrdvar_compare); + avl_init_lock(&st->rrdvar_root_index, rrdvar_compare); netdata_rwlock_init(&st->rrdset_rwlock); - if(name && *name) rrdset_set_name(st, name); - else rrdset_set_name(st, id); + if(name && *name && rrdset_set_name(st, name)) + // we did set the name + ; + else + // could not use the name, use the id + rrdset_set_name(st, id); st->title = config_get(st->config_section, "title", title); json_fix_string(st->title); @@ -640,11 +681,11 @@ RRDSET *rrdset_create_custom( host->rrdset_root = st; if(host->health_enabled) { - rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, 0); - rrdsetvar_create(st, "collected_total_raw", RRDVAR_TYPE_TOTAL, &st->last_collected_total, 0); - rrdsetvar_create(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, 0); - rrdsetvar_create(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, 0); - rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, 0); + rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT); + rrdsetvar_create(st, "collected_total_raw", RRDVAR_TYPE_TOTAL, &st->last_collected_total, RRDVAR_OPTION_DEFAULT); + rrdsetvar_create(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, RRDVAR_OPTION_DEFAULT); + rrdsetvar_create(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, RRDVAR_OPTION_DEFAULT); + rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, RRDVAR_OPTION_DEFAULT); } if(unlikely(rrdset_index_add(host, st) != st)) @@ -1029,7 +1070,7 @@ void rrdset_done(RRDSET *st) { if(unlikely(netdata_exit)) return; if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) { - if(unlikely(st->rrdhost->rrdpush_enabled)) + if(unlikely(st->rrdhost->rrdpush_send_enabled)) rrdset_done_push_exclusive(st); return; @@ -1154,7 +1195,7 @@ void rrdset_done(RRDSET *st) { } st->counter_done++; - if(unlikely(st->rrdhost->rrdpush_enabled)) + if(unlikely(st->rrdhost->rrdpush_send_enabled)) rrdset_done_push(st); #ifdef NETDATA_INTERNAL_CHECKS diff --git a/src/rrdsetvar.c b/src/rrdsetvar.c index 03d7aece..280156a8 100644 --- a/src/rrdsetvar.c +++ b/src/rrdsetvar.c @@ -8,29 +8,29 @@ static inline void rrdsetvar_free_variables(RRDSETVAR *rs) { RRDSET *st = rs->rrdset; + // ------------------------------------------------------------------------ // CHART - - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local); + rrdvar_free(st->rrdhost, &st->rrdvar_root_index, rs->var_local); rs->var_local = NULL; + // ------------------------------------------------------------------------ // FAMILY - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family); + rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family); rs->var_family = NULL; - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host); - rs->var_host = NULL; + rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family_name); + rs->var_family_name = NULL; + // ------------------------------------------------------------------------ // HOST + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host); + rs->var_host = NULL; - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); - rs->var_family_name = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_name); + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host_name); rs->var_host_name = NULL; + // ------------------------------------------------------------------------ // KEYS - freez(rs->key_fullid); rs->key_fullid = NULL; @@ -39,10 +39,14 @@ static inline void rrdsetvar_free_variables(RRDSETVAR *rs) { } static inline void rrdsetvar_create_variables(RRDSETVAR *rs) { - rrdsetvar_free_variables(rs); - RRDSET *st = rs->rrdset; + // ------------------------------------------------------------------------ + // free the old ones (if any) + + rrdsetvar_free_variables(rs); + + // ------------------------------------------------------------------------ // KEYS char buffer[RRDVAR_MAX_LENGTH + 1]; @@ -52,27 +56,27 @@ static inline void rrdsetvar_create_variables(RRDSETVAR *rs) { snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rs->variable); rs->key_fullname = strdupz(buffer); + // ------------------------------------------------------------------------ // CHART + rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, rs->value); - rs->var_local = rrdvar_create_and_index("local", &st->variables_root_index, rs->variable, rs->type, rs->value); - + // ------------------------------------------------------------------------ // FAMILY + rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, rs->value); - rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullid, rs->type, rs->value); - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullname, rs->type, rs->value); - + // ------------------------------------------------------------------------ // HOST - - rs->var_host = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullid, rs->type, rs->value); - rs->var_host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullname, rs->type, rs->value); - + rs->var_host = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullid, rs->type, rs->value); + rs->var_host_name = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullname, rs->type, rs->value); } -RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options) { +RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options) { debug(D_VARIABLES, "RRDVARSET create for chart id '%s' name '%s' with variable name '%s'", st->id, st->name, variable); RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR)); rs->variable = strdupz(variable); + rs->hash = simple_hash(rs->variable); rs->type = type; rs->value = value; rs->options = options; @@ -89,11 +93,9 @@ RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *va void rrdsetvar_rename_all(RRDSET *st) { debug(D_VARIABLES, "RRDSETVAR rename for chart id '%s' name '%s'", st->id, st->name); - RRDSETVAR *rs, *next = st->variables; - while((rs = next)) { - next = rs->next; + RRDSETVAR *rs; + for(rs = st->variables; rs ; rs = rs->next) rrdsetvar_create_variables(rs); - } rrdsetcalc_link_matching(st); } @@ -115,6 +117,63 @@ void rrdsetvar_free(RRDSETVAR *rs) { rrdsetvar_free_variables(rs); freez(rs->variable); + + if(rs->options & RRDVAR_OPTION_ALLOCATED) + freez(rs->value); + freez(rs); } +// -------------------------------------------------------------------------------------------------------------------- +// custom chart variables + +RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name) { + char *n = strdupz(name); + rrdvar_fix_name(n); + uint32_t hash = simple_hash(n); + + rrdset_wrlock(st); + + // find it + RRDSETVAR *rs; + for(rs = st->variables; rs ; rs = rs->next) { + if(hash == rs->hash && strcmp(n, rs->variable) == 0) { + rrdset_unlock(st); + if(rs->options & RRDVAR_OPTION_ALLOCATED) { + free(n); + return rs; + } + else { + error("RRDSETVAR: custom variable '%s' on chart '%s' of host '%s', conflicts with an internal chart variable", n, st->id, st->rrdhost->hostname); + free(n); + return NULL; + } + } + } + + // not found, allocate one + + calculated_number *v = mallocz(sizeof(calculated_number)); + *v = NAN; + + rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED); + rrdset_unlock(st); + + free(n); + return rs; +} + +void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rs, calculated_number value) { + if(unlikely(!(rs->options & RRDVAR_OPTION_ALLOCATED))) { + error("RRDSETVAR: requested to set variable '%s' of chart '%s' on host '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rs->variable, rs->rrdset->id, rs->rrdset->rrdhost->hostname, value); + } + else { + calculated_number *v = rs->value; + if(*v != value) { + *v = value; + + // mark the chart to be sent upstream + rrdset_flag_clear(rs->rrdset, RRDSET_FLAG_EXPOSED_UPSTREAM); + } + } +} diff --git a/src/rrdvar.c b/src/rrdvar.c index 2223d7c9..9119b538 100644 --- a/src/rrdvar.c +++ b/src/rrdvar.c @@ -56,14 +56,17 @@ inline void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv) { if(tree) { debug(D_VARIABLES, "Deleting variable '%s'", rv->name); if(unlikely(!rrdvar_index_del(tree, rv))) - error("Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname); + error("RRDVAR: Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname); } + if(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED) + freez(rv->value); + freez(rv->name); freez(rv); } -inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, int type, void *value) { +inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value) { char *variable = strdupz(name); rrdvar_fix_name(variable); uint32_t hash = simple_hash(variable); @@ -81,7 +84,8 @@ inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, c RRDVAR *ret = rrdvar_index_add(tree, rv); if(unlikely(ret != rv)) { debug(D_VARIABLES, "Variable '%s' in scope '%s' already exists", variable, scope); - rrdvar_free(NULL, NULL, rv); + freez(rv); + freez(variable); rv = NULL; } else @@ -101,61 +105,64 @@ inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, c return rv; } +void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock) { + // FIXME: this is not bullet proof - avl should support some means to destroy it + // with a callback for each item already in the index + + RRDVAR *rv, *last = NULL; + while((rv = (RRDVAR *)tree_lock->avl_tree.root)) { + if(unlikely(rv == last)) { + error("RRDVAR: INTERNAL ERROR: Cannot cleanup tree of RRDVARs"); + break; + } + last = rv; + rrdvar_free(host, tree_lock, rv); + } +} + // ---------------------------------------------------------------------------- -// CUSTOM VARIABLES +// CUSTOM HOST VARIABLES -RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) { +inline int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data) { + return avl_traverse_lock(&host->rrdvar_root_index, callback, data); +} + +static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *tree_lock, const char *name) { calculated_number *v = callocz(1, sizeof(calculated_number)); *v = NAN; - RRDVAR *rv = rrdvar_create_and_index("host", &host->variables_root_index, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v); + + RRDVAR *rv = rrdvar_create_and_index(scope, tree_lock, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v); if(unlikely(!rv)) { free(v); - error("Requested variable '%s' already exists - possibly 2 plugins will be updating it at the same time", name); + debug(D_VARIABLES, "Requested variable '%s' already exists - possibly 2 plugins are updating it at the same time.", name); char *variable = strdupz(name); rrdvar_fix_name(variable); uint32_t hash = simple_hash(variable); - rv = rrdvar_index_find(&host->variables_root_index, variable, hash); + rv = rrdvar_index_find(tree_lock, variable, hash); + + freez(variable); } return rv; } -void rrdvar_custom_host_variable_destroy(RRDHOST *host, const char *name) { - char *variable = strdupz(name); - rrdvar_fix_name(variable); - uint32_t hash = simple_hash(variable); - - RRDVAR *rv = rrdvar_index_find(&host->variables_root_index, variable, hash); - freez(variable); - - if(!rv) { - error("Attempted to remove variable '%s' from host '%s', but it does not exist.", name, host->hostname); - return; - } - - if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) { - error("Attempted to remove variable '%s' from host '%s', but it does not a custom allocated variable.", name, host->hostname); - return; - } - - if(!rrdvar_index_del(&host->variables_root_index, rv)) { - error("Attempted to remove variable '%s' from host '%s', but it cannot be found.", name, host->hostname); - return; - } - - freez(rv->name); - freez(rv->value); - freez(rv); +RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) { + return rrdvar_custom_variable_create("host", &host->rrdvar_root_index, name); } -void rrdvar_custom_host_variable_set(RRDVAR *rv, calculated_number value) { +void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value) { if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value); else { calculated_number *v = rv->value; - *v = value; + if(*v != value) { + *v = value; + + // if the host is streaming, send this variable upstream immediately + rrdpush_sender_send_this_host_variable_now(host, rv); + } } } @@ -191,7 +198,7 @@ static calculated_number rrdvar2number(RRDVAR *rv) { } default: - error("I don't know how to convert RRDVAR type %d to calculated_number", rv->type); + error("I don't know how to convert RRDVAR type %u to calculated_number", rv->type); return NAN; } } @@ -202,19 +209,19 @@ int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, cal if(!st) return 0; - rv = rrdvar_index_find(&st->variables_root_index, variable, hash); + rv = rrdvar_index_find(&st->rrdvar_root_index, variable, hash); if(rv) { *result = rrdvar2number(rv); return 1; } - rv = rrdvar_index_find(&st->rrdfamily->variables_root_index, variable, hash); + rv = rrdvar_index_find(&st->rrdfamily->rrdvar_root_index, variable, hash); if(rv) { *result = rrdvar2number(rv); return 1; } - rv = rrdvar_index_find(&st->rrdhost->variables_root_index, variable, hash); + rv = rrdvar_index_find(&st->rrdhost->rrdvar_root_index, variable, hash); if(rv) { *result = rrdvar2number(rv); return 1; @@ -253,13 +260,13 @@ void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf) { }; buffer_sprintf(buf, "{\n\t\"chart\": \"%s\",\n\t\"chart_name\": \"%s\",\n\t\"chart_context\": \"%s\",\n\t\"chart_variables\": {", st->id, st->name, st->context); - avl_traverse_lock(&st->variables_root_index, single_variable2json, (void *)&helper); + avl_traverse_lock(&st->rrdvar_root_index, single_variable2json, (void *)&helper); buffer_sprintf(buf, "\n\t},\n\t\"family\": \"%s\",\n\t\"family_variables\": {", st->family); helper.counter = 0; - avl_traverse_lock(&st->rrdfamily->variables_root_index, single_variable2json, (void *)&helper); + avl_traverse_lock(&st->rrdfamily->rrdvar_root_index, single_variable2json, (void *)&helper); buffer_sprintf(buf, "\n\t},\n\t\"host\": \"%s\",\n\t\"host_variables\": {", st->rrdhost->hostname); helper.counter = 0; - avl_traverse_lock(&st->rrdhost->variables_root_index, single_variable2json, (void *)&helper); + avl_traverse_lock(&st->rrdhost->rrdvar_root_index, single_variable2json, (void *)&helper); buffer_strcat(buf, "\n\t}\n}\n"); } diff --git a/src/signals.h b/src/signals.h index d8611ede..2fdd3655 100644 --- a/src/signals.h +++ b/src/signals.h @@ -4,7 +4,7 @@ extern void signals_init(void); extern void signals_block(void); extern void signals_unblock(void); -extern void signals_handle(void); extern void signals_reset(void); +extern void signals_handle(void) NORETURN; #endif //NETDATA_SIGNALS_H diff --git a/src/simple_pattern.c b/src/simple_pattern.c index f72a42d0..469ea396 100644 --- a/src/simple_pattern.c +++ b/src/simple_pattern.c @@ -12,12 +12,13 @@ struct simple_pattern { struct simple_pattern *next; }; -static inline struct simple_pattern *parse_pattern(const char *str, SIMPLE_PREFIX_MODE default_mode) { +static inline struct simple_pattern *parse_pattern(char *str, SIMPLE_PREFIX_MODE default_mode) { + // fprintf(stderr, "PARSING PATTERN: '%s'\n", str); + SIMPLE_PREFIX_MODE mode; struct simple_pattern *child = NULL; - char *buf = strdupz(str); - char *s = buf, *c = buf; + char *s = str, *c = str; // skip asterisks in front while(*c == '*') c++; @@ -64,8 +65,6 @@ static inline struct simple_pattern *parse_pattern(const char *str, SIMPLE_PREFI m->child = child; - freez(buf); - return m; } @@ -74,51 +73,63 @@ SIMPLE_PATTERN *simple_pattern_create(const char *list, SIMPLE_PREFIX_MODE defau if(unlikely(!list || !*list)) return root; - char *buf = strdupz(list); - if(buf && *buf) { - char *s = buf; + char *buf = mallocz(strlen(list) + 1); + const char *s = list; - while(s && *s) { - char negative = 0; + while(s && *s) { + buf[0] = '\0'; + char *c = buf; - // skip all spaces - while(isspace(*s)) s++; + char negative = 0; - if(*s == '!') { - negative = 1; - s++; - } + // skip all spaces + while(isspace(*s)) + s++; - // empty string - if(unlikely(!*s)) break; + if(*s == '!') { + negative = 1; + s++; + } - // find the next space - char *c = s; - while(*c && !isspace(*c)) c++; + // empty string + if(unlikely(!*s)) + break; - // find the next word - char *n; - if(likely(*c)) n = c + 1; - else n = NULL; + // find the next space + char escape = 0; + while(*s) { + if(*s == '\\' && !escape) { + escape = 1; + s++; + } + else { + if (isspace(*s) && !escape) { + s++; + break; + } - // terminate our string - *c = '\0'; + *c++ = *s++; + escape = 0; + } + } - struct simple_pattern *m = parse_pattern(s, default_mode); - m->negative = negative; + // terminate our string + *c = '\0'; - if(likely(n)) *c = ' '; + // if we matched the empty string, skip it + if(unlikely(!*buf)) + continue; - // link it at the end - if(unlikely(!root)) - root = last = m; - else { - last->next = m; - last = m; - } + // fprintf(stderr, "FOUND PATTERN: '%s'\n", buf); + struct simple_pattern *m = parse_pattern(buf, default_mode); + m->negative = negative; - // prepare for next loop - s = n; + // link it at the end + if(unlikely(!root)) + root = last = m; + else { + last->next = m; + last = m; } } @@ -126,7 +137,28 @@ SIMPLE_PATTERN *simple_pattern_create(const char *list, SIMPLE_PREFIX_MODE defau return (SIMPLE_PATTERN *)root; } -static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len) { +static inline char *add_wildcarded(const char *matched, size_t matched_size, char *wildcarded, size_t *wildcarded_size) { + //if(matched_size) { + // char buf[matched_size + 1]; + // strncpyz(buf, matched, matched_size); + // fprintf(stderr, "ADD WILDCARDED '%s' of length %zu\n", buf, matched_size); + //} + + if(unlikely(wildcarded && *wildcarded_size && matched && *matched && matched_size)) { + size_t wss = *wildcarded_size - 1; + size_t len = (matched_size < wss)?matched_size:wss; + if(likely(len)) { + strncpyz(wildcarded, matched, len); + + *wildcarded_size -= len; + return &wildcarded[len]; + } + } + + return wildcarded; +} + +static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len, char *wildcarded, size_t *wildcarded_size) { char *s; if(m->len <= len) { @@ -134,20 +166,28 @@ static inline int match_pattern(struct simple_pattern *m, const char *str, size_ case SIMPLE_PATTERN_SUBSTRING: if(!m->len) return 1; if((s = strstr(str, m->match))) { - if(!m->child) return 1; - return match_pattern(m->child, &s[m->len], len - (s - str) - m->len); + wildcarded = add_wildcarded(str, s - str, wildcarded, wildcarded_size); + if(!m->child) { + wildcarded = add_wildcarded(&s[m->len], len - (&s[m->len] - str), wildcarded, wildcarded_size); + return 1; + } + return match_pattern(m->child, &s[m->len], len - (s - str) - m->len, wildcarded, wildcarded_size); } break; case SIMPLE_PATTERN_PREFIX: if(unlikely(strncmp(str, m->match, m->len) == 0)) { - if(!m->child) return 1; - return match_pattern(m->child, &str[m->len], len - m->len); + if(!m->child) { + wildcarded = add_wildcarded(&str[m->len], len - m->len, wildcarded, wildcarded_size); + return 1; + } + return match_pattern(m->child, &str[m->len], len - m->len, wildcarded, wildcarded_size); } break; case SIMPLE_PATTERN_SUFFIX: if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) { + wildcarded = add_wildcarded(str, len - m->len, wildcarded, wildcarded_size); if(!m->child) return 1; return 0; } @@ -166,17 +206,26 @@ static inline int match_pattern(struct simple_pattern *m, const char *str, size_ return 0; } -int simple_pattern_matches(SIMPLE_PATTERN *list, const char *str) { +int simple_pattern_matches_extract(SIMPLE_PATTERN *list, const char *str, char *wildcarded, size_t wildcarded_size) { struct simple_pattern *m, *root = (struct simple_pattern *)list; if(unlikely(!root || !str || !*str)) return 0; size_t len = strlen(str); - for(m = root; m ; m = m->next) - if(match_pattern(m, str, len)) { - if(m->negative) return 0; + for(m = root; m ; m = m->next) { + char *ws = wildcarded; + size_t wss = wildcarded_size; + if(unlikely(ws)) *ws = '\0'; + + if (match_pattern(m, str, len, ws, &wss)) { + + //if(ws && wss) + // fprintf(stderr, "FINAL WILDCARDED '%s' of length %zu\n", ws, strlen(ws)); + + if (m->negative) return 0; return 1; } + } return 0; } diff --git a/src/simple_pattern.h b/src/simple_pattern.h index 3768c508..60a25f49 100644 --- a/src/simple_pattern.h +++ b/src/simple_pattern.h @@ -15,8 +15,11 @@ typedef void SIMPLE_PATTERN; // should be considered PREFIX matches. extern SIMPLE_PATTERN *simple_pattern_create(const char *list, SIMPLE_PREFIX_MODE default_mode); +// test if string str is matched from the pattern and fill 'wildcarded' with the parts matched by '*' +extern int simple_pattern_matches_extract(SIMPLE_PATTERN *list, const char *str, char *wildcarded, size_t wildcarded_size); + // test if string str is matched from the pattern -extern int simple_pattern_matches(SIMPLE_PATTERN *list, const char *str); +#define simple_pattern_matches(list, str) simple_pattern_matches_extract(list, str, NULL, 0) // free a simple_pattern that was created with simple_pattern_create() // list can be NULL, in which case, this does nothing. diff --git a/src/socket.c b/src/socket.c index d28df81a..906ab33d 100644 --- a/src/socket.c +++ b/src/socket.c @@ -857,7 +857,7 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) { // -------------------------------------------------------------------------------------------------------------------- // accept_socket() - accept a socket and store client IP and port -int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize) { +int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list) { struct sockaddr_storage sadr; socklen_t addrlen = sizeof(sadr); @@ -873,6 +873,13 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien client_port[portsize - 1] = '\0'; switch (((struct sockaddr *)&sadr)->sa_family) { + case AF_UNIX: + debug(D_LISTENER, "New UNIX domain web client from %s on socket %d.", client_ip, fd); + // set the port - certain versions of libc return garbage on unix sockets + strncpy(client_port, "UNIX", portsize); + client_port[portsize - 1] = '\0'; + break; + case AF_INET: debug(D_LISTENER, "New IPv4 web client from %s port %s on socket %d.", client_ip, client_port, fd); break; @@ -881,7 +888,8 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien if (strncmp(client_ip, "::ffff:", 7) == 0) { memmove(client_ip, &client_ip[7], strlen(&client_ip[7]) + 1); debug(D_LISTENER, "New IPv4 web client from %s port %s on socket %d.", client_ip, client_port, fd); - } else + } + else debug(D_LISTENER, "New IPv6 web client from %s port %s on socket %d.", client_ip, client_port, fd); break; @@ -889,6 +897,22 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien debug(D_LISTENER, "New UNKNOWN web client from %s port %s on socket %d.", client_ip, client_port, fd); break; } + + if(access_list) { + if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) { + strncpy(client_ip, "localhost", ipsize); + client_ip[ipsize - 1] = '\0'; + } + + if(unlikely(!simple_pattern_matches(access_list, client_ip))) { + errno = 0; + debug(D_LISTENER, "Permission denied for client '%s', port '%s'", client_ip, client_port); + error("DENIED ACCESS to client '%s'", client_ip); + close(nfd); + nfd = -1; + errno = EPERM; + } + } } #ifdef HAVE_ACCEPT4 else if(errno == ENOSYS) @@ -928,8 +952,8 @@ struct poll { struct pollinfo *inf; struct pollinfo *first_free; - void *(*add_callback)(int fd, short int *events); - void (*del_callback)(int fd, void *data); + void *(*add_callback)(int fd, int socktype, short int *events); + void (*del_callback)(int fd, int socktype, void *data); int (*rcv_callback)(int fd, int socktype, void *data, short int *events); int (*snd_callback)(int fd, int socktype, void *data, short int *events); }; @@ -984,7 +1008,7 @@ static inline struct pollinfo *poll_add_fd(struct poll *p, int fd, int socktype, p->max = pi->slot; if(pi->flags & POLLINFO_FLAG_CLIENT_SOCKET) { - pi->data = p->add_callback(fd, &pf->events); + pi->data = p->add_callback(fd, pi->socktype, &pf->events); } if(pi->flags & POLLINFO_FLAG_SERVER_SOCKET) { @@ -1003,7 +1027,7 @@ static inline void poll_close_fd(struct poll *p, struct pollinfo *pi) { if(unlikely(pf->fd == -1)) return; if(pi->flags & POLLINFO_FLAG_CLIENT_SOCKET) { - p->del_callback(pf->fd, pi->data); + p->del_callback(pf->fd, pi->socktype, pi->data); } close(pf->fd); @@ -1036,14 +1060,16 @@ static inline void poll_close_fd(struct poll *p, struct pollinfo *pi) { 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); } -static void *add_callback_default(int fd, short int *events) { +static void *add_callback_default(int fd, int socktype, short int *events) { (void)fd; + (void)socktype; (void)events; return NULL; } -static void del_callback_default(int fd, void *data) { +static void del_callback_default(int fd, int socktype, void *data) { (void)fd; + (void)socktype; (void)data; if(data) @@ -1100,10 +1126,11 @@ void poll_events_cleanup(void *data) { } void poll_events(LISTEN_SOCKETS *sockets - , void *(*add_callback)(int fd, short int *events) - , void (*del_callback)(int fd, void *data) + , void *(*add_callback)(int fd, int socktype, short int *events) + , void (*del_callback)(int fd, int socktype, void *data) , int (*rcv_callback)(int fd, int socktype, void *data, short int *events) , int (*snd_callback)(int fd, int socktype, void *data, short int *events) + , SIMPLE_PATTERN *access_list , void *data ) { int retval; @@ -1182,7 +1209,7 @@ void poll_events(LISTEN_SOCKETS *sockets char client_port[NI_MAXSERV + 1]; debug(D_POLLFD, "POLLFD: LISTENER: calling accept4() slot %zu (fd %d)", i, fd); - nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, NI_MAXHOST + 1, client_port, NI_MAXSERV + 1); + nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, NI_MAXHOST + 1, client_port, NI_MAXSERV + 1, access_list); if (nfd < 0) { // accept failed @@ -1212,6 +1239,8 @@ void poll_events(LISTEN_SOCKETS *sockets debug(D_POLLFD, "POLLFD: LISTENER: reading data from UDP slot %zu (fd %d)", i, fd); + // FIXME: access_list is not applied to UDP + p.rcv_callback(fd, pi->socktype, pi->data, &pf->events); break; } diff --git a/src/socket.h b/src/socket.h index 8ca7288c..08b8518b 100644 --- a/src/socket.h +++ b/src/socket.h @@ -35,7 +35,7 @@ extern int sock_setreuse_port(int fd, int reuse); extern int sock_enlarge_in(int fd); extern int sock_enlarge_out(int fd); -extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize); +extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list); #ifndef HAVE_ACCEPT4 extern int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags); @@ -52,10 +52,11 @@ extern int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flag extern void poll_events(LISTEN_SOCKETS *sockets - , void *(*add_callback)(int fd, short int *events) - , void (*del_callback)(int fd, void *data) + , void *(*add_callback)(int fd, int socktype, short int *events) + , void (*del_callback)(int fd, int socktype, void *data) , int (*rcv_callback)(int fd, int socktype, void *data, short int *events) , int (*snd_callback)(int fd, int socktype, void *data, short int *events) + , SIMPLE_PATTERN *access_list , void *data ); diff --git a/src/statsd.c b/src/statsd.c index 08ce3e2f..39041ca8 100644 --- a/src/statsd.c +++ b/src/statsd.c @@ -54,6 +54,8 @@ typedef struct statsd_histogram_extensions { collected_number last_stddev; collected_number last_sum; + int zeroed; + RRDDIM *rd_min; RRDDIM *rd_max; RRDDIM *rd_percentile; @@ -165,18 +167,21 @@ typedef enum statsd_app_chart_dimension_value_type { } STATSD_APP_CHART_DIM_VALUE_TYPE; typedef struct statsd_app_chart_dimension { - const char *name; - const char *metric; - uint32_t metric_hash; - collected_number multiplier; - collected_number divisor; - STATSD_APP_CHART_DIM_VALUE_TYPE value_type; + const char *name; // the name of this dimension + const char *metric; // the source metric name of this dimension + uint32_t metric_hash; // hash for fast string comparisons + + SIMPLE_PATTERN *metric_pattern; // set when the 'metric' is a simple pattern + + collected_number multiplier; // the multipler of the dimension + collected_number divisor; // the divisor of the dimension + STATSD_APP_CHART_DIM_VALUE_TYPE value_type; // which value to use of the source metric - RRDDIM *rd; - collected_number *value_ptr; - RRD_ALGORITHM algorithm; + RRDDIM *rd; // a pointer to the RRDDIM that has been created for this dimension + collected_number *value_ptr; // a pointer to the source metric value + RRD_ALGORITHM algorithm; // the algorithm of this dimension - struct statsd_app_chart_dimension *next; + struct statsd_app_chart_dimension *next; // the next dimension for this chart } STATSD_APP_CHART_DIM; typedef struct statsd_app_chart { @@ -202,6 +207,7 @@ typedef struct statsd_app { SIMPLE_PATTERN *metrics; STATS_METRIC_OPTIONS default_options; RRD_MEMORY_MODE rrd_memory_mode; + DICTIONARY *dict; long rrd_history_entries; const char *source; @@ -482,7 +488,7 @@ static inline void statsd_process_histogram(STATSD_METRIC *m, const char *value, static inline void statsd_process_timer(STATSD_METRIC *m, const char *value, const char *sampling) { if(unlikely(!value || !*value)) { - error("STATSD: metric of type set, with empty value is ignored."); + error("STATSD: metric of type timer, with empty value is ignored."); return; } @@ -685,8 +691,9 @@ struct statsd_udp { #endif // new TCP client connected -static void *statsd_add_callback(int fd, short int *events) { +static void *statsd_add_callback(int fd, int socktype, short int *events) { (void)fd; + (void)socktype; *events = POLLIN; struct statsd_tcp *data = (struct statsd_tcp *)callocz(sizeof(struct statsd_tcp) + STATSD_TCP_BUFFER_SIZE, 1); @@ -697,8 +704,9 @@ static void *statsd_add_callback(int fd, short int *events) { } // TCP client disconnected -static void statsd_del_callback(int fd, void *data) { +static void statsd_del_callback(int fd, int socktype, void *data) { (void)fd; + (void)socktype; if(data) { struct statsd_tcp *t = data; @@ -912,6 +920,7 @@ void *statsd_collector_thread(void *ptr) { , statsd_del_callback , statsd_rcv_callback , statsd_snd_callback + , NULL , (void *)d ); @@ -928,6 +937,83 @@ void *statsd_collector_thread(void *ptr) { #define STATSD_CONF_LINE_MAX 8192 +static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t line, const char *path, const char *filename) { + if(!type || !*type) type = "last"; + + if(!strcmp(type, "events")) return STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS; + else if(!strcmp(type, "last")) return STATSD_APP_CHART_DIM_VALUE_TYPE_LAST; + else if(!strcmp(type, "min")) return STATSD_APP_CHART_DIM_VALUE_TYPE_MIN; + else if(!strcmp(type, "max")) return STATSD_APP_CHART_DIM_VALUE_TYPE_MAX; + else if(!strcmp(type, "sum")) return STATSD_APP_CHART_DIM_VALUE_TYPE_SUM; + else if(!strcmp(type, "average")) return STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE; + else if(!strcmp(type, "median")) return STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN; + else if(!strcmp(type, "stddev")) return STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV; + else if(!strcmp(type, "percentile")) return STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE; + + error("STATSD: invalid type '%s' at line %zu of file '%s/%s'. Using 'last'.", type, line, path, filename); + return STATSD_APP_CHART_DIM_VALUE_TYPE_LAST; +} + +static const char *valuetype2string(STATSD_APP_CHART_DIM_VALUE_TYPE type) { + switch(type) { + case STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS: return "events"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_LAST: return "last"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_MIN: return "min"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_MAX: return "max"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_SUM: return "sum"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE: return "average"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN: return "median"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV: return "stddev"; + case STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE: return "percentile"; + } + + return "unknown"; +} + +static STATSD_APP_CHART_DIM *add_dimension_to_app_chart( + STATSD_APP *app + , STATSD_APP_CHART *chart + , const char *metric_name + , const char *dim_name + , collected_number multiplier + , collected_number divisor + , STATSD_APP_CHART_DIM_VALUE_TYPE value_type +) { + STATSD_APP_CHART_DIM *dim = callocz(sizeof(STATSD_APP_CHART_DIM), 1); + + dim->metric = strdupz(metric_name); + dim->metric_hash = simple_hash(dim->metric); + + dim->name = strdupz((dim_name)?dim_name:""); + dim->multiplier = multiplier; + dim->divisor = divisor; + dim->value_type = value_type; + + if(!dim->multiplier) + dim->multiplier = 1; + + if(!dim->divisor) + dim->divisor = 1; + + // append it to the list of dimension + STATSD_APP_CHART_DIM *tdim; + for(tdim = chart->dimensions; tdim && tdim->next ; tdim = tdim->next) ; + if(!tdim) { + dim->next = chart->dimensions; + chart->dimensions = dim; + } + else { + dim->next = tdim->next; + tdim->next = dim; + } + chart->dimensions_count++; + + debug(D_STATSD, "Added dimension '%s' to chart '%s' of app '%s', for metric '%s', with type %u, multiplier " COLLECTED_NUMBER_FORMAT ", divisor " COLLECTED_NUMBER_FORMAT, + dim->name, chart->id, app->name, dim->metric, dim->value_type, dim->multiplier, dim->divisor); + + return dim; +} + int statsd_readfile(const char *path, const char *filename) { debug(D_STATSD, "STATSD configuration reading file '%s/%s'", path, filename); @@ -943,6 +1029,7 @@ int statsd_readfile(const char *path, const char *filename) { STATSD_APP *app = NULL; STATSD_APP_CHART *chart = NULL; + DICTIONARY *dict = NULL; size_t line = 0; char *s; @@ -973,22 +1060,33 @@ int statsd_readfile(const char *path, const char *filename) { app->next = statsd.apps; statsd.apps = app; chart = NULL; + dict = NULL; } else if(app) { - // a new chart - chart = callocz(sizeof(STATSD_APP_CHART), 1); - netdata_fix_chart_id(s); - chart->id = strdupz(s); - chart->name = strdupz(s); - chart->title = strdupz("Statsd chart"); - chart->context = strdupz(s); - chart->family = strdupz("overview"); - chart->units = strdupz("value"); - chart->priority = STATSD_CHART_PRIORITY; - chart->chart_type = RRDSET_TYPE_LINE; - - chart->next = app->charts; - app->charts = chart; + if(!strcmp(s, "dictionary")) { + if(!app->dict) + app->dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + + dict = app->dict; + } + else { + dict = NULL; + + // a new chart + chart = callocz(sizeof(STATSD_APP_CHART), 1); + netdata_fix_chart_id(s); + chart->id = strdupz(s); + chart->name = strdupz(s); + chart->title = strdupz("Statsd chart"); + chart->context = strdupz(s); + chart->family = strdupz("overview"); + chart->units = strdupz("value"); + chart->priority = STATSD_CHART_PRIORITY; + chart->chart_type = RRDSET_TYPE_LINE; + + chart->next = app->charts; + app->charts = chart; + } } else error("STATSD: ignoring line %zu ('%s') of file '%s/%s', [app] is not defined.", line, s, path, filename); @@ -1022,7 +1120,14 @@ int statsd_readfile(const char *path, const char *filename) { continue; } - if(!chart) { + if(unlikely(dict)) { + // parse [dictionary] members + + dictionary_set(dict, name, value, strlen(value) + 1); + } + else if(!chart) { + // parse [app] members + if(!strcmp(name, "name")) { freez((void *)app->name); netdata_fix_chart_name(value); @@ -1056,6 +1161,8 @@ int statsd_readfile(const char *path, const char *filename) { } } else { + // parse [chart] members + if(!strcmp(name, "name")) { freez((void *)chart->name); netdata_fix_chart_id(value); @@ -1086,63 +1193,50 @@ int statsd_readfile(const char *path, const char *filename) { } else if (!strcmp(name, "dimension")) { // metric [name [type [multiplier [divisor]]]] - char *words[5]; - pluginsd_split_words(value, words, 5); - - char *metric_name = words[0]; - char *dim_name = words[1]; - char *type = words[2]; - char *multipler = words[3]; - char *divisor = words[4]; - - STATSD_APP_CHART_DIM *dim = callocz(sizeof(STATSD_APP_CHART_DIM), 1); - - dim->metric = strdupz(metric_name); - dim->metric_hash = simple_hash(dim->metric); - - dim->name = strdupz((dim_name && *dim_name)?dim_name:metric_name); - dim->multiplier = (multipler && *multipler)?str2l(multipler):1; - dim->divisor = (divisor && *divisor)?str2l(divisor):1; - - if(!type || !*type) type = "last"; - if(!strcmp(type, "events")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS; - else if(!strcmp(type, "last")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_LAST; - else if(!strcmp(type, "min")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_MIN; - else if(!strcmp(type, "max")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_MAX; - else if(!strcmp(type, "sum")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_SUM; - else if(!strcmp(type, "average")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE; - else if(!strcmp(type, "median")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN; - else if(!strcmp(type, "stddev")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV; - else if(!strcmp(type, "percentile")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE; - else { - error("STATSD: invalid type '%s' at line %zu of file '%s/%s'. Using 'last'.", type, line, path, filename); - dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_LAST; - } + char *words[10]; + pluginsd_split_words(value, words, 10); - if(!dim->multiplier) { - error("STATSD: invalid multiplier value '%s' at line %zu of file '%s/%s'. Using 1.", multipler, line, path, filename); - dim->multiplier = 1; - } - if(!dim->divisor) { - error("STATSD: invalid divisor value '%s' at line %zu of file '%s/%s'. Using 1.", divisor, line, path, filename); - dim->divisor = 1; - } + int pattern = 0; + size_t i = 0; + char *metric_name = words[i++]; - // append it to the list of dimension - STATSD_APP_CHART_DIM *tdim; - for(tdim = chart->dimensions; tdim && tdim->next ; tdim = tdim->next) ; - if(!tdim) { - dim->next = chart->dimensions; - chart->dimensions = dim; + if(strcmp(metric_name, "pattern") == 0) { + metric_name = words[i++]; + pattern = 1; } - else { - dim->next = tdim->next; - tdim->next = dim; + + char *dim_name = words[i++]; + char *type = words[i++]; + char *multipler = words[i++]; + char *divisor = words[i++]; + + if(!pattern) { + if(app->dict) { + if(dim_name && *dim_name) { + char *n = dictionary_get(app->dict, dim_name); + if(n) dim_name = n; + } + else { + dim_name = dictionary_get(app->dict, metric_name); + } + } + + if(!dim_name || !*dim_name) + dim_name = metric_name; } - chart->dimensions_count++; - debug(D_STATSD, "Added dimension '%s' to chart '%s' of app '%s', for metric '%s', with type %u, multiplier " COLLECTED_NUMBER_FORMAT ", divisor " COLLECTED_NUMBER_FORMAT, - dim->name, chart->id, app->name, dim->metric, dim->value_type, dim->multiplier, dim->divisor); + STATSD_APP_CHART_DIM *dim = add_dimension_to_app_chart( + app + , chart + , metric_name + , dim_name + , (multipler && *multipler)?str2l(multipler):1 + , (divisor && *divisor)?str2l(divisor):1 + , string2valuetype(type, line, path, filename) + ); + + if(pattern) + dim->metric_pattern = simple_pattern_create(dim->metric, SIMPLE_PATTERN_EXACT); } else { error("STATSD: ignoring line %zu ('%s') of file '%s/%s'. Unknown keyword for the [%s] section.", line, name, path, filename, chart->id); @@ -1248,19 +1342,21 @@ static inline RRDSET *statsd_private_rrdset_create( statsd.private_charts++; RRDSET *st = rrdset_create_custom( - localhost - , type - , id - , name - , family - , context - , title - , units - , priority - , update_every - , chart_type - , memory_mode - , history + localhost // host + , type // type + , id // id + , name // name + , family // family + , context // context + , title // title + , units // units + , "statsd" // plugin + , NULL // module + , priority // priority + , update_every // update every + , chart_type // chart type + , memory_mode // memory mode + , history // history ); rrdset_flag_set(st, RRDSET_FLAG_STORE_FIRST); // rrdset_flag_set(st, RRDSET_FLAG_DEBUG); @@ -1484,6 +1580,22 @@ static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char netdata_mutex_lock(&m->histogram.ext->mutex); + if(unlikely(!m->histogram.ext->zeroed)) { + // reset the metrics + // if we collected anything, they will be updated below + // this ensures that we report zeros if nothing is collected + + m->histogram.ext->last_min = 0; + m->histogram.ext->last_max = 0; + m->last = 0; + m->histogram.ext->last_median = 0; + m->histogram.ext->last_stddev = 0; + m->histogram.ext->last_sum = 0; + m->histogram.ext->last_percentile = 0; + + m->histogram.ext->zeroed = 1; + } + int updated = 0; if(m->count && !m->reset && m->histogram.ext->used > 0) { size_t len = m->histogram.ext->used; @@ -1506,11 +1618,11 @@ static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char debug(D_STATSD, "STATSD %s metric %s: min " COLLECTED_NUMBER_FORMAT ", max " COLLECTED_NUMBER_FORMAT ", last " COLLECTED_NUMBER_FORMAT ", pcent " COLLECTED_NUMBER_FORMAT ", median " COLLECTED_NUMBER_FORMAT ", stddev " COLLECTED_NUMBER_FORMAT ", sum " COLLECTED_NUMBER_FORMAT, dim, m->name, m->histogram.ext->last_min, m->histogram.ext->last_max, m->last, m->histogram.ext->last_percentile, m->histogram.ext->last_median, m->histogram.ext->last_stddev, m->histogram.ext->last_sum); + m->histogram.ext->zeroed = 0; m->reset = 1; updated = 1; } - if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED))) statsd_private_chart_timer_or_histogram(m, dim, family, units); @@ -1540,6 +1652,71 @@ static inline RRD_ALGORITHM statsd_algorithm_for_metric(STATSD_METRIC *m) { } } +static inline void link_metric_to_app_dimension(STATSD_APP *app, STATSD_METRIC *m, STATSD_APP_CHART *chart, STATSD_APP_CHART_DIM *dim) { + if(dim->value_type == STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS) { + dim->value_ptr = &m->events; + dim->algorithm = RRD_ALGORITHM_INCREMENTAL; + } + else if(m->type == STATSD_METRIC_TYPE_HISTOGRAM || m->type == STATSD_METRIC_TYPE_TIMER) { + dim->algorithm = RRD_ALGORITHM_ABSOLUTE; + dim->divisor *= statsd.decimal_detail; + + switch(dim->value_type) { + case STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS: + // will never match - added to avoid warning + break; + + case STATSD_APP_CHART_DIM_VALUE_TYPE_LAST: + case STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE: + dim->value_ptr = &m->last; + break; + + case STATSD_APP_CHART_DIM_VALUE_TYPE_SUM: + dim->value_ptr = &m->histogram.ext->last_sum; + break; + + case STATSD_APP_CHART_DIM_VALUE_TYPE_MIN: + dim->value_ptr = &m->histogram.ext->last_min; + break; + + case STATSD_APP_CHART_DIM_VALUE_TYPE_MAX: + dim->value_ptr = &m->histogram.ext->last_max; + break; + + case STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN: + dim->value_ptr = &m->histogram.ext->last_median; + break; + + case STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE: + dim->value_ptr = &m->histogram.ext->last_percentile; + break; + + case STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV: + dim->value_ptr = &m->histogram.ext->last_stddev; + break; + } + } + else { + if (dim->value_type != STATSD_APP_CHART_DIM_VALUE_TYPE_LAST) + error("STATSD: unsupported value type for dimension '%s' of chart '%s' of app '%s' on metric '%s'", dim->name, chart->id, app->name, m->name); + + dim->value_ptr = &m->last; + dim->algorithm = statsd_algorithm_for_metric(m); + + if(m->type == STATSD_METRIC_TYPE_GAUGE) + dim->divisor *= statsd.decimal_detail; + } + + if(unlikely(chart->st && dim->rd)) { + rrddim_set_algorithm(chart->st, dim->rd, dim->algorithm); + rrddim_set_multiplier(chart->st, dim->rd, dim->multiplier); + rrddim_set_divisor(chart->st, dim->rd, dim->divisor); + } + + chart->dimensions_linked_count++; + debug(D_STATSD, "metric '%s' of type %u linked with app '%s', chart '%s', dimension '%s', algorithm '%s'", m->name, m->type, app->name, chart->id, dim->name, rrd_algorithm_name(dim->algorithm)); +} + static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC *m) { (void)index; @@ -1565,78 +1742,103 @@ static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC // check if there is a chart in this app, willing to get this metric STATSD_APP_CHART *chart; for(chart = app->charts; chart; chart = chart->next) { + STATSD_APP_CHART_DIM *dim; for(dim = chart->dimensions; dim ; dim = dim->next) { - if(!dim->value_ptr && dim->metric_hash == m->hash && !strcmp(dim->metric, m->name)) { - // we have a match - this metric should be linked to this dimension + if(unlikely(dim->metric_pattern)) { + size_t dim_name_len = strlen(dim->name); + size_t wildcarded_len = dim_name_len + strlen(m->name) + 1; + char wildcarded[wildcarded_len]; - if(dim->value_type == STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS) { - dim->value_ptr = &m->events; - dim->algorithm = RRD_ALGORITHM_INCREMENTAL; - } - else if(m->type == STATSD_METRIC_TYPE_HISTOGRAM || m->type == STATSD_METRIC_TYPE_TIMER) { - dim->algorithm = RRD_ALGORITHM_ABSOLUTE; - dim->divisor *= statsd.decimal_detail; - - switch(dim->value_type) { - case STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS: - // will never match - added to avoid warning - break; - - case STATSD_APP_CHART_DIM_VALUE_TYPE_LAST: - case STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE: - dim->value_ptr = &m->last; - break; - - case STATSD_APP_CHART_DIM_VALUE_TYPE_SUM: - dim->value_ptr = &m->histogram.ext->last_sum; - break; - - case STATSD_APP_CHART_DIM_VALUE_TYPE_MIN: - dim->value_ptr = &m->histogram.ext->last_min; - break; - - case STATSD_APP_CHART_DIM_VALUE_TYPE_MAX: - dim->value_ptr = &m->histogram.ext->last_max; - break; - - case STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN: - dim->value_ptr = &m->histogram.ext->last_median; - break; - - case STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE: - dim->value_ptr = &m->histogram.ext->last_percentile; - break; - - case STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV: - dim->value_ptr = &m->histogram.ext->last_stddev; - break; - } - } - else { - if (dim->value_type != STATSD_APP_CHART_DIM_VALUE_TYPE_LAST) - error("STATSD: unsupported value type for dimension '%s' of chart '%s' of app '%s' on metric '%s'", dim->name, chart->id, app->name, m->name); + strcpy(wildcarded, dim->name); + char *ws = &wildcarded[dim_name_len]; - dim->value_ptr = &m->last; - dim->algorithm = statsd_algorithm_for_metric(m); + if(simple_pattern_matches_extract(dim->metric_pattern, m->name, ws, wildcarded_len - dim_name_len)) { - if(m->type == STATSD_METRIC_TYPE_GAUGE) - dim->divisor *= statsd.decimal_detail; - } + char *final_name = NULL; - if(unlikely(chart->st && dim->rd)) { - rrddim_set_algorithm(chart->st, dim->rd, dim->algorithm); - rrddim_set_multiplier(chart->st, dim->rd, dim->multiplier); - rrddim_set_divisor(chart->st, dim->rd, dim->divisor); - } + if(app->dict) { + if(likely(*wildcarded)) { + // use the name of the wildcarded string + final_name = dictionary_get(app->dict, wildcarded); + } + + if(unlikely(!final_name)) { + // use the name of the metric + final_name = dictionary_get(app->dict, m->name); + } + } - chart->dimensions_linked_count++; - debug(D_STATSD, "metric '%s' of type %u linked with app '%s', chart '%s', dimension '%s', algorithm '%s'", m->name, m->type, app->name, chart->id, dim->name, rrd_algorithm_name(dim->algorithm)); + if(unlikely(!final_name)) + final_name = wildcarded; + + add_dimension_to_app_chart( + app + , chart + , m->name + , final_name + , dim->multiplier + , dim->divisor + , dim->value_type + ); + + // the new dimension is appended to the list + // so, it will be matched and linked later too + } + } + else if(!dim->value_ptr && dim->metric_hash == m->hash && !strcmp(dim->metric, m->name)) { + // we have a match - this metric should be linked to this dimension + link_metric_to_app_dimension(app, m, chart, dim); } } + + } + } + } +} + +static inline RRDDIM *statsd_add_dim_to_app_chart(STATSD_APP *app, STATSD_APP_CHART *chart, STATSD_APP_CHART_DIM *dim) { + (void)app; + + // allow the same statsd metric to be added multiple times to the same chart + + STATSD_APP_CHART_DIM *tdim; + size_t count_same_metric = 0, count_same_metric_value_type = 0; + size_t pos_same_metric_value_type = 0; + + for (tdim = chart->dimensions; tdim && tdim->next; tdim = tdim->next) { + if (dim->metric_hash == tdim->metric_hash && !strcmp(dim->metric, tdim->metric)) { + count_same_metric++; + + if(dim->value_type == tdim->value_type) { + count_same_metric_value_type++; + if (tdim == dim) + pos_same_metric_value_type = count_same_metric_value_type; } } } + + if(count_same_metric > 1) { + // the same metric is found multiple times + + size_t len = strlen(dim->metric) + 100; + char metric[ len + 1 ]; + + if(count_same_metric_value_type > 1) { + // the same metric, with the same value type, is added multiple times + snprintfz(metric, len, "%s_%s%zu", dim->metric, valuetype2string(dim->value_type), pos_same_metric_value_type); + } + else { + // the same metric, with different value type is added + snprintfz(metric, len, "%s_%s", dim->metric, valuetype2string(dim->value_type)); + } + + dim->rd = rrddim_add(chart->st, metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm); + return dim->rd; + } + + dim->rd = rrddim_add(chart->st, dim->metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm); + return dim->rd; } static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *chart) { @@ -1644,19 +1846,21 @@ static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *ch if(!chart->st) { chart->st = rrdset_create_custom( - localhost - , app->name - , chart->id - , chart->name - , chart->family - , chart->context - , chart->title - , chart->units - , chart->priority - , statsd.update_every - , chart->chart_type - , app->rrd_memory_mode - , app->rrd_history_entries + localhost // host + , app->name // type + , chart->id // id + , chart->name // name + , chart->family // family + , chart->context // context + , chart->title // title + , chart->units // units + , "statsd" // plugin + , NULL // module + , chart->priority // priority + , statsd.update_every // update every + , chart->chart_type // chart type + , app->rrd_memory_mode // memory mode + , app->rrd_history_entries // history ); rrdset_flag_set(chart->st, RRDSET_FLAG_STORE_FIRST); @@ -1666,12 +1870,14 @@ static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *ch STATSD_APP_CHART_DIM *dim; for(dim = chart->dimensions; dim ;dim = dim->next) { - if(unlikely(!dim->rd)) - dim->rd = rrddim_add(chart->st, dim->name, NULL, dim->multiplier, dim->divisor, dim->algorithm); + if(likely(!dim->metric_pattern)) { + if (unlikely(!dim->rd)) + statsd_add_dim_to_app_chart(app, chart, dim); - if(unlikely(dim->value_ptr)) { - debug(D_STATSD, "updating dimension '%s' (%s) of chart '%s' (%s) for app '%s' with value " COLLECTED_NUMBER_FORMAT, dim->name, dim->rd->id, chart->id, chart->st->id, app->name, *dim->value_ptr); - rrddim_set_by_pointer(chart->st, dim->rd, *dim->value_ptr); + if (unlikely(dim->value_ptr)) { + debug(D_STATSD, "updating dimension '%s' (%s) of chart '%s' (%s) for app '%s' with value " COLLECTED_NUMBER_FORMAT, dim->name, dim->rd->id, chart->id, chart->st->id, app->name, *dim->value_ptr); + rrddim_set_by_pointer(chart->st, dim->rd, *dim->value_ptr); + } } } @@ -1871,6 +2077,8 @@ void *statsd_main(void *ptr) { , NULL , "Metrics in the netdata statsd database" , "metrics" + , "netdata" + , "stats" , 132000 , statsd.update_every , RRDSET_TYPE_STACKED @@ -1890,6 +2098,8 @@ void *statsd_main(void *ptr) { , NULL , "Events processed by the netdata statsd server" , "events/s" + , "netdata" + , "stats" , 132001 , statsd.update_every , RRDSET_TYPE_STACKED @@ -1911,6 +2121,8 @@ void *statsd_main(void *ptr) { , NULL , "Read operations made by the netdata statsd server" , "reads/s" + , "netdata" + , "stats" , 132002 , statsd.update_every , RRDSET_TYPE_STACKED @@ -1926,6 +2138,8 @@ void *statsd_main(void *ptr) { , NULL , "Bytes read by the netdata statsd server" , "kilobits/s" + , "netdata" + , "stats" , 132003 , statsd.update_every , RRDSET_TYPE_STACKED @@ -1941,6 +2155,8 @@ void *statsd_main(void *ptr) { , NULL , "Network packets processed by the netdata statsd server" , "packets/s" + , "netdata" + , "stats" , 132004 , statsd.update_every , RRDSET_TYPE_STACKED @@ -1956,6 +2172,8 @@ void *statsd_main(void *ptr) { , NULL , "Private metric charts created by the netdata statsd server" , "charts" + , "netdata" + , "stats" , 132010 , statsd.update_every , RRDSET_TYPE_AREA diff --git a/src/storage_number.c b/src/storage_number.c index 05494120..3fd22a41 100644 --- a/src/storage_number.c +++ b/src/storage_number.c @@ -39,7 +39,9 @@ storage_number pack_storage_number(calculated_number value, uint32_t flags) r += (1 << 30) + (m << 27); // the multiplier m if(n > (calculated_number)0x00ffffff) { + #ifdef NETDATA_INTERNAL_CHECKS error("Number " CALCULATED_NUMBER_FORMAT " is too big.", value); + #endif r += 0x00ffffff; return r; } diff --git a/src/storage_number.h b/src/storage_number.h index 3c1b6bab..616ff881 100644 --- a/src/storage_number.h +++ b/src/storage_number.h @@ -17,6 +17,9 @@ typedef long double collected_number; #define calculated_number_llrint(x) llrintl(x) #define calculated_number_round(x) roundl(x) #define calculated_number_fabs(x) fabsl(x) +#define calculated_number_epsilon (calculated_number)0.0000001 + +#define calculated_number_equal(a, b) (calculated_number_fabs((a) - (b)) < calculated_number_epsilon) typedef uint32_t storage_number; #define STORAGE_NUMBER_FORMAT "%u" diff --git a/src/sys_devices_system_edac_mc.c b/src/sys_devices_system_edac_mc.c index 7ec98943..9eac8a12 100644 --- a/src/sys_devices_system_edac_mc.c +++ b/src/sys_devices_system_edac_mc.c @@ -140,6 +140,8 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { , NULL , "ECC Memory Correctable Errors" , "errors" + , "proc" + , "/sys/devices/system/edac/mc" , 6600 , update_every , RRDSET_TYPE_LINE @@ -176,6 +178,8 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { , NULL , "ECC Memory Uncorrectable Errors" , "errors" + , "proc" + , "/sys/devices/system/edac/mc" , 6610 , update_every , RRDSET_TYPE_LINE diff --git a/src/sys_devices_system_node.c b/src/sys_devices_system_node.c index a7690e7b..86d55b29 100644 --- a/src/sys_devices_system_node.c +++ b/src/sys_devices_system_node.c @@ -105,6 +105,8 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) { , NULL , "NUMA events" , "events/s" + , "proc" + , "/sys/devices/system/node" , 1000 , update_every , RRDSET_TYPE_LINE diff --git a/src/sys_fs_cgroup.c b/src/sys_fs_cgroup.c index c047547e..946831af 100644 --- a/src/sys_fs_cgroup.c +++ b/src/sys_fs_cgroup.c @@ -151,7 +151,8 @@ void read_cgroup_plugin_configuration() { // ---------------------------------------------------------------- " !*/init.scope " // ignore init.scope - " *.scope " // we need all *.scope for sure + " !/system.slice/run-*.scope " // ignore system.slice/run-XXXX.scope + " *.scope " // we need all other *.scope for sure // ---------------------------------------------------------------- @@ -180,6 +181,7 @@ void read_cgroup_plugin_configuration() { config_get("plugin:cgroups", "search for cgroups in subpaths matching", " !*/init.scope " // ignore init.scope " !*-qemu " // #345 + " !*.libvirt-qemu " // #3010 " !/init.scope " " !/system " " !/systemd " @@ -201,6 +203,9 @@ void read_cgroup_plugin_configuration() { " *docker* " " *lxc* " " *qemu* " + " *.libvirt-qemu " // #3010 + " !*/vcpu* " // libvirtd adds these sub-cgroups + " !*/emulator* " // libvirtd adds these sub-cgroups " !/ " " !*.mount " " !*.partition " @@ -762,7 +767,7 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) { } if(!*t) { - error("CGROUP: empty container interface returned by script"); + error("CGROUP: empty guest interface returned by script"); continue; } @@ -1447,6 +1452,8 @@ void update_systemd_services_charts( , "services.cpu" , title , "%" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES , update_every , RRDSET_TYPE_STACKED @@ -1469,6 +1476,8 @@ void update_systemd_services_charts( , (cgroup_used_memory_without_cache) ? "Systemd Services Used Memory without Cache" : "Systemd Services Used Memory" , "MB" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 10 , update_every , RRDSET_TYPE_STACKED @@ -1490,6 +1499,8 @@ void update_systemd_services_charts( , "services.mem_rss" , "Systemd Services RSS Memory" , "MB" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 20 , update_every , RRDSET_TYPE_STACKED @@ -1509,6 +1520,8 @@ void update_systemd_services_charts( , "services.mem_mapped" , "Systemd Services Mapped Memory" , "MB" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 30 , update_every , RRDSET_TYPE_STACKED @@ -1528,6 +1541,8 @@ void update_systemd_services_charts( , "services.mem_cache" , "Systemd Services Cache Memory" , "MB" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 40 , update_every , RRDSET_TYPE_STACKED @@ -1547,6 +1562,8 @@ void update_systemd_services_charts( , "services.mem_writeback" , "Systemd Services Writeback Memory" , "MB" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 50 , update_every , RRDSET_TYPE_STACKED @@ -1566,6 +1583,8 @@ void update_systemd_services_charts( , "services.mem_pgfault" , "Systemd Services Memory Minor Page Faults" , "MB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 60 , update_every , RRDSET_TYPE_STACKED @@ -1584,6 +1603,8 @@ void update_systemd_services_charts( , "services.mem_pgmajfault" , "Systemd Services Memory Major Page Faults" , "MB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 70 , update_every , RRDSET_TYPE_STACKED @@ -1603,6 +1624,8 @@ void update_systemd_services_charts( , "services.mem_pgpgin" , "Systemd Services Memory Charging Activity" , "MB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 80 , update_every , RRDSET_TYPE_STACKED @@ -1622,6 +1645,8 @@ void update_systemd_services_charts( , "services.mem_pgpgout" , "Systemd Services Memory Uncharging Activity" , "MB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 90 , update_every , RRDSET_TYPE_STACKED @@ -1643,6 +1668,8 @@ void update_systemd_services_charts( , "services.mem_failcnt" , "Systemd Services Memory Limit Failures" , "MB" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 110 , update_every , RRDSET_TYPE_STACKED @@ -1664,6 +1691,8 @@ void update_systemd_services_charts( , "services.swap_usage" , "Systemd Services Swap Memory Used" , "MB" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 100 , update_every , RRDSET_TYPE_STACKED @@ -1685,6 +1714,8 @@ void update_systemd_services_charts( , "services.io_read" , "Systemd Services Disk Read Bandwidth" , "KB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 120 , update_every , RRDSET_TYPE_STACKED @@ -1704,6 +1735,8 @@ void update_systemd_services_charts( , "services.io_write" , "Systemd Services Disk Write Bandwidth" , "KB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 130 , update_every , RRDSET_TYPE_STACKED @@ -1725,6 +1758,8 @@ void update_systemd_services_charts( , "services.io_ops_read" , "Systemd Services Disk Read Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 140 , update_every , RRDSET_TYPE_STACKED @@ -1744,6 +1779,8 @@ void update_systemd_services_charts( , "services.io_ops_write" , "Systemd Services Disk Write Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 150 , update_every , RRDSET_TYPE_STACKED @@ -1765,6 +1802,8 @@ void update_systemd_services_charts( , "services.throttle_io_read" , "Systemd Services Throttle Disk Read Bandwidth" , "KB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 160 , update_every , RRDSET_TYPE_STACKED @@ -1784,6 +1823,8 @@ void update_systemd_services_charts( , "services.throttle_io_write" , "Systemd Services Throttle Disk Write Bandwidth" , "KB/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 170 , update_every , RRDSET_TYPE_STACKED @@ -1805,6 +1846,8 @@ void update_systemd_services_charts( , "services.throttle_io_ops_read" , "Systemd Services Throttle Disk Read Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 180 , update_every , RRDSET_TYPE_STACKED @@ -1824,6 +1867,8 @@ void update_systemd_services_charts( , "services.throttle_io_ops_write" , "Systemd Services Throttle Disk Write Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 190 , update_every , RRDSET_TYPE_STACKED @@ -1845,6 +1890,8 @@ void update_systemd_services_charts( , "services.queued_io_ops_read" , "Systemd Services Queued Disk Read Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 200 , update_every , RRDSET_TYPE_STACKED @@ -1864,6 +1911,8 @@ void update_systemd_services_charts( , "services.queued_io_ops_write" , "Systemd Services Queued Disk Write Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 210 , update_every , RRDSET_TYPE_STACKED @@ -1885,6 +1934,8 @@ void update_systemd_services_charts( , "services.merged_io_ops_read" , "Systemd Services Merged Disk Read Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 220 , update_every , RRDSET_TYPE_STACKED @@ -1904,6 +1955,8 @@ void update_systemd_services_charts( , "services.merged_io_ops_write" , "Systemd Services Merged Disk Write Operations" , "operations/s" + , "cgroup" + , "systemd" , CHART_PRIORITY_SYSTEMD_SERVICES + 230 , update_every , RRDSET_TYPE_STACKED @@ -2184,6 +2237,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.cpu" , title , "%" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS , update_every , RRDSET_TYPE_STACKED @@ -2215,6 +2270,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.cpu_per_core" , title , "%" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 100 , update_every , RRDSET_TYPE_STACKED @@ -2247,6 +2304,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem" , title , "MB" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 210 , update_every , RRDSET_TYPE_STACKED @@ -2285,6 +2344,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.writeback" , title , "MB" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 300 , update_every , RRDSET_TYPE_AREA @@ -2315,6 +2376,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem_activity" , title , "MB/s" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 400 , update_every , RRDSET_TYPE_LINE @@ -2341,6 +2404,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.pgfaults" , title , "MB/s" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 500 , update_every , RRDSET_TYPE_LINE @@ -2369,6 +2434,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem_usage" , title , "MB" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 200 , update_every , RRDSET_TYPE_STACKED @@ -2397,6 +2464,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem_failcnt" , title , "count" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 250 , update_every , RRDSET_TYPE_LINE @@ -2423,6 +2492,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.io" , title , "KB/s" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 1200 , update_every , RRDSET_TYPE_AREA @@ -2451,6 +2522,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.serviced_ops" , title , "operations/s" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 1200 , update_every , RRDSET_TYPE_LINE @@ -2479,6 +2552,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.throttle_io" , title , "KB/s" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 1200 , update_every , RRDSET_TYPE_AREA @@ -2507,6 +2582,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.throttle_serviced_ops" , title , "operations/s" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 1200 , update_every , RRDSET_TYPE_LINE @@ -2535,6 +2612,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.queued_ops" , title , "operations" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 2000 , update_every , RRDSET_TYPE_LINE @@ -2563,6 +2642,8 @@ void update_cgroup_charts(int update_every) { , "cgroup.merged_ops" , title , "operations/s" + , "cgroup" + , "default" , CHART_PRIORITY_CONTAINERS + 2100 , update_every , RRDSET_TYPE_LINE @@ -2650,6 +2731,8 @@ void *cgroups_main(void *ptr) { , NULL , "NetData CGroups Plugin CPU usage" , "milliseconds/s" + , "cgroup" + , "stats" , 132000 , cgroup_update_every , RRDSET_TYPE_STACKED diff --git a/src/sys_kernel_mm_ksm.c b/src/sys_kernel_mm_ksm.c index 6b04ef28..356315be 100644 --- a/src/sys_kernel_mm_ksm.c +++ b/src/sys_kernel_mm_ksm.c @@ -102,6 +102,8 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { , NULL , "Kernel Same Page Merging" , "MB" + , "proc" + , "/sys/kernel/mm/ksm" , 5000 , update_every , RRDSET_TYPE_AREA @@ -140,6 +142,8 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { , NULL , "Kernel Same Page Merging Savings" , "MB" + , "proc" + , "/sys/kernel/mm/ksm" , 5001 , update_every , RRDSET_TYPE_AREA @@ -172,6 +176,8 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { , NULL , "Kernel Same Page Merging Effectiveness" , "percentage" + , "proc" + , "/sys/kernel/mm/ksm" , 5002 , update_every , RRDSET_TYPE_LINE diff --git a/src/unit_test.c b/src/unit_test.c index 3c963211..821063ba 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -1,5 +1,62 @@ #include "common.h" +static int check_rrdcalc_comparisons(void) { + RRDCALC_STATUS a, b; + + // make sure calloc() sets the status to UNINITIALIZED + memset(&a, 0, sizeof(RRDCALC_STATUS)); + if(a != RRDCALC_STATUS_UNINITIALIZED) { + fprintf(stderr, "%s is not zero.\n", rrdcalc_status2string(RRDCALC_STATUS_UNINITIALIZED)); + return 1; + } + + a = RRDCALC_STATUS_REMOVED; + b = RRDCALC_STATUS_UNDEFINED; + if(!(a < b)) { + fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b)); + return 1; + } + + a = RRDCALC_STATUS_UNDEFINED; + b = RRDCALC_STATUS_UNINITIALIZED; + if(!(a < b)) { + fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b)); + return 1; + } + + a = RRDCALC_STATUS_UNINITIALIZED; + b = RRDCALC_STATUS_CLEAR; + if(!(a < b)) { + fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b)); + return 1; + } + + a = RRDCALC_STATUS_CLEAR; + b = RRDCALC_STATUS_RAISED; + if(!(a < b)) { + fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b)); + return 1; + } + + a = RRDCALC_STATUS_RAISED; + b = RRDCALC_STATUS_WARNING; + if(!(a < b)) { + fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b)); + return 1; + } + + a = RRDCALC_STATUS_WARNING; + b = RRDCALC_STATUS_CRITICAL; + if(!(a < b)) { + fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b)); + return 1; + } + + fprintf(stderr, "RRDCALC_STATUSes are sortable.\n"); + + return 0; +} + int check_storage_number(calculated_number n, int debug) { char buffer[100]; uint32_t flags = SN_EXISTS; @@ -973,7 +1030,7 @@ int run_test(struct test *test) snprintfz(name, 100, "unittest-%s", test->name); // create the chart - RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1 + RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", "unittest", NULL, 1 , test->update_every, RRDSET_TYPE_LINE); RRDDIM *rd = rrddim_add(st, "dim1", NULL, test->multiplier, test->divisor, test->algorithm); @@ -1062,7 +1119,7 @@ int run_test(struct test *test) static int test_variable_renames(void) { fprintf(stderr, "Creating chart\n"); - RRDSET *st = rrdset_create_localhost("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE); + RRDSET *st = rrdset_create_localhost("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", "unittest", NULL, 1, 1, RRDSET_TYPE_LINE); fprintf(stderr, "Created chart with id '%s', name '%s'\n", st->id, st->name); fprintf(stderr, "Creating dimension DIM1\n"); @@ -1106,6 +1163,9 @@ static int test_variable_renames(void) { int run_all_mockup_tests(void) { + if(check_rrdcalc_comparisons()) + return 1; + if(!test_variable_renames()) return 1; @@ -1182,7 +1242,7 @@ int unit_test(long delay, long shift) int do_abst = 0; int do_absi = 0; - RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1 + RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", "unittest", NULL, 1, 1 , RRDSET_TYPE_LINE); rrdset_flag_set(st, RRDSET_FLAG_DEBUG); diff --git a/src/web_api_v1.c b/src/web_api_v1.c index 9514f8db..02c6b0ed 100644 --- a/src/web_api_v1.c +++ b/src/web_api_v1.c @@ -1,20 +1,105 @@ #include "common.h" -inline int web_client_api_request_v1_data_group(char *name, int def) { - if(!strcmp(name, "average")) - return GROUP_AVERAGE; - - else if(!strcmp(name, "min")) - return GROUP_MIN; - - else if(!strcmp(name, "max")) - return GROUP_MAX; +static struct { + const char *name; + uint32_t hash; + int value; +} api_v1_data_groups[] = { + { "average" , 0 , GROUP_AVERAGE} + , {"min" , 0 , GROUP_MIN} + , {"max" , 0 , GROUP_MAX} + , {"sum" , 0 , GROUP_SUM} + , {"incremental_sum", 0 , GROUP_INCREMENTAL_SUM} + , {"incremental-sum", 0 , GROUP_INCREMENTAL_SUM} + , { NULL, 0, 0} +}; + +static struct { + const char *name; + uint32_t hash; + uint32_t value; +} api_v1_data_options[] = { + { "nonzero" , 0 , RRDR_OPTION_NONZERO} + , {"flip" , 0 , RRDR_OPTION_REVERSED} + , {"reversed" , 0 , RRDR_OPTION_REVERSED} + , {"reverse" , 0 , RRDR_OPTION_REVERSED} + , {"jsonwrap" , 0 , RRDR_OPTION_JSON_WRAP} + , {"min2max" , 0 , RRDR_OPTION_MIN2MAX} + , {"ms" , 0 , RRDR_OPTION_MILLISECONDS} + , {"milliseconds" , 0 , RRDR_OPTION_MILLISECONDS} + , {"abs" , 0 , RRDR_OPTION_ABSOLUTE} + , {"absolute" , 0 , RRDR_OPTION_ABSOLUTE} + , {"absolute_sum" , 0 , RRDR_OPTION_ABSOLUTE} + , {"absolute-sum" , 0 , RRDR_OPTION_ABSOLUTE} + , {"display_absolute", 0 , RRDR_OPTION_DISPLAY_ABS} + , {"display-absolute", 0 , RRDR_OPTION_DISPLAY_ABS} + , {"seconds" , 0 , RRDR_OPTION_SECONDS} + , {"null2zero" , 0 , RRDR_OPTION_NULL2ZERO} + , {"objectrows" , 0 , RRDR_OPTION_OBJECTSROWS} + , {"google_json" , 0 , RRDR_OPTION_GOOGLE_JSON} + , {"google-json" , 0 , RRDR_OPTION_GOOGLE_JSON} + , {"percentage" , 0 , RRDR_OPTION_PERCENTAGE} + , {"unaligned" , 0 , RRDR_OPTION_NOT_ALIGNED} + , { NULL, 0, 0} +}; + +static struct { + const char *name; + uint32_t hash; + uint32_t value; +} api_v1_data_formats[] = { + { DATASOURCE_FORMAT_DATATABLE_JSON , 0 , DATASOURCE_DATATABLE_JSON} + , {DATASOURCE_FORMAT_DATATABLE_JSONP, 0 , DATASOURCE_DATATABLE_JSONP} + , {DATASOURCE_FORMAT_JSON , 0 , DATASOURCE_JSON} + , {DATASOURCE_FORMAT_JSONP , 0 , DATASOURCE_JSONP} + , {DATASOURCE_FORMAT_SSV , 0 , DATASOURCE_SSV} + , {DATASOURCE_FORMAT_CSV , 0 , DATASOURCE_CSV} + , {DATASOURCE_FORMAT_TSV , 0 , DATASOURCE_TSV} + , {"tsv-excel" , 0 , DATASOURCE_TSV} + , {DATASOURCE_FORMAT_HTML , 0 , DATASOURCE_HTML} + , {DATASOURCE_FORMAT_JS_ARRAY , 0 , DATASOURCE_JS_ARRAY} + , {DATASOURCE_FORMAT_SSV_COMMA , 0 , DATASOURCE_SSV_COMMA} + , {DATASOURCE_FORMAT_CSV_JSON_ARRAY , 0 , DATASOURCE_CSV_JSON_ARRAY} + , { NULL, 0, 0} +}; + +static struct { + const char *name; + uint32_t hash; + uint32_t value; +} api_v1_data_google_formats[] = { + // this is not error - when google requests json, it expects javascript + // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source#responseformat + { "json" , 0 , DATASOURCE_DATATABLE_JSONP} + , {"html" , 0 , DATASOURCE_HTML} + , {"csv" , 0 , DATASOURCE_CSV} + , {"tsv-excel", 0 , DATASOURCE_TSV} + , { NULL, 0, 0} +}; + +void web_client_api_v1_init(void) { + int i; + + for(i = 0; api_v1_data_groups[i].name ; i++) + api_v1_data_groups[i].hash = simple_hash(api_v1_data_groups[i].name); + + for(i = 0; api_v1_data_options[i].name ; i++) + api_v1_data_options[i].hash = simple_hash(api_v1_data_options[i].name); + + for(i = 0; api_v1_data_formats[i].name ; i++) + api_v1_data_formats[i].hash = simple_hash(api_v1_data_formats[i].name); + + for(i = 0; api_v1_data_google_formats[i].name ; i++) + api_v1_data_google_formats[i].hash = simple_hash(api_v1_data_google_formats[i].name); +} - else if(!strcmp(name, "sum")) - return GROUP_SUM; +inline int web_client_api_request_v1_data_group(char *name, int def) { + int i; - else if(!strcmp(name, "incremental-sum")) - return GROUP_INCREMENTAL_SUM; + uint32_t hash = simple_hash(name); + for(i = 0; api_v1_data_groups[i].name ; i++) + if(unlikely(hash == api_v1_data_groups[i].hash && !strcmp(name, api_v1_data_groups[i].name))) + return api_v1_data_groups[i].value; return def; } @@ -26,84 +111,41 @@ inline uint32_t web_client_api_request_v1_data_options(char *o) { while(o && *o && (tok = mystrsep(&o, ", |"))) { if(!*tok) continue; - if(!strcmp(tok, "nonzero")) - ret |= RRDR_OPTION_NONZERO; - else if(!strcmp(tok, "flip") || !strcmp(tok, "reversed") || !strcmp(tok, "reverse")) - ret |= RRDR_OPTION_REVERSED; - else if(!strcmp(tok, "jsonwrap")) - ret |= RRDR_OPTION_JSON_WRAP; - else if(!strcmp(tok, "min2max")) - ret |= RRDR_OPTION_MIN2MAX; - else if(!strcmp(tok, "ms") || !strcmp(tok, "milliseconds")) - ret |= RRDR_OPTION_MILLISECONDS; - else if(!strcmp(tok, "abs") || !strcmp(tok, "absolute") || !strcmp(tok, "absolute_sum") || !strcmp(tok, "absolute-sum")) - ret |= RRDR_OPTION_ABSOLUTE; - else if(!strcmp(tok, "seconds")) - ret |= RRDR_OPTION_SECONDS; - else if(!strcmp(tok, "null2zero")) - ret |= RRDR_OPTION_NULL2ZERO; - else if(!strcmp(tok, "objectrows")) - ret |= RRDR_OPTION_OBJECTSROWS; - else if(!strcmp(tok, "google_json")) - ret |= RRDR_OPTION_GOOGLE_JSON; - else if(!strcmp(tok, "percentage")) - ret |= RRDR_OPTION_PERCENTAGE; - else if(!strcmp(tok, "unaligned")) - ret |= RRDR_OPTION_NOT_ALIGNED; + uint32_t hash = simple_hash(tok); + int i; + for(i = 0; api_v1_data_options[i].name ; i++) { + if (unlikely(hash == api_v1_data_options[i].hash && !strcmp(tok, api_v1_data_options[i].name))) { + ret |= api_v1_data_options[i].value; + break; + } + } } return ret; } inline uint32_t web_client_api_request_v1_data_format(char *name) { - if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSON)) // datatable - return DATASOURCE_DATATABLE_JSON; - - else if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSONP)) // datasource - return DATASOURCE_DATATABLE_JSONP; - - else if(!strcmp(name, DATASOURCE_FORMAT_JSON)) // json - return DATASOURCE_JSON; - - else if(!strcmp(name, DATASOURCE_FORMAT_JSONP)) // jsonp - return DATASOURCE_JSONP; - - else if(!strcmp(name, DATASOURCE_FORMAT_SSV)) // ssv - return DATASOURCE_SSV; - - else if(!strcmp(name, DATASOURCE_FORMAT_CSV)) // csv - return DATASOURCE_CSV; - - else if(!strcmp(name, DATASOURCE_FORMAT_TSV) || !strcmp(name, "tsv-excel")) // tsv - return DATASOURCE_TSV; - - else if(!strcmp(name, DATASOURCE_FORMAT_HTML)) // html - return DATASOURCE_HTML; - - else if(!strcmp(name, DATASOURCE_FORMAT_JS_ARRAY)) // array - return DATASOURCE_JS_ARRAY; + uint32_t hash = simple_hash(name); + int i; - else if(!strcmp(name, DATASOURCE_FORMAT_SSV_COMMA)) // ssvcomma - return DATASOURCE_SSV_COMMA; - - else if(!strcmp(name, DATASOURCE_FORMAT_CSV_JSON_ARRAY)) // csvjsonarray - return DATASOURCE_CSV_JSON_ARRAY; + for(i = 0; api_v1_data_formats[i].name ; i++) { + if (unlikely(hash == api_v1_data_formats[i].hash && !strcmp(name, api_v1_data_formats[i].name))) { + return api_v1_data_formats[i].value; + } + } return DATASOURCE_JSON; } inline uint32_t web_client_api_request_v1_data_google_format(char *name) { - if(!strcmp(name, "json")) - return DATASOURCE_DATATABLE_JSONP; - - else if(!strcmp(name, "html")) - return DATASOURCE_HTML; + uint32_t hash = simple_hash(name); + int i; - else if(!strcmp(name, "csv")) - return DATASOURCE_CSV; - - else if(!strcmp(name, "tsv-excel")) - return DATASOURCE_TSV; + for(i = 0; api_v1_data_google_formats[i].name ; i++) { + if (unlikely(hash == api_v1_data_google_formats[i].hash && !strcmp(name, api_v1_data_google_formats[i].name))) { + return api_v1_data_google_formats[i].value; + } + } return DATASOURCE_JSON; } @@ -371,7 +413,7 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u if(!st) st = rrdset_find_byname(host, chart); if(!st) { buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1); + buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, 0); ret = 200; goto cleanup; } @@ -382,7 +424,7 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u rc = rrdcalc_find(st, alarm); if (!rc) { buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1); + buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, 0); ret = 200; goto cleanup; } @@ -498,7 +540,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u units, label_color, value_color, - precision); + precision, + options + ); ret = 200; } else { @@ -532,7 +576,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u units, label_color, value_color, - precision); + precision, + options + ); } cleanup: @@ -816,55 +862,65 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client * #endif /* NETDATA_INTERNAL_CHECKS */ } - if(respect_web_browser_do_not_track_policy && web_client_has_donottrack(w)) { + if(unlikely(respect_web_browser_do_not_track_policy && web_client_has_donottrack(w))) { buffer_flush(w->response.data); buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work."); return 400; } - if(action == 'A' && (!machine_guid || !machine_url || !url_name)) { - error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Access request."); - return 400; - } - else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) { - error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Delete request."); - return 400; + if(unlikely(action == 'H')) { + // HELLO request, dashboard ACL + if(unlikely(!web_client_can_access_dashboard(w))) + return web_client_permission_denied(w); } - else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) { - error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Search request."); - return 400; - } - else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) { - error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Switch request."); - return 400; + else { + // everything else, registry ACL + if(unlikely(!web_client_can_access_registry(w))) + return web_client_permission_denied(w); } switch(action) { case 'A': + if(unlikely(!machine_guid || !machine_url || !url_name)) { + error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", machine_guid ? machine_guid : "UNSET", machine_url ? machine_url : "UNSET", url_name ? url_name : "UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Access request."); + return 400; + } + web_client_enable_tracking_required(w); return registry_request_access_json(host, w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec()); case 'D': + if(unlikely(!machine_guid || !machine_url || !delete_url)) { + error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Delete request."); + return 400; + } + web_client_enable_tracking_required(w); return registry_request_delete_json(host, w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec()); case 'S': + if(unlikely(!machine_guid || !machine_url || !search_machine_guid)) { + error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Search request."); + return 400; + } + web_client_enable_tracking_required(w); return registry_request_search_json(host, w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec()); case 'W': + if(unlikely(!machine_guid || !machine_url || !to_person_guid)) { + error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Switch request."); + return 400; + } + web_client_enable_tracking_required(w); return registry_request_switch_json(host, w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec()); @@ -878,19 +934,40 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client * } } +static struct api_command { + const char *command; + uint32_t hash; + WEB_CLIENT_ACL acl; + int (*callback)(RRDHOST *host, struct web_client *w, char *url); +} api_commands[] = { + { "data", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_data }, + { "chart", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_chart }, + { "charts", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_charts }, + + // registry checks the ACL by itself, so we allow everything + { "registry", 0, WEB_CLIENT_ACL_NOCHECK, web_client_api_request_v1_registry }, + + // badges can be fetched with both dashboard and badge permissions + { "badge.svg", 0, WEB_CLIENT_ACL_DASHBOARD|WEB_CLIENT_ACL_BADGE, web_client_api_request_v1_badge }, + + { "alarms", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarms }, + { "alarm_log", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_log }, + { "alarm_variables", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_variables }, + { "allmetrics", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_allmetrics }, + + // terminator + { NULL, 0, WEB_CLIENT_ACL_NONE, NULL }, +}; + inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url) { - static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0, hash_alarm_log = 0, hash_alarm_variables = 0, hash_raw = 0; + static int initialized = 0; + int i; + + if(unlikely(initialized == 0)) { + initialized = 1; - if(unlikely(hash_data == 0)) { - hash_data = simple_hash("data"); - hash_chart = simple_hash("chart"); - hash_charts = simple_hash("charts"); - hash_registry = simple_hash("registry"); - hash_badge = simple_hash("badge.svg"); - hash_alarms = simple_hash("alarms"); - hash_alarm_log = simple_hash("alarm_log"); - hash_alarm_variables = simple_hash("alarm_variables"); - hash_raw = simple_hash("allmetrics"); + for(i = 0; api_commands[i].command ; i++) + api_commands[i].hash = simple_hash(api_commands[i].command); } // get the command @@ -899,39 +976,19 @@ inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char * debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok); uint32_t hash = simple_hash(tok); - if(hash == hash_data && !strcmp(tok, "data")) - return web_client_api_request_v1_data(host, w, url); - - else if(hash == hash_chart && !strcmp(tok, "chart")) - return web_client_api_request_v1_chart(host, w, url); - - else if(hash == hash_charts && !strcmp(tok, "charts")) - return web_client_api_request_v1_charts(host, w, url); - - else if(hash == hash_registry && !strcmp(tok, "registry")) - return web_client_api_request_v1_registry(host, w, url); - - else if(hash == hash_badge && !strcmp(tok, "badge.svg")) - return web_client_api_request_v1_badge(host, w, url); - - else if(hash == hash_alarms && !strcmp(tok, "alarms")) - return web_client_api_request_v1_alarms(host, w, url); - - else if(hash == hash_alarm_log && !strcmp(tok, "alarm_log")) - return web_client_api_request_v1_alarm_log(host, w, url); + for(i = 0; api_commands[i].command ;i++) { + if(unlikely(hash == api_commands[i].hash && !strcmp(tok, api_commands[i].command))) { + if(unlikely(api_commands[i].acl != WEB_CLIENT_ACL_NOCHECK) && !(w->acl & api_commands[i].acl)) + return web_client_permission_denied(w); - else if(hash == hash_alarm_variables && !strcmp(tok, "alarm_variables")) - return web_client_api_request_v1_alarm_variables(host, w, url); - - else if(hash == hash_raw && !strcmp(tok, "allmetrics")) - return web_client_api_request_v1_allmetrics(host, w, url); - - else { - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Unsupported v1 API command: "); - buffer_strcat_htmlescape(w->response.data, tok); - return 404; + return api_commands[i].callback(host, w, url); + } } + + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Unsupported v1 API command: "); + buffer_strcat_htmlescape(w->response.data, tok); + return 404; } else { buffer_flush(w->response.data); diff --git a/src/web_api_v1.h b/src/web_api_v1.h index e980edb1..6f4de1ab 100644 --- a/src/web_api_v1.h +++ b/src/web_api_v1.h @@ -18,4 +18,6 @@ extern int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c extern int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url); extern int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url); +extern void web_client_api_v1_init(void); + #endif //NETDATA_WEB_API_V1_H diff --git a/src/web_buffer_svg.c b/src/web_buffer_svg.c index 287bbd6b..25128bd3 100644 --- a/src/web_buffer_svg.c +++ b/src/web_buffer_svg.c @@ -382,7 +382,7 @@ static inline char *format_value_with_precision_and_unit(char *value_string, siz calculated_number abs = value; if(isless(value, 0)) { lstop = 1; - abs = -value; + abs = calculated_number_fabs(value); } if(isgreaterequal(abs, 1000)) { @@ -610,16 +610,22 @@ static inline const char *color_map(const char *color) { return color; } +typedef enum color_comparison { + COLOR_COMPARE_EQUAL, + COLOR_COMPARE_NOTEQUAL, + COLOR_COMPARE_LESS, + COLOR_COMPARE_LESSEQUAL, + COLOR_COMPARE_GREATER, + COLOR_COMPARE_GREATEREQUAL, +} BADGE_COLOR_COMPARISON; + static inline void calc_colorz(const char *color, char *final, size_t len, calculated_number value) { - int value_is_null = 0; - if(isnan(value) || isinf(value)) { - value = 0.0; - value_is_null = 1; - } + if(isnan(value) || isinf(value)) + value = NAN; char color_buffer[256 + 1] = ""; char value_buffer[256 + 1] = ""; - char comparison = '>'; + BADGE_COLOR_COMPARISON comparison = COLOR_COMPARE_GREATER; // example input: // color<max|color>min|color:null... @@ -633,8 +639,15 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu while(*t && *t != '|') { switch(*t) { + case '!': + if(t[1] == '=') t++; + comparison = COLOR_COMPARE_NOTEQUAL; + dv = value_buffer; + break; + + case '=': case ':': - comparison = '='; + comparison = COLOR_COMPARE_EQUAL; dv = value_buffer; break; @@ -642,11 +655,11 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu case ')': case '>': if(t[1] == '=') { - comparison = ')'; + comparison = COLOR_COMPARE_GREATEREQUAL; t++; } else - comparison = '>'; + comparison = COLOR_COMPARE_GREATER; dv = value_buffer; break; @@ -654,11 +667,15 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu case '(': case '<': if(t[1] == '=') { - comparison = '('; + comparison = COLOR_COMPARE_LESSEQUAL; + t++; + } + else if(t[1] == '>' || t[1] == ')' || t[1] == '}') { + comparison = COLOR_COMPARE_NOTEQUAL; t++; } else - comparison = '<'; + comparison = COLOR_COMPARE_LESS; dv = value_buffer; break; @@ -689,19 +706,28 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu *dc = '\0'; if(dv) { *dv = '\0'; + calculated_number v; - if(value_is_null) { - if(!*value_buffer || !strcmp(value_buffer, "null")) - break; + if(!*value_buffer || !strcmp(value_buffer, "null")) { + v = NAN; } else { - calculated_number v = str2l(value_buffer); + v = str2l(value_buffer); + if(isnan(v) || isinf(v)) + v = NAN; + } - if(comparison == '<' && value < v) break; - else if(comparison == '(' && value <= v) break; - else if(comparison == '>' && value > v) break; - else if(comparison == ')' && value >= v) break; - else if(comparison == '=' && value == v) break; + if(unlikely(isnan(value) || isnan(v))) { + if(isnan(value) && isnan(v)) + break; + } + else { + if (unlikely(comparison == COLOR_COMPARE_LESS && isless(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_LESSEQUAL && islessequal(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_GREATER && isgreater(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_GREATEREQUAL && isgreaterequal(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_EQUAL && !islessgreater(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_NOTEQUAL && islessgreater(value, v))) break; } } else @@ -726,7 +752,7 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu // colors #define COLOR_STRING_SIZE 100 -void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision) { +void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, uint32_t options) { char label_buffer[LABEL_STRING_SIZE + 1] , value_color_buffer[COLOR_STRING_SIZE + 1] , value_string[VALUE_STRING_SIZE + 1] @@ -744,7 +770,7 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch value_color = (isnan(value) || isinf(value))?"#999":"#4c1"; calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value); - format_value_and_unit(value_string, VALUE_STRING_SIZE, value, units, precision); + format_value_and_unit(value_string, VALUE_STRING_SIZE, (options & RRDR_OPTION_DISPLAY_ABS)?calculated_number_fabs(value):value, units, precision); // we need to copy the label, since verdana11_width may write to it strncpyz(label_buffer, label, LABEL_STRING_SIZE); diff --git a/src/web_buffer_svg.h b/src/web_buffer_svg.h index 49f73e44..c09ef7bc 100644 --- a/src/web_buffer_svg.h +++ b/src/web_buffer_svg.h @@ -1,7 +1,7 @@ #ifndef NETDATA_WEB_BUFFER_SVG_H #define NETDATA_WEB_BUFFER_SVG_H 1 -extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision); +extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, uint32_t options); extern char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision); #endif /* NETDATA_WEB_BUFFER_SVG_H */ diff --git a/src/web_client.c b/src/web_client.c index 6ec3e11e..e17bac92 100644 --- a/src/web_client.c +++ b/src/web_client.c @@ -8,6 +8,15 @@ int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS; int respect_web_browser_do_not_track_policy = 0; char *web_x_frame_options = NULL; +SIMPLE_PATTERN *web_allow_connections_from = NULL; +SIMPLE_PATTERN *web_allow_streaming_from = NULL; +SIMPLE_PATTERN *web_allow_netdataconf_from = NULL; + +// WEB_CLIENT_ACL +SIMPLE_PATTERN *web_allow_dashboard_from = NULL; +SIMPLE_PATTERN *web_allow_registry_from = NULL; +SIMPLE_PATTERN *web_allow_badges_from = NULL; + #ifdef NETDATA_WITH_ZLIB int web_enable_gzip = 1, web_gzip_level = 3, web_gzip_strategy = Z_DEFAULT_STRATEGY; #endif /* NETDATA_WITH_ZLIB */ @@ -50,6 +59,31 @@ static inline int web_client_uncrock_socket(struct web_client *w) { return 0; } +inline int web_client_permission_denied(struct web_client *w) { + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "You are not allowed to access this resource."); + w->response.code = 403; + return 403; +} + +static void log_connection(struct web_client *w, const char *msg) { + log_access("%llu: %d '[%s]:%s' '%s'", w->id, gettid(), w->client_ip, w->client_port, msg); +} + +static void web_client_update_acl_matches(struct web_client *w) { + w->acl = WEB_CLIENT_ACL_NONE; + + if(!web_allow_dashboard_from || simple_pattern_matches(web_allow_dashboard_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_DASHBOARD; + + if(!web_allow_registry_from || simple_pattern_matches(web_allow_registry_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_REGISTRY; + + if(!web_allow_badges_from || simple_pattern_matches(web_allow_badges_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_BADGE; +} + struct web_client *web_client_create(int listener) { struct web_client *w; @@ -58,12 +92,25 @@ struct web_client *web_client_create(int listener) { w->mode = WEB_CLIENT_MODE_NORMAL; { - w->ifd = accept_socket(listener, SOCK_NONBLOCK, w->client_ip, sizeof(w->client_ip), w->client_port, sizeof(w->client_port)); + w->ifd = accept_socket(listener, SOCK_NONBLOCK, w->client_ip, sizeof(w->client_ip), w->client_port, sizeof(w->client_port), web_allow_connections_from); + + if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-"); + if(unlikely(!*w->client_port)) strcpy(w->client_port, "-"); + if (w->ifd == -1) { - error("%llu: Cannot accept new incoming connection.", w->id); + if(errno == EPERM) + log_connection(w, "ACCESS DENIED"); + else { + log_connection(w, "CONNECTION FAILED"); + error("%llu: Failed to accept new incoming connection.", w->id); + } + freez(w); return NULL; } + else + log_connection(w, "CONNECTED"); + w->ofd = w->ifd; int flag = 1; @@ -75,6 +122,8 @@ struct web_client *web_client_create(int listener) { error("%llu: Cannot set SO_KEEPALIVE on socket.", w->id); } + web_client_update_acl_matches(w); + w->response.data = buffer_create(INITIAL_WEB_DATA_LENGTH); w->response.header = buffer_create(HTTP_RESPONSE_HEADER_SIZE); w->response.header_output = buffer_create(HTTP_RESPONSE_HEADER_SIZE); @@ -119,18 +168,45 @@ void web_client_reset(struct web_client *w) { // -------------------------------------------------------------------- - // access log - log_access("%llu: (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: %d '%s'", - w->id, - sent, size, -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0), - dt_usec(&w->tv_ready, &w->tv_in) / 1000.0, - dt_usec(&tv, &w->tv_ready) / 1000.0, - dt_usec(&tv, &w->tv_in) / 1000.0, - (w->mode == WEB_CLIENT_MODE_FILECOPY) ? "filecopy" : ((w->mode == WEB_CLIENT_MODE_OPTIONS) - ? "options" : "data"), - w->response.code, - w->last_url + const char *mode; + switch(w->mode) { + case WEB_CLIENT_MODE_FILECOPY: + mode = "FILECOPY"; + break; + + case WEB_CLIENT_MODE_OPTIONS: + mode = "OPTIONS"; + break; + + case WEB_CLIENT_MODE_STREAM: + mode = "STREAM"; + break; + + case WEB_CLIENT_MODE_NORMAL: + mode = "DATA"; + break; + + default: + mode = "UNKNOWN"; + break; + } + + // access log + log_access("%llu: %d '[%s]:%s' '%s' (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %d '%s'", + w->id + , gettid() + , w->client_ip + , w->client_port + , mode + , sent + , size + , -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0) + , dt_usec(&w->tv_ready, &w->tv_in) / 1000.0 + , dt_usec(&tv, &w->tv_ready) / 1000.0 + , dt_usec(&tv, &w->tv_in) / 1000.0 + , w->response.code + , w->last_url ); } @@ -271,6 +347,9 @@ gid_t web_files_gid(void) { int mysendfile(struct web_client *w, char *filename) { debug(D_WEB_CLIENT, "%llu: Looking for file '%s/%s'", w->id, netdata_configured_web_dir, filename); + if(!web_client_can_access_dashboard(w)) + return web_client_permission_denied(w); + // skip leading slashes while (*filename == '/') filename++; @@ -553,6 +632,13 @@ static inline int check_host_and_call(RRDHOST *host, struct web_client *w, char return func(host, w, url); } +static inline int check_host_and_dashboard_acl_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) { + if(!web_client_can_access_dashboard(w)) + return web_client_permission_denied(w); + + return check_host_and_call(host, w, url, func); +} + int web_client_api_request(RRDHOST *host, struct web_client *w, char *url) { // get the api version @@ -1082,25 +1168,28 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch } else if(unlikely(hash == hash_data && strcmp(tok, WEB_PATH_DATA) == 0)) { // old API "data" debug(D_WEB_CLIENT_ACCESS, "%llu: old API data request...", w->id); - return check_host_and_call(host, w, url, web_client_api_old_data_request_json); + return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_data_request_json); } else if(unlikely(hash == hash_datasource && strcmp(tok, WEB_PATH_DATASOURCE) == 0)) { // old API "datasource" debug(D_WEB_CLIENT_ACCESS, "%llu: old API datasource request...", w->id); - return check_host_and_call(host, w, url, web_client_api_old_data_request_jsonp); + return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_data_request_jsonp); } else if(unlikely(hash == hash_graph && strcmp(tok, WEB_PATH_GRAPH) == 0)) { // old API "graph" debug(D_WEB_CLIENT_ACCESS, "%llu: old API graph request...", w->id); - return check_host_and_call(host, w, url, web_client_api_old_graph_request); + return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_graph_request); } else if(unlikely(hash == hash_list && strcmp(tok, "list") == 0)) { // old API "list" debug(D_WEB_CLIENT_ACCESS, "%llu: old API list request...", w->id); - return check_host_and_call(host, w, url, web_client_api_old_list_request); + return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_list_request); } else if(unlikely(hash == hash_all_json && strcmp(tok, "all.json") == 0)) { // old API "all.json" debug(D_WEB_CLIENT_ACCESS, "%llu: old API all.json request...", w->id); - return check_host_and_call(host, w, url, web_client_api_old_all_json); + return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_all_json); } else if(unlikely(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0)) { // netdata.conf + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + debug(D_WEB_CLIENT_ACCESS, "%llu: generating netdata.conf ...", w->id); w->response.data->contenttype = CT_TEXT_PLAIN; buffer_flush(w->response.data); @@ -1109,6 +1198,9 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch } #ifdef NETDATA_INTERNAL_CHECKS else if(unlikely(hash == hash_exit && strcmp(tok, "exit") == 0)) { + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + w->response.data->contenttype = CT_TEXT_PLAIN; buffer_flush(w->response.data); @@ -1122,6 +1214,9 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch return 200; } else if(unlikely(hash == hash_debug && strcmp(tok, "debug") == 0)) { + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + buffer_flush(w->response.data); // get the name of the data to show @@ -1159,6 +1254,9 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch return 400; } else if(unlikely(hash == hash_mirror && strcmp(tok, "mirror") == 0)) { + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id); // replace the zero bytes with spaces @@ -1189,10 +1287,20 @@ void web_client_process_request(struct web_client *w) { case HTTP_VALIDATION_OK: switch(w->mode) { case WEB_CLIENT_MODE_STREAM: + if(unlikely(!web_client_can_access_stream(w))) { + web_client_permission_denied(w); + return; + } + w->response.code = rrdpush_receiver_thread_spawn(localhost, w, w->decoded_url); return; case WEB_CLIENT_MODE_OPTIONS: + if(unlikely(!web_client_can_access_dashboard(w) && !web_client_can_access_registry(w) && !web_client_can_access_badges(w))) { + web_client_permission_denied(w); + return; + } + w->response.data->contenttype = CT_TEXT_PLAIN; buffer_flush(w->response.data); buffer_strcat(w->response.data, "OK"); @@ -1201,6 +1309,11 @@ void web_client_process_request(struct web_client *w) { case WEB_CLIENT_MODE_FILECOPY: case WEB_CLIENT_MODE_NORMAL: + if(unlikely(!web_client_can_access_dashboard(w) && !web_client_can_access_registry(w) && !web_client_can_access_badges(w))) { + web_client_permission_denied(w); + return; + } + w->response.code = web_client_process_url(localhost, w, w->decoded_url); break; } @@ -1607,8 +1720,6 @@ void *web_client_main(void *ptr) int retval, timeout; nfds_t fdmax = 0; - log_access("%llu: %s port %s connected on thread task id %d", w->id, w->client_ip, w->client_port, gettid()); - for(;;) { if(unlikely(netdata_exit)) break; @@ -1716,9 +1827,11 @@ void *web_client_main(void *ptr) } } + if(w->mode != WEB_CLIENT_MODE_STREAM) + log_connection(w, "DISCONNECTED"); + web_client_reset(w); - log_access("%llu: %s port %s disconnected from thread task id %d", w->id, w->client_ip, w->client_port, gettid()); debug(D_WEB_CLIENT, "%llu: done...", w->id); // close the sockets/files now diff --git a/src/web_client.h b/src/web_client.h index 126a494f..a07558e1 100644 --- a/src/web_client.h +++ b/src/web_client.h @@ -44,7 +44,7 @@ typedef enum web_client_flags { //#define web_client_flag_set(w, flag) __atomic_or_fetch(&((w)->flags), flag, __ATOMIC_SEQ_CST) //#define web_client_flag_clear(w, flag) __atomic_and_fetch(&((w)->flags), ~flag, __ATOMIC_SEQ_CST) //#else -#define web_client_flag_check(w, flag) ((w)->flags & flag) +#define web_client_flag_check(w, flag) ((w)->flags & (flag)) #define web_client_flag_set(w, flag) (w)->flags |= flag #define web_client_flag_clear(w, flag) (w)->flags &= ~flag //#endif @@ -77,6 +77,7 @@ typedef enum web_client_flags { #define web_client_set_tcp(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TCP_CLIENT) #define web_client_set_unix(w) web_client_flag_set(w, WEB_CLIENT_FLAG_UNIX_CLIENT) +#define web_client_check_unix(w) web_client_flag_check(w, WEB_CLIENT_FLAG_UNIX_CLIENT) #define web_client_is_corkable(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT) @@ -107,11 +108,30 @@ struct response { }; +typedef enum web_client_acl { + WEB_CLIENT_ACL_NONE = 0, + WEB_CLIENT_ACL_NOCHECK = 0, + WEB_CLIENT_ACL_DASHBOARD = 1 << 0, + WEB_CLIENT_ACL_REGISTRY = 1 << 1, + WEB_CLIENT_ACL_BADGE = 1 << 2 +} WEB_CLIENT_ACL; + +#define web_client_can_access_dashboard(w) ((w)->acl & WEB_CLIENT_ACL_DASHBOARD) +#define web_client_can_access_registry(w) ((w)->acl & WEB_CLIENT_ACL_REGISTRY) +#define web_client_can_access_badges(w) ((w)->acl & WEB_CLIENT_ACL_BADGE) + +#define web_client_can_access_stream(w) \ + (!web_allow_streaming_from || simple_pattern_matches(web_allow_streaming_from, (w)->client_ip)) + +#define web_client_can_access_netdataconf(w) \ + (!web_allow_netdataconf_from || simple_pattern_matches(web_allow_netdataconf_from, (w)->client_ip)) + struct web_client { unsigned long long id; WEB_CLIENT_FLAGS flags; // status flags for the client WEB_CLIENT_MODE mode; // the operational mode of the client + WEB_CLIENT_ACL acl; // the access list of the client int tcp_cork; // 1 = we have a cork on the socket @@ -142,10 +162,18 @@ struct web_client { }; extern struct web_client *web_clients; +extern SIMPLE_PATTERN *web_allow_connections_from; +extern SIMPLE_PATTERN *web_allow_dashboard_from; +extern SIMPLE_PATTERN *web_allow_registry_from; +extern SIMPLE_PATTERN *web_allow_badges_from; +extern SIMPLE_PATTERN *web_allow_streaming_from; +extern SIMPLE_PATTERN *web_allow_netdataconf_from; extern uid_t web_files_uid(void); extern uid_t web_files_gid(void); +extern int web_client_permission_denied(struct web_client *w); + extern struct web_client *web_client_create(int listener); extern struct web_client *web_client_free(struct web_client *w); extern ssize_t web_client_send(struct web_client *w); diff --git a/src/web_server.c b/src/web_server.c index 72168d15..d231cbb5 100644 --- a/src/web_server.c +++ b/src/web_server.c @@ -168,6 +168,11 @@ void *socket_listen_main_multi_threaded(void *ptr) { continue; } + if(api_sockets.fds_families[i] == AF_UNIX) + web_client_set_unix(w); + else + web_client_set_tcp(w); + if(pthread_create(&w->thread, NULL, web_client_main, w) != 0) { error("%llu: failed to create new thread for web client.", w->id); WEB_CLIENT_IS_OBSOLETE(w); @@ -203,8 +208,8 @@ static inline int single_threaded_link_client(struct web_client *w, fd_set *ifds if(unlikely(web_client_check_obsolete(w) || web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w)))) return 1; - if(unlikely(w->ifd < 0 || w->ifd >= FD_SETSIZE || w->ofd < 0 || w->ofd >= FD_SETSIZE)) { - error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd < FD_SETSIZE (%d)", w->id, w->ifd, w->ofd, FD_SETSIZE); + if(unlikely(w->ifd < 0 || w->ifd >= (int)FD_SETSIZE || w->ofd < 0 || w->ofd >= (int)FD_SETSIZE)) { + error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd < FD_SETSIZE (%d)", w->id, w->ifd, w->ofd, (int)FD_SETSIZE); return 1; } @@ -261,7 +266,7 @@ void *socket_listen_main_single_threaded(void *ptr) { fatal("LISTENER: no listen sockets available."); size_t i; - for(i = 0; i < FD_SETSIZE ; i++) + for(i = 0; i < (size_t)FD_SETSIZE ; i++) single_threaded_clients[i] = NULL; fd_set ifds, ofds, efds, rifds, rofds, refds; @@ -271,7 +276,7 @@ void *socket_listen_main_single_threaded(void *ptr) { int fdmax = 0; for(i = 0; i < api_sockets.opened ; i++) { - if (api_sockets.fds[i] < 0 || api_sockets.fds[i] >= FD_SETSIZE) + if (api_sockets.fds[i] < 0 || api_sockets.fds[i] >= (int)FD_SETSIZE) fatal("LISTENER: Listen socket %d is not ready, or invalid.", api_sockets.fds[i]); info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN"); @@ -372,3 +377,142 @@ void *socket_listen_main_single_threaded(void *ptr) { pthread_exit(NULL); return NULL; } + + +#if 0 +// new TCP client connected +static void *web_server_add_callback(int fd, int socktype, short int *events) { + (void)fd; + (void)socktype; + + *events = POLLIN; + + debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", fd); + struct web_client *w = web_client_create(fd); + + if(unlikely(socktype == AF_UNIX)) + web_client_set_unix(w); + else + web_client_set_tcp(w); + + return (void *)w; +} + +// TCP client disconnected +static void web_server_del_callback(int fd, int socktype, void *data) { + (void)fd; + (void)socktype; + + struct web_client *w = (struct web_client *)data; + + if(w) { + if(w->ofd == -1 || fd == w->ofd) { + // we free the client, only if the closing fd + // is the client socket + web_client_free(w); + } + } + + return; +} + +// Receive data +static int web_server_rcv_callback(int fd, int socktype, void *data, short int *events) { + (void)fd; + (void)socktype; + + *events = 0; + + struct web_client *w = (struct web_client *)data; + + if(unlikely(!web_client_has_wait_receive(w))) + return -1; + + if(unlikely(web_client_receive(w) < 0)) + return -1; + + if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) { + if(unlikely(w->ifd != -1 && w->ifd != fd)) { + // FIXME: we switched input fd + // add a new socket to poll_events, with the same + } + else if(unlikely(w->ifd == -1)) { + // FIXME: we closed input fd + // instruct poll_events() to close fd + return -1; + } + } + else { + debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id); + web_client_process_request(w); + } + + if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) + *events |= POLLIN; + + if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) + *events |= POLLOUT; + + if(unlikely(*events == 0)) + return -1; + + return 0; +} + +static int web_server_snd_callback(int fd, int socktype, void *data, short int *events) { + (void)fd; + (void)socktype; + + struct web_client *w = (struct web_client *)data; + + if(unlikely(!web_client_has_wait_send(w))) + return -1; + + if(unlikely(web_client_send(w) < 0)) + return -1; + + if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) + *events |= POLLIN; + + if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) + *events |= POLLOUT; + + if(unlikely(*events == 0)) + return -1; + + return 0; +} + +void *socket_listen_main_single_threaded(void *ptr) { + struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; + + web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED; + + info("Single-threaded WEB SERVER thread created with task id %d", gettid()); + + if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) + error("Cannot set pthread cancel type to DEFERRED."); + + if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) + error("Cannot set pthread cancel state to ENABLE."); + + if(!api_sockets.opened) + fatal("LISTENER: no listen sockets available."); + + poll_events(&api_sockets + , web_server_add_callback + , web_server_del_callback + , web_server_rcv_callback + , web_server_snd_callback + , web_allow_connections_from + , NULL + ); + + debug(D_WEB_CLIENT, "LISTENER: exit!"); + listen_sockets_close(&api_sockets); + + static_thread->enabled = 0; + pthread_exit(NULL); + return NULL; +} +#endif diff --git a/src/zfs_common.c b/src/zfs_common.c index 7fa05b03..0915416f 100644 --- a/src/zfs_common.c +++ b/src/zfs_common.c @@ -1,9 +1,9 @@ #include "common.h" #include "zfs_common.h" -extern struct arcstats arcstats; +struct arcstats arcstats = { 0 }; -void generate_charts_arcstats(int update_every) { +void generate_charts_arcstats(const char *plugin, int update_every) { // ARC reads unsigned long long aread = arcstats.hits + arcstats.misses; @@ -24,8 +24,8 @@ void generate_charts_arcstats(int update_every) { unsigned long long mread = mhit + mmiss; // l2 reads - unsigned long long l2hit = arcstats.l2_hits + arcstats.l2_misses; - unsigned long long l2miss = arcstats.prefetch_metadata_misses + arcstats.demand_metadata_misses; + unsigned long long l2hit = arcstats.l2_hits; + unsigned long long l2miss = arcstats.l2_misses; unsigned long long l2read = l2hit + l2miss; // -------------------------------------------------------------------- @@ -46,6 +46,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS ARC Size" , "MB" + , plugin + , "zfs" , 2000 , update_every , RRDSET_TYPE_AREA @@ -68,7 +70,7 @@ void generate_charts_arcstats(int update_every) { // -------------------------------------------------------------------- - if(likely(l2exist)) { + if(likely(arcstats.l2exist)) { static RRDSET *st_l2_size = NULL; static RRDDIM *rd_l2_size = NULL; static RRDDIM *rd_l2_asize = NULL; @@ -82,6 +84,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS L2 ARC Size" , "MB" + , plugin + , "zfs" , 2000 , update_every , RRDSET_TYPE_AREA @@ -117,6 +121,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS Reads" , "reads/s" + , plugin + , "zfs" , 2010 , update_every , RRDSET_TYPE_AREA @@ -127,7 +133,7 @@ void generate_charts_arcstats(int update_every) { rd_pread = rrddim_add(st_reads, "preads", "prefetch", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_mread = rrddim_add(st_reads, "mreads", "metadata", 1, 1, RRD_ALGORITHM_INCREMENTAL); - if(l2exist) + if(arcstats.l2exist) rd_l2read = rrddim_add(st_reads, "l2reads", "l2", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else @@ -138,7 +144,7 @@ void generate_charts_arcstats(int update_every) { rrddim_set_by_pointer(st_reads, rd_pread, pread); rrddim_set_by_pointer(st_reads, rd_mread, mread); - if(l2exist) + if(arcstats.l2exist) rrddim_set_by_pointer(st_reads, rd_l2read, l2read); rrdset_done(st_reads); @@ -146,7 +152,7 @@ void generate_charts_arcstats(int update_every) { // -------------------------------------------------------------------- - if(likely(l2exist)) { + if(likely(arcstats.l2exist)) { static RRDSET *st_l2bytes = NULL; static RRDDIM *rd_l2_read_bytes = NULL; static RRDDIM *rd_l2_write_bytes = NULL; @@ -160,6 +166,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS ARC L2 Read/Write Rate" , "kilobytes/s" + , plugin + , "zfs" , 2200 , update_every , RRDSET_TYPE_AREA @@ -192,6 +200,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS ARC Hits" , "percentage" + , plugin + , "zfs" , 2020 , update_every , RRDSET_TYPE_STACKED @@ -224,6 +234,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS Demand Hits" , "percentage" + , plugin + , "zfs" , 2030 , update_every , RRDSET_TYPE_STACKED @@ -256,6 +268,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS Prefetch Hits" , "percentage" + , plugin + , "zfs" , 2040 , update_every , RRDSET_TYPE_STACKED @@ -288,6 +302,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS Metadata Hits" , "percentage" + , plugin + , "zfs" , 2050 , update_every , RRDSET_TYPE_STACKED @@ -306,7 +322,7 @@ void generate_charts_arcstats(int update_every) { // -------------------------------------------------------------------- - if(likely(l2exist)) { + if(likely(arcstats.l2exist)) { static RRDSET *st_l2hits = NULL; static RRDDIM *rd_l2hits = NULL; static RRDDIM *rd_l2misses = NULL; @@ -320,6 +336,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS L2 Hits" , "percentage" + , plugin + , "zfs" , 2060 , update_every , RRDSET_TYPE_STACKED @@ -354,6 +372,8 @@ void generate_charts_arcstats(int update_every) { , NULL , "ZFS List Hits" , "hits/s" + , plugin + , "zfs" , 2100 , update_every , RRDSET_TYPE_AREA @@ -375,7 +395,7 @@ void generate_charts_arcstats(int update_every) { } } -void generate_charts_arc_summary(int update_every) { +void generate_charts_arc_summary(const char *plugin, int update_every) { unsigned long long arc_accesses_total = arcstats.hits + arcstats.misses; unsigned long long real_hits = arcstats.mfu_hits + arcstats.mru_hits; unsigned long long real_misses = arc_accesses_total - real_hits; @@ -411,6 +431,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS ARC Size Breakdown" , "percentage" + , plugin + , "zfs" , 2020 , update_every , RRDSET_TYPE_STACKED @@ -448,6 +470,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS Memory Operations" , "operations/s" + , plugin + , "zfs" , 2023 , update_every , RRDSET_TYPE_LINE @@ -492,6 +516,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS Important Operations" , "operations/s" + , plugin + , "zfs" , 2022 , update_every , RRDSET_TYPE_LINE @@ -528,6 +554,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS Actual Cache Hits" , "percentage" + , plugin + , "zfs" , 2019 , update_every , RRDSET_TYPE_STACKED @@ -560,6 +588,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS Data Demand Efficiency" , "percentage" + , plugin + , "zfs" , 2031 , update_every , RRDSET_TYPE_STACKED @@ -592,6 +622,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS Data Prefetch Efficiency" , "percentage" + , plugin + , "zfs" , 2032 , update_every , RRDSET_TYPE_STACKED @@ -624,6 +656,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS ARC Hash Elements" , "elements" + , plugin + , "zfs" , 2300 , update_every , RRDSET_TYPE_LINE @@ -656,6 +690,8 @@ void generate_charts_arc_summary(int update_every) { , NULL , "ZFS ARC Hash Chains" , "chains" + , plugin + , "zfs" , 2310 , update_every , RRDSET_TYPE_LINE diff --git a/src/zfs_common.h b/src/zfs_common.h index 9d3aa7df..4494e70c 100644 --- a/src/zfs_common.h +++ b/src/zfs_common.h @@ -8,6 +8,7 @@ #define ZFS_FAMILY_HASH "hashes" struct arcstats { + // values unsigned long long hits; unsigned long long misses; unsigned long long demand_data_hits; @@ -99,11 +100,12 @@ struct arcstats { unsigned long long arc_meta_min; unsigned long long arc_need_free; unsigned long long arc_sys_free; -}; -int l2exist; + // flags + int l2exist; +}; -void generate_charts_arcstats(int update_every); -void generate_charts_arc_summary(int update_every); +void generate_charts_arcstats(const char *plugin, int update_every); +void generate_charts_arc_summary(const char *plugin, int update_every); #endif //NETDATA_ZFS_COMMON_H |