diff options
Diffstat (limited to '')
152 files changed, 9184 insertions, 9816 deletions
diff --git a/collectors/COLLECTORS.md b/collectors/COLLECTORS.md index 1be50fd14..7f66076ff 100644 --- a/collectors/COLLECTORS.md +++ b/collectors/COLLECTORS.md @@ -74,6 +74,10 @@ configure any of these collectors according to your setup and infrastructure. - [Prometheus endpoints](https://learn.netdata.cloud/docs/agent/collectors/go.d.plugin/modules/prometheus): Gathers metrics from any number of Prometheus endpoints, with support to autodetect more than 600 services and applications. +- [Pandas](https://learn.netdata.cloud/docs/agent/collectors/python.d.plugin/pandas): A Python collector that gathers + metrics from a [pandas](https://pandas.pydata.org/) dataframe. Pandas is a high level data processing library in + Python that can read various formats of data from local files or web endpoints. Custom processing and transformation + logic can also be expressed as part of the collector configuration. ### APM (application performance monitoring) @@ -510,6 +514,5 @@ default. To use a third-party collector, visit their GitHub/documentation page a ## Etc -- [checks.plugin](checks.plugin/README.md): A debugging collector, disabled by default. - [charts.d example](charts.d.plugin/example/README.md): An example `charts.d` collector. - [python.d example](python.d.plugin/example/README.md): An example `python.d` collector. diff --git a/collectors/Makefile.am b/collectors/Makefile.am index a0a972e8f..9f8bf5280 100644 --- a/collectors/Makefile.am +++ b/collectors/Makefile.am @@ -7,7 +7,6 @@ SUBDIRS = \ apps.plugin \ cgroups.plugin \ charts.d.plugin \ - checks.plugin \ cups.plugin \ diskspace.plugin \ timex.plugin \ diff --git a/collectors/REFERENCE.md b/collectors/REFERENCE.md index 949858f60..939b189ee 100644 --- a/collectors/REFERENCE.md +++ b/collectors/REFERENCE.md @@ -148,11 +148,6 @@ collect_data() { // attach a metric to it rd = rrddim_add(st, "id", "name", multiplier, divider, algorithm); } - else { - // this chart is already created - // let Netdata know we start a new iteration on it - rrdset_next(st); - } // give the collected value(s) to the chart rrddim_set_by_pointer(st, rd, collected_value); diff --git a/collectors/all.h b/collectors/all.h index 3d7304dd5..85a7ac8b2 100644 --- a/collectors/all.h +++ b/collectors/all.h @@ -195,11 +195,11 @@ #define NETDATA_CHART_PRIO_ZFS_IO 2700 #define NETDATA_CHART_PRIO_ZFS_HITS 2520 #define NETDATA_CHART_PRIO_ZFS_DHITS 2530 -#define NETDATA_CHART_PRIO_ZFS_DEMAND_DATA_HITS 2531 -#define NETDATA_CHART_PRIO_ZFS_PREFETCH_DATA_HITS 2532 -#define NETDATA_CHART_PRIO_ZFS_PHITS 2540 -#define NETDATA_CHART_PRIO_ZFS_MHITS 2550 -#define NETDATA_CHART_PRIO_ZFS_L2HITS 2560 +#define NETDATA_CHART_PRIO_ZFS_DEMAND_DATA_HITS 2540 +#define NETDATA_CHART_PRIO_ZFS_PREFETCH_DATA_HITS 2550 +#define NETDATA_CHART_PRIO_ZFS_PHITS 2560 +#define NETDATA_CHART_PRIO_ZFS_MHITS 2570 +#define NETDATA_CHART_PRIO_ZFS_L2HITS 2580 #define NETDATA_CHART_PRIO_ZFS_LIST_HITS 2600 #define NETDATA_CHART_PRIO_ZFS_HASH_ELEMENTS 2800 #define NETDATA_CHART_PRIO_ZFS_HASH_CHAINS 2810 diff --git a/collectors/apps.plugin/apps_groups.conf b/collectors/apps.plugin/apps_groups.conf index 89db6c4e8..dd45c5a5a 100644 --- a/collectors/apps.plugin/apps_groups.conf +++ b/collectors/apps.plugin/apps_groups.conf @@ -96,13 +96,13 @@ agent_sd: agent_sd # ----------------------------------------------------------------------------- # authentication/authorization related servers -auth: radius* openldap* ldap* slapd authelia +auth: radius* openldap* ldap* slapd authelia sssd saslauthd polkitd gssproxy fail2ban: fail2ban* # ----------------------------------------------------------------------------- # web/ftp servers -httpd: apache* httpd nginx* lighttpd hiawatha caddy +httpd: apache* httpd nginx* lighttpd hiawatha caddy h2o proxy: squid* c-icap squidGuard varnish* php: php* lsphp* ftpd: proftpd in.tftpd vsftpd @@ -121,7 +121,8 @@ columndb: clickhouse-server* # ----------------------------------------------------------------------------- # email servers -email: dovecot imapd pop3d amavis* zmstat-* zmdiaglog zmmailboxdmgr saslauthd opendkim postfwd2 smtp* lmtp* sendmail postfix master pickup qmgr showq tlsmgr postscreen oqmgr +mta: amavis* zmstat-* zmdiaglog zmmailboxdmgr opendkim postfwd2 smtp* lmtp* sendmail postfix master pickup qmgr showq tlsmgr postscreen oqmgr msmtp* nullmailer* +mda: dovecot *imapd *pop3d *popd # ----------------------------------------------------------------------------- # network, routing, VPN @@ -131,15 +132,17 @@ vpn: openvpn pptp* cjdroute gvpe tincd wireguard tailscaled wifi: hostapd wpa_supplicant routing: ospfd* ospf6d* bgpd bfdd fabricd isisd eigrpd sharpd staticd ripd ripngd pimd pbrd nhrpd ldpd zebra vrrpd vtysh bird* modem: ModemManager -netmanager: NetworkManager nm* systemd-networkd networkctl netplan +netmanager: NetworkManager nm* systemd-networkd networkctl netplan connmand wicked* avahi-autoipd networkd-dispatcher +firewall: firewalld ufw nft tor: tor +bluetooth: bluetooth bluez bluedevil obexd # ----------------------------------------------------------------------------- # high availability and balancers camo: *camo* balancer: ipvs_* haproxy -ha: corosync hs_logd ha_logd stonithd pacemakerd lrmd crmd keepalived +ha: corosync hs_logd ha_logd stonithd pacemakerd lrmd crmd keepalived ucarp* # ----------------------------------------------------------------------------- # telephony @@ -155,10 +158,18 @@ chat: irssi *vines* *prosody* murmurd # ----------------------------------------------------------------------------- # monitoring -logs: ulogd* syslog* rsyslog* logrotate systemd-journald rotatelogs -nms: snmpd vnstatd smokeping zabbix* monit munin* mon openhpid watchdog tailon nrpe +logs: ulogd* syslog* rsyslog* logrotate systemd-journald rotatelogs sysklogd metalog +nms: snmpd vnstatd smokeping zabbix* munin* mon openhpid tailon nrpe +monit: monit splunk: splunkd azure: mdsd *waagent* *omiserver* *omiagent* hv_kvp_daemon hv_vss_daemon *auoms* *omsagent* +datadog: *datadog* +edgedelta: edgedelta +newrelic: newrelic* +google-agent: *google_guest_agent* *google_osconfig_agent* +nvidia-smi: nvidia-smi +htop: htop +watchdog: watchdog # ----------------------------------------------------------------------------- # storage, file systems and file servers @@ -170,6 +181,7 @@ zfs: spl_* z_* txg_* zil_* arc_* l2arc* btrfs: btrfs* iscsi: iscsid iscsi_eh afp: netatalk afpd cnid_dbd cnid_metad +ntfs-3g: ntfs-3g # ----------------------------------------------------------------------------- # kubernetes @@ -189,18 +201,21 @@ aws: aws # ----------------------------------------------------------------------------- # virtualization platform -proxmox-ve: pve* +proxmox-ve: pve* spiceproxy # ----------------------------------------------------------------------------- # containers & virtual machines containers: lxc* docker* balena* -VMs: vbox* VBox* qemu* kvm +VMs: vbox* VBox* qemu* kvm* +libvirt: virtlogd virtqemud virtstoraged virtnetworkd virtlockd virtinterfaced +libvirt: virtnodedevd virtproxyd virtsecretd libvirtd +guest-agent: qemu-ga spice-vdagent cloud-init* # ----------------------------------------------------------------------------- # ssh servers and clients -ssh: ssh* scp dropbear +ssh: ssh* scp sftp* dropbear # ----------------------------------------------------------------------------- # print servers and clients @@ -210,24 +225,30 @@ print: cups* lpd lpq # ----------------------------------------------------------------------------- # time servers and clients -time: ntp* systemd-timesyn* chronyd +time: ntp* systemd-timesyn* chronyd ptp* # ----------------------------------------------------------------------------- # dhcp servers and clients -dhcp: *dhcp* +dhcp: *dhcp* dhclient # ----------------------------------------------------------------------------- # name servers and clients -dns: named unbound nsd pdns_server knotd gdnsd yadifad dnsmasq systemd-resolve* pihole* +dns: named unbound nsd pdns_server knotd gdnsd yadifad dnsmasq systemd-resolve* pihole* avahi-daemon avahi-dnsconfd dnsdist: dnsdist # ----------------------------------------------------------------------------- # installation / compilation / debugging build: cc1 cc1plus as gcc* cppcheck ld make cmake automake autoconf autoreconf -build: cargo rustc bazel buck git gdb valgrind* +build: cargo rustc bazel buck git gdb valgrind* rpmbuild dpkg-buildpackage + +# ----------------------------------------------------------------------------- +# package management + +packagemanager: apt* dpkg* dselect dnf yum rpm zypp* yast* pacman xbps* swupd* emerge* +packagemanager: packagekitd pkgin pkg apk snapd slackpkg slapt-get # ----------------------------------------------------------------------------- # antivirus @@ -258,7 +279,10 @@ ups: upsmon upsd */nut/* apcupsd # media players, servers, clients media: mplayer vlc xine mediatomb omxplayer* kodi* xbmc* mediacenter eventlircd -media: mpd minidlnad mt-daapd avahi* Plex* jellyfin squeeze* jackett Ombi +media: mpd minidlnad mt-daapd Plex* jellyfin squeeze* jackett Ombi +media: strawberry* clementine* + +audio: pulse* pipewire wireplumber jack* # ----------------------------------------------------------------------------- # java applications @@ -290,25 +314,56 @@ solr: *solr.install.dir* airflow: *airflow* # ----------------------------------------------------------------------------- -# X - -X: X Xorg xinit lightdm xdm pulseaudio gkrellm xfwm4 xfdesktop xfce* Thunar -X: xfsettingsd xfconfd gnome-* gdm gconf* dconf* xfconf* *gvfs gvfs* slim -X: kdeinit* kdm plasmashell -X: evolution-* firefox chromium opera vivaldi-bin epiphany WebKit* -X: '*systemd --user*' chrome *chrome-sandbox* *google-chrome* *chromium* *firefox* +# GUI + +X: X Xorg xinit xdm Xwayland xsettingsd +wayland: swaylock swayidle waypipe wayvnc +kde: *kdeinit* kdm sddm plasmashell startplasma-* kwin* kwallet* krunner kactivitymanager* +gnome: gnome-* gdm gconf* mutter +mate: mate-* msd-* marco* +cinnamon: cinnamon* muffin +xfce: xfwm4 xfdesktop xfce* Thunar xfsettingsd xfconf* +lxde: lxde* startlxde lxdm lxappearance* lxlauncher* lxpanel* lxsession* lxsettings* +lxqt: lxqt* startlxqt +enlightenment: entrance enlightenment* +i3: i3* +awesome: awesome awesome-client +dwm: dwm.* +sway: sway +weston: weston +cage: cage +wayfire: wayfire +gui: lightdm colord seatd greetd gkrellm slim qingy dconf* *gvfs gvfs* +gui: '*systemd --user*' xdg-* at-spi-* + +webbrowser: *chrome-sandbox* *google-chrome* *chromium* *firefox* vivaldi* opera* epiphany chrome* +webbrowser: lynx elinks w3m w3mmee links +mua: evolution-* thunderbird* mutt neomutt pine mailx alpine # ----------------------------------------------------------------------------- # Kernel / System ksmd: ksmd +khugepaged: khugepaged +kdamond: kdamond +kswapd: kswapd +zswap: zswap +kcompactd: kcompactd + +system: systemd-* udisks* udevd* *udevd ipv6_addrconf dbus-* rtkit* +system: mdadm acpid uuidd upowerd elogind* eudev mdev lvmpolld dmeventd +system: accounts-daemon rngd haveged rasdaemon irqbalance start-stop-daemon +system: supervise-daemon openrc* init runit runsvdir runsv auditd lsmd +system: abrt* nscd rtkit-daemon gpg-agent usbguard* + +kernel: kworker kthreadd kauditd lockd khelper kdevtmpfs khungtaskd rpciod +kernel: fsnotify_mark kthrotld deferwq scsi_* kdmflush oom_reaper kdevtempfs +kernel: ksoftirqd -system: systemd-* udisks* udevd* *udevd connmand ipv6_addrconf dbus-* rtkit* -system: inetd xinetd mdadm polkitd acpid uuidd packagekitd upowerd colord -system: accounts-daemon rngd haveged +# ----------------------------------------------------------------------------- +# inetd -kernel: kthreadd kauditd lockd khelper kdevtmpfs khungtaskd rpciod -kernel: fsnotify_mark kthrotld deferwq scsi_* +inetd: inetd xinetd # ----------------------------------------------------------------------------- # other application servers @@ -355,3 +410,13 @@ gremlin: gremlin* # load testing tools locust: locust + +# ----------------------------------------------------------------------------- +# data science and machine learning tools + +jupyter: jupyter* + +# ----------------------------------------------------------------------------- +# File synchronization tools + +filesync: dropbox syncthing diff --git a/collectors/apps.plugin/apps_plugin.c b/collectors/apps.plugin/apps_plugin.c index 8521e078e..89b83332b 100644 --- a/collectors/apps.plugin/apps_plugin.c +++ b/collectors/apps.plugin/apps_plugin.c @@ -10,6 +10,11 @@ #include "libnetdata/libnetdata.h" #include "libnetdata/required_dummies.h" +#define APPS_PLUGIN_FUNCTIONS() do { \ + fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " \"processes\" 10 \"Detailed information on the currently running processes on this node\"\n"); \ + } while(0) + + // ---------------------------------------------------------------------------- // debugging @@ -191,6 +196,18 @@ struct pid_on_target { struct pid_on_target *next; }; +struct openfds { + kernel_uint_t files; + kernel_uint_t pipes; + kernel_uint_t sockets; + kernel_uint_t inotifies; + kernel_uint_t eventfds; + kernel_uint_t timerfds; + kernel_uint_t signalfds; + kernel_uint_t eventpolls; + kernel_uint_t other; +}; + // ---------------------------------------------------------------------------- // target // @@ -235,24 +252,16 @@ struct target { kernel_uint_t io_logical_bytes_read; kernel_uint_t io_logical_bytes_written; - // kernel_uint_t io_read_calls; - // kernel_uint_t io_write_calls; + kernel_uint_t io_read_calls; + kernel_uint_t io_write_calls; kernel_uint_t io_storage_bytes_read; kernel_uint_t io_storage_bytes_written; - // kernel_uint_t io_cancelled_write_bytes; + kernel_uint_t io_cancelled_write_bytes; int *target_fds; int target_fds_size; - kernel_uint_t openfiles; - kernel_uint_t openpipes; - kernel_uint_t opensockets; - kernel_uint_t openinotifies; - kernel_uint_t openeventfds; - kernel_uint_t opentimerfds; - kernel_uint_t opensignalfds; - kernel_uint_t openeventpolls; - kernel_uint_t openother; + struct openfds openfds; kernel_uint_t starttime; kernel_uint_t collected_starttime; @@ -382,22 +391,24 @@ struct pid_stat { kernel_uint_t io_logical_bytes_read_raw; kernel_uint_t io_logical_bytes_written_raw; - // kernel_uint_t io_read_calls_raw; - // kernel_uint_t io_write_calls_raw; + kernel_uint_t io_read_calls_raw; + kernel_uint_t io_write_calls_raw; kernel_uint_t io_storage_bytes_read_raw; kernel_uint_t io_storage_bytes_written_raw; - // kernel_uint_t io_cancelled_write_bytes_raw; + kernel_uint_t io_cancelled_write_bytes_raw; kernel_uint_t io_logical_bytes_read; kernel_uint_t io_logical_bytes_written; - // kernel_uint_t io_read_calls; - // kernel_uint_t io_write_calls; + kernel_uint_t io_read_calls; + kernel_uint_t io_write_calls; kernel_uint_t io_storage_bytes_read; kernel_uint_t io_storage_bytes_written; - // kernel_uint_t io_cancelled_write_bytes; + kernel_uint_t io_cancelled_write_bytes; struct pid_fd *fds; // array of fds it uses - size_t fds_size; // the size of the fds array + size_t fds_size; // the size of the fds array + + struct openfds openfds; int children_count; // number of processes directly referencing this unsigned char keep:1; // 1 when we need to keep this process in memory even after it exited @@ -447,8 +458,8 @@ kernel_uint_t global_uptime; static struct pid_stat *root_of_pids = NULL, // global list of all processes running - **all_pids = NULL; // to avoid allocations, we pre-allocate the - // the entire pid space. + **all_pids = NULL; // to avoid allocations, we pre-allocate + // a pointer for each pid in the entire pid space. static size_t all_pids_count = 0; // the number of processes running @@ -961,15 +972,10 @@ static inline struct pid_stat *get_pid_entry(pid_t pid) { p->fds = mallocz(sizeof(struct pid_fd) * MAX_SPARE_FDS); p->fds_size = MAX_SPARE_FDS; init_pid_fds(p, 0, p->fds_size); - - if(likely(root_of_pids)) - root_of_pids->prev = p; - - p->next = root_of_pids; - root_of_pids = p; - p->pid = pid; + DOUBLE_LINKED_LIST_APPEND_UNSAFE(root_of_pids, p, prev, next); + all_pids[pid] = p; all_pids_count++; @@ -986,11 +992,7 @@ static inline void del_pid_entry(pid_t pid) { debug_log("process %d %s exited, deleting it.", pid, p->comm); - if(root_of_pids == p) - root_of_pids = p->next; - - if(p->next) p->next->prev = p->prev; - if(p->prev) p->prev->next = p->next; + DOUBLE_LINKED_LIST_REMOVE_UNSAFE(root_of_pids, p, prev, next); // free the filename #ifndef __FreeBSD__ @@ -1554,21 +1556,21 @@ static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) { #else pid_incremental_rate(io, p->io_logical_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 0, 1))); pid_incremental_rate(io, p->io_logical_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 1, 1))); - // pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1))); - // pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1))); + pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1))); + pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1))); pid_incremental_rate(io, p->io_storage_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 4, 1))); pid_incremental_rate(io, p->io_storage_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 5, 1))); - // pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1))); + pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1))); #endif if(unlikely(global_iterations_counter == 1)) { p->io_logical_bytes_read = 0; p->io_logical_bytes_written = 0; - // p->io_read_calls = 0; - // p->io_write_calls = 0; + p->io_read_calls = 0; + p->io_write_calls = 0; p->io_storage_bytes_read = 0; p->io_storage_bytes_written = 0; - // p->io_cancelled_write_bytes = 0; + p->io_cancelled_write_bytes = 0; } return 1; @@ -1577,11 +1579,11 @@ static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) { cleanup: p->io_logical_bytes_read = 0; p->io_logical_bytes_written = 0; - // p->io_read_calls = 0; - // p->io_write_calls = 0; + p->io_read_calls = 0; + p->io_write_calls = 0; p->io_storage_bytes_read = 0; p->io_storage_bytes_written = 0; - // p->io_cancelled_write_bytes = 0; + p->io_cancelled_write_bytes = 0; return 0; #endif } @@ -1888,7 +1890,7 @@ static inline int file_descriptor_find_or_add(const char *name, uint32_t hash) { else if(likely(strncmp(name, "anon_inode:", 11) == 0)) { const char *t = &name[11]; - if(strcmp(t, "inotify") == 0) type = FILETYPE_INOTIFY; + if(strcmp(t, "inotify") == 0) type = FILETYPE_INOTIFY; else if(strcmp(t, "[eventfd]") == 0) type = FILETYPE_EVENTFD; else if(strcmp(t, "[eventpoll]") == 0) type = FILETYPE_EVENTPOLL; else if(strcmp(t, "[timerfd]") == 0) type = FILETYPE_TIMERFD; @@ -1943,7 +1945,6 @@ static inline void cleanup_negative_pid_fds(struct pid_stat *p) { static inline void init_pid_fds(struct pid_stat *p, size_t first, size_t size) { struct pid_fd *pfd = &p->fds[first], *pfdend = &p->fds[first + size]; - size_t i = first; while(pfd < pfdend) { #ifndef __FreeBSD__ @@ -1951,7 +1952,6 @@ static inline void init_pid_fds(struct pid_stat *p, size_t first, size_t size) { #endif clear_pid_fd(pfd); pfd++; - i++; } } @@ -2904,24 +2904,24 @@ static size_t zero_all_targets(struct target *root) { w->io_logical_bytes_read = 0; w->io_logical_bytes_written = 0; - // w->io_read_calls = 0; - // w->io_write_calls = 0; + w->io_read_calls = 0; + w->io_write_calls = 0; w->io_storage_bytes_read = 0; w->io_storage_bytes_written = 0; - // w->io_cancelled_write_bytes = 0; + w->io_cancelled_write_bytes = 0; // zero file counters if(w->target_fds) { memset(w->target_fds, 0, sizeof(int) * w->target_fds_size); - w->openfiles = 0; - w->openpipes = 0; - w->opensockets = 0; - w->openinotifies = 0; - w->openeventfds = 0; - w->opentimerfds = 0; - w->opensignalfds = 0; - w->openeventpolls = 0; - w->openother = 0; + w->openfds.files = 0; + w->openfds.pipes = 0; + w->openfds.sockets = 0; + w->openfds.inotifies = 0; + w->openfds.eventfds = 0; + w->openfds.timerfds = 0; + w->openfds.signalfds = 0; + w->openfds.eventpolls = 0; + w->openfds.other = 0; } w->collected_starttime = 0; @@ -2935,7 +2935,7 @@ static size_t zero_all_targets(struct target *root) { while(pid_on_target) { pid_on_target_to_free = pid_on_target; pid_on_target = pid_on_target->next; - free(pid_on_target_to_free); + freez(pid_on_target_to_free); } w->root_pid = NULL; @@ -2956,60 +2956,64 @@ static inline void reallocate_target_fds(struct target *w) { } } -static inline void aggregate_fd_on_target(int fd, struct target *w) { - if(unlikely(!w)) - return; - - if(unlikely(w->target_fds[fd])) { - // it is already aggregated - // just increase its usage counter - w->target_fds[fd]++; - return; - } - - // increase its usage counter - // so that we will not add it again - w->target_fds[fd]++; - - switch(all_files[fd].type) { +static void aggregage_fd_type_on_openfds(FD_FILETYPE type, struct openfds *openfds) { + switch(type) { case FILETYPE_FILE: - w->openfiles++; + openfds->files++; break; case FILETYPE_PIPE: - w->openpipes++; + openfds->pipes++; break; case FILETYPE_SOCKET: - w->opensockets++; + openfds->sockets++; break; case FILETYPE_INOTIFY: - w->openinotifies++; + openfds->inotifies++; break; case FILETYPE_EVENTFD: - w->openeventfds++; + openfds->eventfds++; break; case FILETYPE_TIMERFD: - w->opentimerfds++; + openfds->timerfds++; break; case FILETYPE_SIGNALFD: - w->opensignalfds++; + openfds->signalfds++; break; case FILETYPE_EVENTPOLL: - w->openeventpolls++; + openfds->eventpolls++; break; case FILETYPE_OTHER: - w->openother++; + openfds->other++; break; } } +static inline void aggregate_fd_on_target(int fd, struct target *w) { + if(unlikely(!w)) + return; + + if(unlikely(w->target_fds[fd])) { + // it is already aggregated + // just increase its usage counter + w->target_fds[fd]++; + return; + } + + // increase its usage counter + // so that we will not add it again + w->target_fds[fd]++; + + aggregage_fd_type_on_openfds(all_files[fd].type, &w->openfds); +} + static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) { if(unlikely(!p->updated)) { @@ -3023,6 +3027,16 @@ static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) { reallocate_target_fds(u); reallocate_target_fds(g); + p->openfds.files = 0; + p->openfds.pipes = 0; + p->openfds.sockets = 0; + p->openfds.inotifies = 0; + p->openfds.eventfds = 0; + p->openfds.timerfds = 0; + p->openfds.signalfds = 0; + p->openfds.eventpolls = 0; + p->openfds.other = 0; + long currentfds = 0; size_t c, size = p->fds_size; struct pid_fd *fds = p->fds; @@ -3033,6 +3047,7 @@ static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) { continue; currentfds++; + aggregage_fd_type_on_openfds(all_files[fd].type, &p->openfds); aggregate_fd_on_target(fd, w); aggregate_fd_on_target(fd, u); @@ -3079,11 +3094,11 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p, w->io_logical_bytes_read += p->io_logical_bytes_read; w->io_logical_bytes_written += p->io_logical_bytes_written; - // w->io_read_calls += p->io_read_calls; - // w->io_write_calls += p->io_write_calls; + w->io_read_calls += p->io_read_calls; + w->io_write_calls += p->io_write_calls; w->io_storage_bytes_read += p->io_storage_bytes_read; w->io_storage_bytes_written += p->io_storage_bytes_written; - // w->io_cancelled_write_bytes += p->io_cancelled_write_bytes; + w->io_cancelled_write_bytes += p->io_cancelled_write_bytes; w->processes++; w->num_threads += p->num_threads; @@ -3638,7 +3653,7 @@ static void send_collected_data_to_netdata(struct target *root, const char *type send_BEGIN(type, "files", dt); for (w = root; w; w = w->next) { if (unlikely(w->exposed && w->processes)) - send_SET(w->name, w->openfiles); + send_SET(w->name, w->openfds.files); } if (!strcmp("apps", type)){ kernel_uint_t usedfdpercentage = (kernel_uint_t) ((currentmaxfds * 100) / sysconf(_SC_OPEN_MAX)); @@ -3649,14 +3664,14 @@ static void send_collected_data_to_netdata(struct target *root, const char *type send_BEGIN(type, "sockets", dt); for (w = root; w; w = w->next) { if (unlikely(w->exposed && w->processes)) - send_SET(w->name, w->opensockets); + send_SET(w->name, w->openfds.sockets); } send_END(); send_BEGIN(type, "pipes", dt); for (w = root; w; w = w->next) { if (unlikely(w->exposed && w->processes)) - send_SET(w->name, w->openpipes); + send_SET(w->name, w->openfds.pipes); } send_END(); } @@ -3704,30 +3719,36 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, time_factor * RATES_DETAIL / 100, w->hidden ? "hidden" : ""); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MiB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L); } + APPS_PLUGIN_FUNCTIONS(); + fprintf(stdout, "CHART %s.vmem '' '%s Virtual Memory Size' 'MiB' mem %s.vmem stacked 20005 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20006 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20007 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); #ifndef __FreeBSD__ fprintf(stdout, "CHART %s.uptime '' '%s Carried Over Uptime' 'seconds' processes %s.uptime line 20008 %d\n", type, title, type, update_every); @@ -3735,6 +3756,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); if (enable_detailed_uptime_charts) { fprintf(stdout, "CHART %s.uptime_min '' '%s Minimum Uptime' 'seconds' processes %s.uptime_min line 20009 %d\n", type, title, type, update_every); @@ -3742,18 +3764,21 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.uptime_avg '' '%s Average Uptime' 'seconds' processes %s.uptime_avg line 20010 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.uptime_max '' '%s Maximum Uptime' 'seconds' processes %s.uptime_max line 20011 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); } #endif @@ -3762,12 +3787,14 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (100%% = 1 core)' 'percentage' cpu %s.cpu_system stacked 20021 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU); } + APPS_PLUGIN_FUNCTIONS(); if(show_guest_time) { fprintf(stdout, "CHART %s.cpu_guest '' '%s CPU Guest Time (100%% = 1 core)' 'percentage' cpu %s.cpu_guest stacked 20022 %d\n", type, title, type, update_every); @@ -3775,6 +3802,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU); } + APPS_PLUGIN_FUNCTIONS(); } #ifndef __FreeBSD__ @@ -3783,6 +3811,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L); } + APPS_PLUGIN_FUNCTIONS(); #endif fprintf(stdout, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20012 %d\n", type, title, type, update_every); @@ -3790,12 +3819,14 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.minor_faults '' '%s Minor Page Faults' 'page faults/s' mem %s.minor_faults stacked 20011 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); #ifdef __FreeBSD__ fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'blocks/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every); @@ -3803,36 +3834,42 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'blocks/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); #else fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'KiB/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'KiB/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.lreads '' '%s Disk Logical Reads' 'KiB/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.lwrites '' '%s I/O Logical Writes' 'KiB/s' disk %s.lwrites stacked 20042 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL); } + APPS_PLUGIN_FUNCTIONS(); #endif if(enable_file_charts) { @@ -3842,6 +3879,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if (unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.sockets '' '%s Open Sockets' 'open sockets' net %s.sockets stacked 20051 %d\n", type, title, type, update_every); @@ -3849,6 +3887,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if (unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); fprintf(stdout, "CHART %s.pipes '' '%s Pipes' 'open pipes' processes %s.pipes stacked 20053 %d\n", type, title, type, update_every); @@ -3856,6 +3895,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if (unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name); } + APPS_PLUGIN_FUNCTIONS(); } } @@ -4134,6 +4174,664 @@ static int check_capabilities() { } #endif +netdata_mutex_t mutex = NETDATA_MUTEX_INITIALIZER; + +#define PROCESS_FILTER_CATEGORY "category:" +#define PROCESS_FILTER_USER "user:" +#define PROCESS_FILTER_GROUP "group:" +#define PROCESS_FILTER_PROCESS "process:" +#define PROCESS_FILTER_PID "pid:" +#define PROCESS_FILTER_UID "uid:" +#define PROCESS_FILTER_GID "gid:" + +static struct target *find_target_by_name(struct target *base, const char *name) { + struct target *t; + for(t = base; t ; t = t->next) { + if (strcmp(t->name, name) == 0) + return t; + } + + return NULL; +} + +static kernel_uint_t MemTotal = 0; + +static void get_MemTotal(void) { +#ifdef __FreeBSD__ + // TODO - fix this for FreeBSD + return; +#else + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s/proc/meminfo", netdata_configured_host_prefix); + + procfile *ff = procfile_open(filename, ": \t", PROCFILE_FLAG_DEFAULT); + if(!ff) + return; + + ff = procfile_readall(ff); + if(!ff) + return; + + size_t line, lines = procfile_lines(ff); + + for(line = 0; line < lines ;line++) { + size_t words = procfile_linewords(ff, line); + if(words == 3 && strcmp(procfile_lineword(ff, line, 0), "MemTotal") == 0 && strcmp(procfile_lineword(ff, line, 2), "kB") == 0) { + kernel_uint_t n = str2ull(procfile_lineword(ff, line, 1)); + if(n) MemTotal = n; + break; + } + } + + procfile_close(ff); +#endif +} + +static void apps_plugin_function_error(const char *transaction, int code, const char *msg) { + char buffer[PLUGINSD_LINE_MAX + 1]; + json_escape_string(buffer, msg, PLUGINSD_LINE_MAX); + + pluginsd_function_result_begin_to_stdout(transaction, code, "application/json", now_realtime_sec()); + fprintf(stdout, "{\"status\":%d,\"error_message\":\"%s\"}", code, buffer); + pluginsd_function_result_end_to_stdout(); +} + +static void apps_plugin_function_processes_help(const char *transaction) { + pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "text/plain", now_realtime_sec() + 3600); + fprintf(stdout, "%s", + "apps.plugin / processes\n" + "\n" + "Function `processes` presents all the currently running processes of the system.\n" + "\n" + "The following filters are supported:\n" + "\n" + " category:NAME\n" + " Shows only processes that are assigned the category `NAME` in apps_groups.conf\n" + "\n" + " user:NAME\n" + " Shows only processes that are running as user name `NAME`.\n" + "\n" + " group:NAME\n" + " Shows only processes that are running as group name `NAME`.\n" + "\n" + " process:NAME\n" + " Shows only processes that their Command is `NAME` or their parent's Command is `NAME`.\n" + "\n" + " pid:NUMBER\n" + " Shows only processes that their PID is `NUMBER` or their parent's PID is `NUMBER`\n" + "\n" + " uid:NUMBER\n" + " Shows only processes that their UID is `NUMBER`\n" + "\n" + " gid:NUMBER\n" + " Shows only processes that their GID is `NUMBER`\n" + "\n" + "Filters can be combined. Each filter can be given only one time.\n" + ); + pluginsd_function_result_end_to_stdout(); +} + +#define add_table_field(wb, key, name, visible, type, units, max, sort, sortable, sticky, unique_key, pointer_to, summary) do { \ + if(fields_added) buffer_strcat(wb, ","); \ + buffer_sprintf(wb, "\n \"%s\": {", key); \ + buffer_sprintf(wb, "\n \"index\":%d,", fields_added); \ + buffer_sprintf(wb, "\n \"unique_key\":%s,", (unique_key)?"true":"false"); \ + buffer_sprintf(wb, "\n \"name\":\"%s\",", name); \ + buffer_sprintf(wb, "\n \"visible\":%s,", (visible)?"true":"false"); \ + buffer_sprintf(wb, "\n \"type\":\"%s\",", type); \ + if(units) \ + buffer_sprintf(wb, "\n \"units\":\"%s\",", (char*)(units)); \ + if(!isnan((NETDATA_DOUBLE)(max))) \ + buffer_sprintf(wb, "\n \"max\":%f,", (NETDATA_DOUBLE)(max)); \ + if(pointer_to) \ + buffer_sprintf(wb, "\n \"pointer_to\":\"%s\",", (char *)(pointer_to)); \ + buffer_sprintf(wb, "\n \"sort\":\"%s\",", sort); \ + buffer_sprintf(wb, "\n \"sortable\":%s,", (sortable)?"true":"false"); \ + buffer_sprintf(wb, "\n \"sticky\":%s,", (sticky)?"true":"false"); \ + buffer_sprintf(wb, "\n \"summary\":\"%s\"", summary); \ + buffer_sprintf(wb, "\n }"); \ + fields_added++; \ +} while(0) + +#define add_value_field_llu_with_max(wb, key, value) do { \ + unsigned long long _tmp = (value); \ + key ## _max = (rows == 0) ? (_tmp) : MAX(key ## _max, _tmp); \ + buffer_fast_strcat(wb, ",", 1); \ + buffer_print_llu(wb, _tmp); \ +} while(0) + +#define add_value_field_ndd_with_max(wb, key, value) do { \ + NETDATA_DOUBLE _tmp = (value); \ + key ## _max = (rows == 0) ? (_tmp) : MAX(key ## _max, _tmp); \ + buffer_fast_strcat(wb, ",", 1); \ + buffer_rrd_value(wb, _tmp); \ +} while(0) + +static void apps_plugin_function_processes(const char *transaction, char *function __maybe_unused, char *line_buffer __maybe_unused, int line_max __maybe_unused, int timeout __maybe_unused) { + struct pid_stat *p; + + char *words[PLUGINSD_MAX_WORDS] = { NULL }; + size_t num_words = pluginsd_split_words(function, words, PLUGINSD_MAX_WORDS, NULL, NULL, 0); + + struct target *category = NULL, *user = NULL, *group = NULL; + const char *process_name = NULL; + pid_t pid = 0; + uid_t uid = 0; + gid_t gid = 0; + + bool filter_pid = false, filter_uid = false, filter_gid = false; + + for(int i = 1; i < PLUGINSD_MAX_WORDS ;i++) { + const char *keyword = get_word(words, num_words, i); + if(!keyword) break; + + if(!category && strncmp(keyword, PROCESS_FILTER_CATEGORY, strlen(PROCESS_FILTER_CATEGORY)) == 0) { + category = find_target_by_name(apps_groups_root_target, &keyword[strlen(PROCESS_FILTER_CATEGORY)]); + if(!category) { + apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, "No category with that name found."); + return; + } + } + else if(!user && strncmp(keyword, PROCESS_FILTER_USER, strlen(PROCESS_FILTER_USER)) == 0) { + user = find_target_by_name(users_root_target, &keyword[strlen(PROCESS_FILTER_USER)]); + if(!user) { + apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, "No user with that name found."); + return; + } + } + else if(strncmp(keyword, PROCESS_FILTER_GROUP, strlen(PROCESS_FILTER_GROUP)) == 0) { + group = find_target_by_name(groups_root_target, &keyword[strlen(PROCESS_FILTER_GROUP)]); + if(!group) { + apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, "No group with that name found."); + return; + } + } + else if(!process_name && strncmp(keyword, PROCESS_FILTER_PROCESS, strlen(PROCESS_FILTER_PROCESS)) == 0) { + process_name = &keyword[strlen(PROCESS_FILTER_PROCESS)]; + } + else if(!pid && strncmp(keyword, PROCESS_FILTER_PID, strlen(PROCESS_FILTER_PID)) == 0) { + pid = str2i(&keyword[strlen(PROCESS_FILTER_PID)]); + filter_pid = true; + } + else if(!uid && strncmp(keyword, PROCESS_FILTER_UID, strlen(PROCESS_FILTER_UID)) == 0) { + uid = str2i(&keyword[strlen(PROCESS_FILTER_UID)]); + filter_uid = true; + } + else if(!gid && strncmp(keyword, PROCESS_FILTER_GID, strlen(PROCESS_FILTER_GID)) == 0) { + gid = str2i(&keyword[strlen(PROCESS_FILTER_GID)]); + filter_gid = true; + } + else if(strcmp(keyword, "help") == 0) { + apps_plugin_function_processes_help(transaction); + return; + } + else { + char msg[PLUGINSD_LINE_MAX]; + snprintfz(msg, PLUGINSD_LINE_MAX, "Invalid parameter '%s'", keyword); + apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, msg); + return; + } + } + + time_t expires = now_realtime_sec() + update_every; + pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires); + + unsigned int cpu_divisor = time_factor * RATES_DETAIL / 100; + unsigned int memory_divisor = 1024; + unsigned int io_divisor = 1024 * RATES_DETAIL; + + BUFFER *wb = buffer_create(PLUGINSD_LINE_MAX); + buffer_sprintf(wb, + "{" + "\n \"status\":%d" + ",\n \"type\":\"table\"" + ",\n \"update_every\":%d" + ",\n \"data\":[" + "\n" + , HTTP_RESP_OK + , update_every + ); + + NETDATA_DOUBLE + UserCPU_max = 0.0 + , SysCPU_max = 0.0 + , GuestCPU_max = 0.0 + , CUserCPU_max = 0.0 + , CSysCPU_max = 0.0 + , CGuestCPU_max = 0.0 + , CPU_max = 0.0 + , VMSize_max = 0.0 + , RSS_max = 0.0 + , Shared_max = 0.0 + , Swap_max = 0.0 + , MemPcnt_max = 0.0 + ; + + unsigned long long + Processes_max = 0 + , Threads_max = 0 + , Uptime_max = 0 + , MinFlt_max = 0 + , CMinFlt_max = 0 + , TMinFlt_max = 0 + , MajFlt_max = 0 + , CMajFlt_max = 0 + , TMajFlt_max = 0 + , PReads_max = 0 + , PWrites_max = 0 + , RCalls_max = 0 + , WCalls_max = 0 + , Files_max = 0 + , Pipes_max = 0 + , Sockets_max = 0 + , iNotiFDs_max = 0 + , EventFDs_max = 0 + , TimerFDs_max = 0 + , SigFDs_max = 0 + , EvPollFDs_max = 0 + , OtherFDs_max = 0 + , FDs_max = 0 + ; + +#ifndef __FreeBSD__ + unsigned long long + LReads_max = 0 + , LWrites_max = 0 + ; +#endif + + int rows= 0; + for(p = root_of_pids; p ; p = p->next) { + if(!p->updated) + continue; + + if(category && p->target != category) + continue; + + if(user && p->user_target != user) + continue; + + if(group && p->group_target != group) + continue; + + if(process_name && ((strcmp(p->comm, process_name) != 0 && !p->parent) || (p->parent && strcmp(p->comm, process_name) != 0 && strcmp(p->parent->comm, process_name) != 0))) + continue; + + if(filter_pid && p->pid != pid && p->ppid != pid) + continue; + + if(filter_uid && p->uid != uid) + continue; + + if(filter_gid && p->gid != gid) + continue; + + if(rows) buffer_fast_strcat(wb, ",\n", 2); + rows++; + + buffer_strcat(wb, " ["); + + // IMPORTANT! + // THE ORDER SHOULD BE THE SAME WITH THE FIELDS! + + // pid + buffer_print_llu(wb, p->pid); + + // cmd + buffer_fast_strcat(wb, ",\"", 2); + buffer_strcat_jsonescape(wb, p->comm); + buffer_fast_strcat(wb, "\"", 1); + +#ifdef NETDATA_DEV_MODE + // cmdline + buffer_fast_strcat(wb, ",\"", 2); + buffer_strcat_jsonescape(wb, (p->cmdline && *p->cmdline) ? p->cmdline : p->comm); + buffer_fast_strcat(wb, "\"", 1); +#endif + + // ppid + buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->ppid); + + // category + buffer_fast_strcat(wb, ",\"", 2); + buffer_strcat_jsonescape(wb, p->target ? p->target->name : "-"); + buffer_fast_strcat(wb, "\"", 1); + + // user + buffer_fast_strcat(wb, ",\"", 2); + buffer_strcat_jsonescape(wb, p->user_target ? p->user_target->name : "-"); + buffer_fast_strcat(wb, "\"", 1); + + // uid + buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->uid); + + // group + buffer_fast_strcat(wb, ",\"", 2); + buffer_strcat_jsonescape(wb, p->group_target ? p->group_target->name : "-"); + buffer_fast_strcat(wb, "\"", 1); + + // gid + buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->gid); + + // procs + add_value_field_llu_with_max(wb, Processes, p->children_count); + + // threads + add_value_field_llu_with_max(wb, Threads, p->num_threads); + + // uptime + add_value_field_llu_with_max(wb, Uptime, p->uptime); + + // minor page faults + add_value_field_llu_with_max(wb, MinFlt, p->minflt / RATES_DETAIL); + add_value_field_llu_with_max(wb, CMinFlt, p->cminflt / RATES_DETAIL); + add_value_field_llu_with_max(wb, TMinFlt, (p->minflt + p->cminflt) / RATES_DETAIL); + + // major page faults + add_value_field_llu_with_max(wb, MajFlt, p->majflt / RATES_DETAIL); + add_value_field_llu_with_max(wb, CMajFlt, p->cmajflt / RATES_DETAIL); + add_value_field_llu_with_max(wb, TMajFlt, (p->majflt + p->cmajflt) / RATES_DETAIL); + + // CPU utilization % + add_value_field_ndd_with_max(wb, UserCPU, (NETDATA_DOUBLE)(p->utime) / cpu_divisor); + add_value_field_ndd_with_max(wb, SysCPU, (NETDATA_DOUBLE)(p->stime) / cpu_divisor); + add_value_field_ndd_with_max(wb, GuestCPU, (NETDATA_DOUBLE)(p->gtime) / cpu_divisor); + add_value_field_ndd_with_max(wb, CUserCPU, (NETDATA_DOUBLE)(p->cutime) / cpu_divisor); + add_value_field_ndd_with_max(wb, CSysCPU, (NETDATA_DOUBLE)(p->cstime) / cpu_divisor); + add_value_field_ndd_with_max(wb, CGuestCPU, (NETDATA_DOUBLE)(p->cgtime) / cpu_divisor); + add_value_field_ndd_with_max(wb, CPU, (NETDATA_DOUBLE)(p->utime + p->stime + p->gtime + p->cutime + p->cstime + p->cgtime) / cpu_divisor); + + // memory MiB + add_value_field_ndd_with_max(wb, VMSize, (NETDATA_DOUBLE)p->status_vmsize / memory_divisor); + add_value_field_ndd_with_max(wb, RSS, (NETDATA_DOUBLE)p->status_vmrss / memory_divisor); + add_value_field_ndd_with_max(wb, Shared, (NETDATA_DOUBLE)p->status_vmshared / memory_divisor); + add_value_field_ndd_with_max(wb, Swap, (NETDATA_DOUBLE)p->status_vmswap / memory_divisor); + + if(MemTotal) + add_value_field_ndd_with_max(wb, MemPcnt, (NETDATA_DOUBLE)p->status_vmrss * 100.0 / (NETDATA_DOUBLE)MemTotal); + + // Logical I/O +#ifndef __FreeBSD__ + add_value_field_llu_with_max(wb, LReads, p->io_logical_bytes_read / io_divisor); + add_value_field_llu_with_max(wb, LWrites, p->io_logical_bytes_written / io_divisor); +#endif + + // Physical I/O + add_value_field_llu_with_max(wb, PReads, p->io_storage_bytes_read / io_divisor); + add_value_field_llu_with_max(wb, PWrites, p->io_storage_bytes_written / io_divisor); + + // I/O calls + add_value_field_llu_with_max(wb, RCalls, p->io_read_calls / RATES_DETAIL); + add_value_field_llu_with_max(wb, WCalls, p->io_write_calls / RATES_DETAIL); + + // open file descriptors + add_value_field_llu_with_max(wb, Files, p->openfds.files); + add_value_field_llu_with_max(wb, Pipes, p->openfds.pipes); + add_value_field_llu_with_max(wb, Sockets, p->openfds.sockets); + add_value_field_llu_with_max(wb, iNotiFDs, p->openfds.inotifies); + add_value_field_llu_with_max(wb, EventFDs, p->openfds.eventfds); + add_value_field_llu_with_max(wb, TimerFDs, p->openfds.timerfds); + add_value_field_llu_with_max(wb, SigFDs, p->openfds.signalfds); + add_value_field_llu_with_max(wb, EvPollFDs, p->openfds.eventpolls); + add_value_field_llu_with_max(wb, OtherFDs, p->openfds.other); + add_value_field_llu_with_max(wb, FDs, p->openfds.files + p->openfds.pipes + p->openfds.sockets + p->openfds.inotifies + p->openfds.eventfds + p->openfds.timerfds + p->openfds.signalfds + p->openfds.eventpolls + p->openfds.other); + + buffer_fast_strcat(wb, "]", 1); + + fwrite(buffer_tostring(wb), buffer_strlen(wb), 1, stdout); + buffer_flush(wb); + } + + { + int fields_added = 0; + + buffer_flush(wb); + buffer_sprintf(wb, "\n ],\n \"columns\": {"); + + // IMPORTANT! + // THE ORDER SHOULD BE THE SAME WITH THE VALUES! + add_table_field(wb, "Pid", "Process ID", true, "integer", NULL, NAN, "ascending", true, true, true, NULL, "count_unique"); + add_table_field(wb, "Cmd", "Process Name", true, "string", NULL, NAN, "ascending", true, true, false, NULL, "count_unique"); + +#ifdef NETDATA_DEV_MODE + add_table_field(wb, "CmdLine", "Command Line", false, "detail-string:Cmd", NULL, NAN, "ascending", true, false, false, NULL, "count_unique"); +#endif + add_table_field(wb, "PPid", "Parent Process ID", false, "integer", NULL, NAN, "ascending", true, false, false, "Pid", "count_unique"); + add_table_field(wb, "Category", "Category (apps_groups.conf)", true, "string", NULL, NAN, "ascending", true, true, false, NULL, "count_unique"); + add_table_field(wb, "User", "User Owner", true, "string", NULL, NAN, "ascending", true, false, false, NULL, "count_unique"); + add_table_field(wb, "Uid", "User ID", false, "integer", NULL, NAN, "ascending", true, false, false, NULL, "count_unique"); + add_table_field(wb, "Group", "Group Owner", false, "string", NULL, NAN, "ascending", true, false, false, NULL, "count_unique"); + add_table_field(wb, "Gid", "Group ID", false, "integer", NULL, NAN, "ascending", true, false, false, NULL, "count_unique"); + add_table_field(wb, "Processes", "Processes", true, "bar-with-integer", "processes", Processes_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "Threads", "Threads", true, "bar-with-integer", "threads", Threads_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "Uptime", "Uptime in seconds", true, "duration", "seconds", Uptime_max, "descending", true, false, false, NULL, "max"); + + // minor page faults + add_table_field(wb, "MinFlt", "Minor Page Faults/s", false, "bar", "pgflts/s", MinFlt_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "CMinFlt", "Children Minor Page Faults/s", false, "bar", "pgflts/s", CMinFlt_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "TMinFlt", "Total Minor Page Faults/s", false, "bar", "pgflts/s", TMinFlt_max, "descending", true, false, false, NULL, "sum"); + + // major page faults + add_table_field(wb, "MajFlt", "Major Page Faults/s", false, "bar", "pgflts/s", MajFlt_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "CMajFlt", "Children Major Page Faults/s", false, "bar", "pgflts/s", CMajFlt_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "TMajFlt", "Total Major Page Faults/s", true, "bar", "pgflts/s", TMajFlt_max, "descending", true, false, false, NULL, "sum"); + + // CPU utilization + add_table_field(wb, "UserCPU", "User CPU time", false, "bar", "%", UserCPU_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "SysCPU", "System CPU Time", false, "bar", "%", SysCPU_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "GuestCPU", "Guest CPU Time", false, "bar", "%", GuestCPU_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "CUserCPU", "Children User CPU Time", false, "bar", "%", CUserCPU_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "CSysCPU", "Children System CPU Time", false, "bar", "%", CSysCPU_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "CGuestCPU", "Children Guest CPU Time", false, "bar", "%", CGuestCPU_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "CPU", "Total CPU Time", true, "bar", "%", CPU_max, "descending", true, false, false, NULL, "sum"); + + // memory + add_table_field(wb, "VMSize", "Virtual Memory Size", false, "bar", "MiB", VMSize_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "RSS", "Resident Set Size", MemTotal ? false : true, "bar", "MiB", RSS_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "Shared", "Shared Pages", false, "bar", "MiB", Shared_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "Swap", "Swap Memory", false, "bar", "MiB", Swap_max, "descending", true, false, false, NULL, "sum"); + + if(MemTotal) + add_table_field(wb, "MemPcnt", "Memory Percentage", true, "bar", "%", 100.0, "descending", true, false, false, NULL, "sum"); + + // Logical I/O +#ifndef __FreeBSD__ + add_table_field(wb, "LReads", "Logical I/O Reads", false, "bar", "KiB/s", LReads_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "LWrites", "Logical I/O Writes", false, "bar", "KiB/s", LWrites_max, "descending", true, false, false, NULL, "sum"); +#endif + + // Physical I/O + add_table_field(wb, "PReads", "Physical I/O Reads", true, "bar", "KiB/s", PReads_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "PWrites", "Physical I/O Writes", true, "bar", "KiB/s", PWrites_max, "descending", true, false, false, NULL, "sum"); + + // I/O calls + add_table_field(wb, "RCalls", "I/O Read Calls", false, "bar", "calls/s", RCalls_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "WCalls", "I/O Write Calls", false, "bar", "calls/s", WCalls_max, "descending", true, false, false, NULL, "sum"); + + // open file descriptors + add_table_field(wb, "Files", "Open Files", false, "bar", "fds", Files_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "Pipes", "Open Pipes", false, "bar", "fds", Pipes_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "Sockets", "Open Sockets", false, "bar", "fds", Sockets_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "iNotiFDs", "Open iNotify Descriptors", false, "bar", "fds", iNotiFDs_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "EventFDs", "Open Event Descriptors", false, "bar", "fds", EventFDs_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "TimerFDs", "Open Timer Descriptors", false, "bar", "fds", TimerFDs_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "SigFDs", "Open Signal Descriptors", false, "bar", "fds", SigFDs_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "EvPollFDs", "Open Event Poll Descriptors", false, "bar", "fds", EvPollFDs_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "OtherFDs", "Other Open Descriptors", false, "bar", "fds", OtherFDs_max, "descending", true, false, false, NULL, "sum"); + add_table_field(wb, "FDs", "All Open File Descriptors", true, "bar", "fds", FDs_max, "descending", true, false, false, NULL, "sum"); + + buffer_strcat( + wb, + "" + "\n }," + "\n \"default_sort_column\": \"CPU\"," + "\n \"charts\": {" + "\n \"CPU\": {" + "\n \"name\":\"CPU Utilization\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"UserCPU\", \"SysCPU\", \"GuestCPU\", \"CUserCPU\", \"CSysCPU\", \"CGuestCPU\" ]" + "\n }," + "\n \"Memory\": {" + "\n \"name\":\"Memory\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"VMSize\", \"RSS\", \"Shared\", \"Swap\" ]" + "\n }," + ); + + if(MemTotal) + buffer_strcat( + wb, + "" + "\n \"MemoryPercent\": {" + "\n \"name\":\"Memory Percentage\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"MemPcnt\" ]" + "\n }," + ); + + buffer_strcat( + wb, "" + #ifndef __FreeBSD__ + "\n \"Reads\": {" + "\n \"name\":\"I/O Reads\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"LReads\", \"PReads\" ]" + "\n }," + "\n \"Writes\": {" + "\n \"name\":\"I/O Writes\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"LWrites\", \"PWrites\" ]" + "\n }," + "\n \"LogicalIO\": {" + "\n \"name\":\"Logical I/O\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"LReads\", \"LWrites\" ]" + "\n }," + #endif + "\n \"PhysicalIO\": {" + "\n \"name\":\"Physical I/O\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"PReads\", \"PWrites\" ]" + "\n }," + "\n \"IOCalls\": {" + "\n \"name\":\"I/O Calls\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"RCalls\", \"WCalls\" ]" + "\n }," + "\n \"MinFlt\": {" + "\n \"name\":\"Minor Page Faults\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"MinFlt\", \"CMinFlt\" ]" + "\n }," + "\n \"MajFlt\": {" + "\n \"name\":\"Major Page Faults\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"MajFlt\", \"CMajFlt\" ]" + "\n }," + "\n \"Threads\": {" + "\n \"name\":\"Threads\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"Threads\" ]" + "\n }," + "\n \"Processes\": {" + "\n \"name\":\"Processes\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"Processes\" ]" + "\n }," + "\n \"FDs\": {" + "\n \"name\":\"File Descriptors\"," + "\n \"type\":\"stacked-bar\"," + "\n \"columns\": [ \"Files\", \"Pipes\", \"Sockets\", \"iNotiFDs\", \"EventFDs\", \"TimerFDs\", \"SigFDs\", \"EvPollFDs\", \"OtherFDs\" ]" + "\n }" + "\n }," + "\n \"group_by\": {" + "\n \"pid\": {" + "\n \"name\":\"Process Tree by PID\"," + "\n \"columns\":[ \"PPid\" ]" + "\n }," + "\n \"category\": {" + "\n \"name\":\"Process Tree by Category\"," + "\n \"columns\":[ \"Category\", \"PPid\" ]" + "\n }," + "\n \"user\": {" + "\n \"name\":\"Process Tree by User\"," + "\n \"columns\":[ \"User\", \"PPid\" ]" + "\n }," + "\n \"group\": {" + "\n \"name\":\"Process Tree by Group\"," + "\n \"columns\":[ \"Group\", \"PPid\" ]" + "\n }" + "\n }" + ); + + fwrite(buffer_tostring(wb), buffer_strlen(wb), 1, stdout); + } + + buffer_free(wb); + + fprintf(stdout, ",\n \"expires\":%lld", (long long)expires); + fprintf(stdout, "\n}"); + + pluginsd_function_result_end_to_stdout(); +} + +bool apps_plugin_exit = false; + +void *reader_main(void *arg __maybe_unused) { + char buffer[PLUGINSD_LINE_MAX + 1]; + + char *s = NULL; + while(!apps_plugin_exit && (s = fgets(buffer, PLUGINSD_LINE_MAX, stdin))) { + + char *words[PLUGINSD_MAX_WORDS] = { NULL }; + size_t num_words = pluginsd_split_words(buffer, words, PLUGINSD_MAX_WORDS, NULL, NULL, 0); + + const char *keyword = get_word(words, num_words, 0); + + if(keyword && strcmp(keyword, PLUGINSD_KEYWORD_FUNCTION) == 0) { + char *transaction = get_word(words, num_words, 1); + char *timeout_s = get_word(words, num_words, 2); + char *function = get_word(words, num_words, 3); + + if(!transaction || !*transaction || !timeout_s || !*timeout_s || !function || !*function) { + error("Received incomplete %s (transaction = '%s', timeout = '%s', function = '%s'). Ignoring it.", + keyword, + transaction?transaction:"(unset)", + timeout_s?timeout_s:"(unset)", + function?function:"(unset)"); + } + else { + int timeout = str2i(timeout_s); + if(timeout <= 0) timeout = PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT; + +// internal_error(true, "Received function '%s', transaction '%s', timeout %d", function, transaction, timeout); + + netdata_mutex_lock(&mutex); + + if(strncmp(function, "processes", strlen("processes")) == 0) + apps_plugin_function_processes(transaction, function, buffer, PLUGINSD_LINE_MAX + 1, timeout); + else + apps_plugin_function_error(transaction, HTTP_RESP_NOT_FOUND, "No function with this name found in apps.plugin."); + + fflush(stdout); + netdata_mutex_unlock(&mutex); + +// internal_error(true, "Done with function '%s', transaction '%s', timeout %d", function, transaction, timeout); + } + } + else + error("Received unknown command: %s", keyword?keyword:"(unset)"); + } + + if(!s || feof(stdin) || ferror(stdin)) { + apps_plugin_exit = true; + error("Received error on stdin."); + } + + exit(1); + return NULL; +} + int main(int argc, char **argv) { // debug_flags = D_PROCFILE; @@ -4151,6 +4849,13 @@ int main(int argc, char **argv) { error_log_errors_per_period = 100; error_log_throttle_period = 3600; + bool send_resource_usage = true; + { + const char *s = getenv("NETDATA_INTERNALS_MONITORING"); + if(s && *s && strcmp(s, "NO") == 0) + send_resource_usage = false; + } + // since apps.plugin runs as root, prevent it from opening symbolic links procfile_open_flags = O_RDONLY|O_NOFOLLOW; @@ -4224,16 +4929,21 @@ int main(int argc, char **argv) { debug_log("group file: '%s'", all_group_ids.filename); #if (ALL_PIDS_ARE_READ_INSTANTLY == 0) - all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max); + all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max + 1); #endif - all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max); + all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max + 1); + + netdata_thread_t reader_thread; + netdata_thread_create(&reader_thread, "APPS_READER", NETDATA_THREAD_OPTION_DONT_LOG, reader_main, NULL); + netdata_mutex_lock(&mutex); usec_t step = update_every * USEC_PER_SEC; global_iterations_counter = 1; heartbeat_t hb; heartbeat_init(&hb); - for(;1; global_iterations_counter++) { + for(; !apps_plugin_exit ; global_iterations_counter++) { + netdata_mutex_unlock(&mutex); #ifdef NETDATA_PROFILING #warning "compiling for profiling" @@ -4244,16 +4954,28 @@ int main(int argc, char **argv) { #else usec_t dt = heartbeat_next(&hb, step); #endif + netdata_mutex_lock(&mutex); struct pollfd pollfd = { .fd = fileno(stdout), .events = POLLERR }; - if (unlikely(poll(&pollfd, 1, 0) < 0)) + if (unlikely(poll(&pollfd, 1, 0) < 0)) { + netdata_mutex_unlock(&mutex); + netdata_thread_cancel(reader_thread); fatal("Cannot check if a pipe is available"); - if (unlikely(pollfd.revents & POLLERR)) - fatal("Cannot write to a pipe"); + } + if (unlikely(pollfd.revents & POLLERR)) { + netdata_mutex_unlock(&mutex); + netdata_thread_cancel(reader_thread); + fatal("Received error on read pipe."); + } + + if(global_iterations_counter % 10 == 0) + get_MemTotal(); if(!collect_data_for_all_processes()) { error("Cannot collect /proc data for running processes. Disabling apps.plugin..."); printf("DISABLE\n"); + netdata_mutex_unlock(&mutex); + netdata_thread_cancel(reader_thread); exit(1); } @@ -4261,7 +4983,8 @@ int main(int argc, char **argv) { calculate_netdata_statistics(); normalize_utilization(apps_groups_root_target); - send_resource_usage_to_netdata(dt); + if(send_resource_usage) + send_resource_usage_to_netdata(dt); #ifndef __FreeBSD__ send_proc_states_count(dt); diff --git a/collectors/cgroups.plugin/cgroup-name.sh b/collectors/cgroups.plugin/cgroup-name.sh index d1277b745..55b02ac72 100755 --- a/collectors/cgroups.plugin/cgroup-name.sh +++ b/collectors/cgroups.plugin/cgroup-name.sh @@ -450,7 +450,10 @@ function k8s_get_name() { function docker_get_name() { local id="${1}" - if hash docker 2> /dev/null; then + # See https://github.com/netdata/netdata/pull/13523 for details + if command -v snap >/dev/null 2>&1 && snap list docker >/dev/null 2>&1; then + docker_like_get_name_api DOCKER_HOST "${id}" + elif hash docker 2> /dev/null; then docker_like_get_name_command docker "${id}" else docker_like_get_name_api DOCKER_HOST "${id}" || docker_like_get_name_command podman "${id}" diff --git a/collectors/cgroups.plugin/cgroup-network-helper.sh b/collectors/cgroups.plugin/cgroup-network-helper.sh index 07318d774..783332f73 100755 --- a/collectors/cgroups.plugin/cgroup-network-helper.sh +++ b/collectors/cgroups.plugin/cgroup-network-helper.sh @@ -150,6 +150,7 @@ virsh_cgroup_to_domain_name() { # extract for the cgroup path sed -n -e "s|.*/machine-qemu\\\\x2d[0-9]\+\\\\x2d\(.*\)\.scope$|\1|p" \ + -e "s|.*/machine/qemu-[0-9]\+-\(.*\)\.libvirt-qemu$|\1|p" \ -e "s|.*/machine/\(.*\)\.libvirt-qemu$|\1|p" \ <<EOF ${c} diff --git a/collectors/cgroups.plugin/cgroup-network.c b/collectors/cgroups.plugin/cgroup-network.c index ec3d814c6..0b66ea475 100644 --- a/collectors/cgroups.plugin/cgroup-network.c +++ b/collectors/cgroups.plugin/cgroup-network.c @@ -506,21 +506,21 @@ void call_the_helper(pid_t pid, const char *cgroup) { info("running: %s", command); pid_t cgroup_pid; - FILE *fp; + FILE *fp_child_input, *fp_child_output; if(cgroup) { - (void)mypopen_raw_default_flags(&cgroup_pid, environment, &fp, PLUGINS_DIR "/cgroup-network-helper.sh", "--cgroup", cgroup); + (void)netdata_popen_raw_default_flags(&cgroup_pid, environment, &fp_child_input, &fp_child_output, PLUGINS_DIR "/cgroup-network-helper.sh", "--cgroup", cgroup); } else { char buffer[100]; snprintfz(buffer, sizeof(buffer) - 1, "%d", pid); - (void)mypopen_raw_default_flags(&cgroup_pid, environment, &fp, PLUGINS_DIR "/cgroup-network-helper.sh", "--pid", buffer); + (void)netdata_popen_raw_default_flags(&cgroup_pid, environment, &fp_child_input, &fp_child_output, PLUGINS_DIR "/cgroup-network-helper.sh", "--pid", buffer); } - if(fp) { + if(fp_child_output) { char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; char *s; - while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) { + while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp_child_output))) { trim(s); if(*s && *s != '\n') { @@ -536,7 +536,7 @@ void call_the_helper(pid_t pid, const char *cgroup) { } } - mypclose(fp, cgroup_pid); + netdata_pclose(fp_child_input, fp_child_output, cgroup_pid); } else error("cannot execute cgroup-network helper script: %s", command); diff --git a/collectors/cgroups.plugin/sys_fs_cgroup.c b/collectors/cgroups.plugin/sys_fs_cgroup.c index 330562173..8f7548286 100644 --- a/collectors/cgroups.plugin/sys_fs_cgroup.c +++ b/collectors/cgroups.plugin/sys_fs_cgroup.c @@ -37,6 +37,8 @@ // ---------------------------------------------------------------------------- // cgroup globals +static char cgroup_chart_id_prefix[] = "cgroup_"; + static int is_inside_k8s = 0; static long system_page_size = 4096; // system will be queried via sysconf() in configuration() @@ -151,14 +153,15 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec) char buf[MAXSIZE_PROC_CMDLINE]; char *begin, *end; - FILE *f = mypopen(exec, &command_pid); + FILE *fp_child_input; + FILE *fp_child_output = netdata_popen(exec, &command_pid, &fp_child_input); - if (!f) + if (!fp_child_output) return retval; fd_set rfds; struct timeval timeout; - int fd = fileno(f); + int fd = fileno(fp_child_output); int ret = -1; FD_ZERO(&rfds); @@ -175,7 +178,7 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec) } else if (ret == 0) { info("Cannot get the output of \"%s\" within %"PRId64" seconds", exec, (int64_t)timeout.tv_sec); } else { - while (fgets(buf, MAXSIZE_PROC_CMDLINE, f) != NULL) { + while (fgets(buf, MAXSIZE_PROC_CMDLINE, fp_child_output) != NULL) { if ((begin = strstr(buf, SYSTEMD_HIERARCHY_STRING))) { end = begin = begin + strlen(SYSTEMD_HIERARCHY_STRING); if (!*begin) @@ -194,7 +197,7 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec) } } - if (mypclose(f, command_pid)) + if (netdata_pclose(fp_child_input, fp_child_output, command_pid)) return SYSTEMD_CGROUP_ERR; return retval; @@ -208,18 +211,19 @@ static enum cgroups_type cgroups_try_detect_version() int cgroups2_available = 0; // 1. check if cgroups2 available on system at all - FILE *f = mypopen("grep cgroup /proc/filesystems", &command_pid); - if (!f) { + FILE *fp_child_input; + FILE *fp_child_output = netdata_popen("grep cgroup /proc/filesystems", &command_pid, &fp_child_input); + if (!fp_child_output) { error("popen failed"); return CGROUPS_AUTODETECT_FAIL; } - while (fgets(buf, MAXSIZE_PROC_CMDLINE, f) != NULL) { + while (fgets(buf, MAXSIZE_PROC_CMDLINE, fp_child_output) != NULL) { if (strstr(buf, "cgroup2")) { cgroups2_available = 1; break; } } - if(mypclose(f, command_pid)) + if(netdata_pclose(fp_child_input, fp_child_output, command_pid)) return CGROUPS_AUTODETECT_FAIL; if(!cgroups2_available) @@ -252,19 +256,19 @@ static enum cgroups_type cgroups_try_detect_version() // 4. if we are unified as on Fedora (default cgroups2 only mode) // check kernel command line flag that can override that setting - f = fopen("/proc/cmdline", "r"); - if (!f) { + FILE *fp = fopen("/proc/cmdline", "r"); + if (!fp) { error("Error reading kernel boot commandline parameters"); return CGROUPS_AUTODETECT_FAIL; } - if (!fgets(buf, MAXSIZE_PROC_CMDLINE, f)) { + if (!fgets(buf, MAXSIZE_PROC_CMDLINE, fp)) { error("couldn't read all cmdline params into buffer"); - fclose(f); + fclose(fp); return CGROUPS_AUTODETECT_FAIL; } - fclose(f); + fclose(fp); if (strstr(buf, "systemd.unified_cgroup_hierarchy=0")) { info("cgroups v2 (unified cgroups) is available but are disabled on this system."); @@ -855,16 +859,16 @@ struct cgroup { char *filename_cpu_cfs_quota; unsigned long long cpu_cfs_quota; - RRDSETVAR *chart_var_cpu_limit; + const RRDSETVAR_ACQUIRED *chart_var_cpu_limit; NETDATA_DOUBLE prev_cpu_usage; char *filename_memory_limit; unsigned long long memory_limit; - RRDSETVAR *chart_var_memory_limit; + const RRDSETVAR_ACQUIRED *chart_var_memory_limit; char *filename_memoryswap_limit; unsigned long long memoryswap_limit; - RRDSETVAR *chart_var_memoryswap_limit; + const RRDSETVAR_ACQUIRED *chart_var_memoryswap_limit; // services RRDDIM *rd_cpu; @@ -1443,7 +1447,6 @@ static inline void cgroup2_read_pressure(struct pressure *res) { return; } - res->some.share_time.value10 = strtod(procfile_lineword(ff, 0, 2), NULL); res->some.share_time.value60 = strtod(procfile_lineword(ff, 0, 4), NULL); res->some.share_time.value300 = strtod(procfile_lineword(ff, 0, 6), NULL); @@ -1663,16 +1666,16 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) { } debug(D_CGROUP, "executing cgroup_identifier %s --cgroup '%s' for cgroup '%s'", cgroups_network_interface_script, cgroup_identifier, cg->id); - FILE *fp; - (void)mypopen_raw_default_flags_and_environment(&cgroup_pid, &fp, cgroups_network_interface_script, "--cgroup", cgroup_identifier); - if(!fp) { + FILE *fp_child_input, *fp_child_output; + (void)netdata_popen_raw_default_flags_and_environment(&cgroup_pid, &fp_child_input, &fp_child_output, cgroups_network_interface_script, "--cgroup", cgroup_identifier); + if(!fp_child_output) { error("CGROUP: cannot popen(%s --cgroup \"%s\", \"r\").", cgroups_network_interface_script, cgroup_identifier); return; } char *s; char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; - while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) { + while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp_child_output))) { trim(s); if(*s && *s != '\n') { @@ -1707,7 +1710,7 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) { } } - mypclose(fp, cgroup_pid); + netdata_pclose(fp_child_input, fp_child_output, cgroup_pid); // debug(D_CGROUP, "closed cgroup_identifier for cgroup '%s'", cg->id); } @@ -1869,9 +1872,9 @@ static inline void discovery_rename_cgroup(struct cgroup *cg) { debug(D_CGROUP, "executing command %s \"%s\" for cgroup '%s'", cgroups_rename_script, cg->intermediate_id, cg->chart_id); pid_t cgroup_pid; - FILE *fp; - (void)mypopen_raw_default_flags_and_environment(&cgroup_pid, &fp, cgroups_rename_script, cg->id, cg->intermediate_id); - if (!fp) { + FILE *fp_child_input, *fp_child_output; + (void)netdata_popen_raw_default_flags_and_environment(&cgroup_pid, &fp_child_input, &fp_child_output, cgroups_rename_script, cg->id, cg->intermediate_id); + if (!fp_child_output) { error("CGROUP: cannot popen(%s \"%s\", \"r\").", cgroups_rename_script, cg->intermediate_id); cg->pending_renames = 0; cg->processed = 1; @@ -1879,8 +1882,8 @@ static inline void discovery_rename_cgroup(struct cgroup *cg) { } char buffer[CGROUP_CHARTID_LINE_MAX + 1]; - char *new_name = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp); - int exit_code = mypclose(fp, cgroup_pid); + char *new_name = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp_child_output); + int exit_code = netdata_pclose(fp_child_input, fp_child_output, cgroup_pid); switch (exit_code) { case 0: @@ -2682,7 +2685,7 @@ static inline void discovery_process_cgroup(struct cgroup *cg) { cg->processed = 1; - if (strlen(cg->chart_id) >= RRD_ID_LENGTH_MAX) { + if ((strlen(cg->chart_id) + strlen(cgroup_chart_id_prefix)) >= RRD_ID_LENGTH_MAX) { info("cgroup '%s' (chart id '%s') disabled because chart_id exceeds the limit (RRD_ID_LENGTH_MAX)", cg->id, cg->chart_id); return; } @@ -2843,57 +2846,45 @@ void update_systemd_services_charts( // create the charts - if(likely(do_cpu)) { - if(unlikely(!st_cpu)) { - char title[CHART_TITLE_MAX + 1]; - snprintfz(title, CHART_TITLE_MAX, "Systemd Services CPU utilization (100%% = 1 core)"); - - st_cpu = rrdset_create_localhost( - "services" - , "cpu" - , NULL - , "cpu" - , "services.cpu" - , title - , "percentage" - , PLUGIN_CGROUPS_NAME - , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME - , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD - , update_every - , RRDSET_TYPE_STACKED - ); - - } - else - rrdset_next(st_cpu); + if (unlikely(do_cpu && !st_cpu)) { + char title[CHART_TITLE_MAX + 1]; + snprintfz(title, CHART_TITLE_MAX, "Systemd Services CPU utilization (100%% = 1 core)"); + + st_cpu = rrdset_create_localhost( + "services" + , "cpu" + , NULL + , "cpu" + , "services.cpu" + , title + , "percentage" + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + , update_every + , RRDSET_TYPE_STACKED + ); } - if(likely(do_mem_usage)) { - if(unlikely(!st_mem_usage)) { - - st_mem_usage = rrdset_create_localhost( - "services" - , "mem_usage" - , NULL - , "mem" - , "services.mem_usage" - , "Systemd Services Used Memory" - , "MiB" - , PLUGIN_CGROUPS_NAME - , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME - , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 10 - , update_every - , RRDSET_TYPE_STACKED - ); - - } - else - rrdset_next(st_mem_usage); + if (unlikely(do_mem_usage && !st_mem_usage)) { + st_mem_usage = rrdset_create_localhost( + "services" + , "mem_usage" + , NULL + , "mem" + , "services.mem_usage" + , "Systemd Services Used Memory" + , "MiB" + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 10 + , update_every + , RRDSET_TYPE_STACKED + ); } if(likely(do_mem_detailed)) { if(unlikely(!st_mem_detailed_rss)) { - st_mem_detailed_rss = rrdset_create_localhost( "services" , "mem_rss" @@ -2908,13 +2899,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_mem_detailed_rss); if(unlikely(!st_mem_detailed_mapped)) { - st_mem_detailed_mapped = rrdset_create_localhost( "services" , "mem_mapped" @@ -2929,13 +2916,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_mem_detailed_mapped); if(unlikely(!st_mem_detailed_cache)) { - st_mem_detailed_cache = rrdset_create_localhost( "services" , "mem_cache" @@ -2950,13 +2933,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_mem_detailed_cache); if(unlikely(!st_mem_detailed_writeback)) { - st_mem_detailed_writeback = rrdset_create_localhost( "services" , "mem_writeback" @@ -2973,11 +2952,8 @@ void update_systemd_services_charts( ); } - else - rrdset_next(st_mem_detailed_writeback); if(unlikely(!st_mem_detailed_pgfault)) { - st_mem_detailed_pgfault = rrdset_create_localhost( "services" , "mem_pgfault" @@ -2993,11 +2969,8 @@ void update_systemd_services_charts( , RRDSET_TYPE_STACKED ); } - else - rrdset_next(st_mem_detailed_pgfault); if(unlikely(!st_mem_detailed_pgmajfault)) { - st_mem_detailed_pgmajfault = rrdset_create_localhost( "services" , "mem_pgmajfault" @@ -3012,13 +2985,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_mem_detailed_pgmajfault); if(unlikely(!st_mem_detailed_pgpgin)) { - st_mem_detailed_pgpgin = rrdset_create_localhost( "services" , "mem_pgpgin" @@ -3035,11 +3004,8 @@ void update_systemd_services_charts( ); } - else - rrdset_next(st_mem_detailed_pgpgin); if(unlikely(!st_mem_detailed_pgpgout)) { - st_mem_detailed_pgpgout = rrdset_create_localhost( "services" , "mem_pgpgout" @@ -3054,61 +3020,45 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_mem_detailed_pgpgout); } - if(likely(do_mem_failcnt)) { - if(unlikely(!st_mem_failcnt)) { - - st_mem_failcnt = rrdset_create_localhost( - "services" - , "mem_failcnt" - , NULL - , "mem" - , "services.mem_failcnt" - , "Systemd Services Memory Limit Failures" - , "failures" - , PLUGIN_CGROUPS_NAME - , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME - , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 110 - , update_every - , RRDSET_TYPE_STACKED - ); - - } - else - rrdset_next(st_mem_failcnt); + if(unlikely(do_mem_failcnt && !st_mem_failcnt)) { + st_mem_failcnt = rrdset_create_localhost( + "services" + , "mem_failcnt" + , NULL + , "mem" + , "services.mem_failcnt" + , "Systemd Services Memory Limit Failures" + , "failures" + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 110 + , update_every + , RRDSET_TYPE_STACKED + ); } - if(likely(do_swap_usage)) { - if(unlikely(!st_swap_usage)) { - - st_swap_usage = rrdset_create_localhost( - "services" - , "swap_usage" - , NULL - , "swap" - , "services.swap_usage" - , "Systemd Services Swap Memory Used" - , "MiB" - , PLUGIN_CGROUPS_NAME - , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME - , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 100 - , update_every - , RRDSET_TYPE_STACKED - ); - - } - else - rrdset_next(st_swap_usage); + if (do_swap_usage && !st_swap_usage) { + st_swap_usage = rrdset_create_localhost( + "services" + , "swap_usage" + , NULL + , "swap" + , "services.swap_usage" + , "Systemd Services Swap Memory Used" + , "MiB" + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 100 + , update_every + , RRDSET_TYPE_STACKED + ); } if(likely(do_io)) { if(unlikely(!st_io_read)) { - st_io_read = rrdset_create_localhost( "services" , "io_read" @@ -3123,13 +3073,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_io_read); if(unlikely(!st_io_write)) { - st_io_write = rrdset_create_localhost( "services" , "io_write" @@ -3144,15 +3090,11 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_io_write); } if(likely(do_io_ops)) { if(unlikely(!st_io_serviced_read)) { - st_io_serviced_read = rrdset_create_localhost( "services" , "io_ops_read" @@ -3167,13 +3109,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_io_serviced_read); if(unlikely(!st_io_serviced_write)) { - st_io_serviced_write = rrdset_create_localhost( "services" , "io_ops_write" @@ -3188,10 +3126,7 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_io_serviced_write); } if(likely(do_throttle_io)) { @@ -3213,11 +3148,8 @@ void update_systemd_services_charts( ); } - else - rrdset_next(st_throttle_io_read); if(unlikely(!st_throttle_io_write)) { - st_throttle_io_write = rrdset_create_localhost( "services" , "throttle_io_write" @@ -3232,15 +3164,11 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_throttle_io_write); } if(likely(do_throttle_ops)) { if(unlikely(!st_throttle_ops_read)) { - st_throttle_ops_read = rrdset_create_localhost( "services" , "throttle_io_ops_read" @@ -3255,13 +3183,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_throttle_ops_read); if(unlikely(!st_throttle_ops_write)) { - st_throttle_ops_write = rrdset_create_localhost( "services" , "throttle_io_ops_write" @@ -3276,15 +3200,11 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_throttle_ops_write); } if(likely(do_queued_ops)) { if(unlikely(!st_queued_ops_read)) { - st_queued_ops_read = rrdset_create_localhost( "services" , "queued_io_ops_read" @@ -3299,10 +3219,7 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_queued_ops_read); if(unlikely(!st_queued_ops_write)) { @@ -3320,15 +3237,11 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_queued_ops_write); } if(likely(do_merged_ops)) { if(unlikely(!st_merged_ops_read)) { - st_merged_ops_read = rrdset_create_localhost( "services" , "merged_io_ops_read" @@ -3343,13 +3256,9 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_merged_ops_read); if(unlikely(!st_merged_ops_write)) { - st_merged_ops_write = rrdset_create_localhost( "services" , "merged_io_ops_write" @@ -3364,10 +3273,7 @@ void update_systemd_services_charts( , update_every , RRDSET_TYPE_STACKED ); - } - else - rrdset_next(st_merged_ops_write); } // update the values @@ -3595,7 +3501,7 @@ static inline char *cgroup_chart_type(char *buffer, const char *id, size_t len) if(id[0] == '\0' || (id[0] == '/' && id[1] == '\0')) strncpy(buffer, "cgroup_root", len); else - snprintfz(buffer, len, "cgroup_%s", id); + snprintfz(buffer, len, "%s%s", cgroup_chart_id_prefix, id); netdata_fix_chart_id(buffer); return buffer; @@ -3706,10 +3612,10 @@ cpu_limits2_err: } } -static inline int update_memory_limits(char **filename, RRDSETVAR **chart_var, unsigned long long *value, const char *chart_var_name, struct cgroup *cg) { +static inline int update_memory_limits(char **filename, const RRDSETVAR_ACQUIRED **chart_var, unsigned long long *value, const char *chart_var_name, struct cgroup *cg) { if(*filename) { if(unlikely(!*chart_var)) { - *chart_var = rrdsetvar_custom_chart_variable_create(cg->st_mem_usage, chart_var_name); + *chart_var = rrdsetvar_custom_chart_variable_add_and_acquire(cg->st_mem_usage, chart_var_name); if(!*chart_var) { error("Cannot create cgroup %s chart variable '%s'. Will not update its limit anymore.", cg->id, chart_var_name); freez(*filename); @@ -3725,7 +3631,7 @@ static inline int update_memory_limits(char **filename, RRDSETVAR **chart_var, u *filename = NULL; } else { - rrdsetvar_custom_chart_variable_set(*chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); + rrdsetvar_custom_chart_variable_set(cg->st_mem_usage, *chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); return 1; } } else { @@ -3740,11 +3646,11 @@ static inline int update_memory_limits(char **filename, RRDSETVAR **chart_var, u char *s = "max\n\0"; if(strcmp(s, buffer) == 0){ *value = UINT64_MAX; - rrdsetvar_custom_chart_variable_set(*chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); + rrdsetvar_custom_chart_variable_set(cg->st_mem_usage, *chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); return 1; } *value = str2ull(buffer); - rrdsetvar_custom_chart_variable_set(*chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); + rrdsetvar_custom_chart_variable_set(cg->st_mem_usage, *chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); return 1; } } @@ -3824,8 +3730,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_cpu, "system", NULL, 100, 1000000, RRD_ALGORITHM_INCREMENTAL); } } - else - rrdset_next(cg->st_cpu); rrddim_set(cg->st_cpu, "user", cg->cpuacct_stat.user); rrddim_set(cg->st_cpu, "system", cg->cpuacct_stat.system); @@ -3841,7 +3745,7 @@ void update_cgroup_charts(int update_every) { } if(unlikely(!cg->chart_var_cpu_limit)) { - cg->chart_var_cpu_limit = rrdsetvar_custom_chart_variable_create(cg->st_cpu, "cpu_limit"); + cg->chart_var_cpu_limit = rrdsetvar_custom_chart_variable_add_and_acquire(cg->st_cpu, "cpu_limit"); if(!cg->chart_var_cpu_limit) { error("Cannot create cgroup %s chart variable 'cpu_limit'. Will not update its limit anymore.", cg->id); if(cg->filename_cpuset_cpus) freez(cg->filename_cpuset_cpus); @@ -3866,8 +3770,6 @@ void update_cgroup_charts(int update_every) { value = (NETDATA_DOUBLE)cg->cpuset_cpus * 100; } if(likely(value)) { - rrdsetvar_custom_chart_variable_set(cg->chart_var_cpu_limit, value); - if(unlikely(!cg->st_cpu_limit)) { snprintfz(title, CHART_TITLE_MAX, "CPU Usage within the limits"); @@ -3894,8 +3796,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_cpu_limit, "used", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); cg->prev_cpu_usage = (NETDATA_DOUBLE)(cg->cpuacct_stat.user + cg->cpuacct_stat.system) * 100; } - else - rrdset_next(cg->st_cpu_limit); NETDATA_DOUBLE cpu_usage = 0; cpu_usage = (NETDATA_DOUBLE)(cg->cpuacct_stat.user + cg->cpuacct_stat.system) * 100; @@ -3907,14 +3807,15 @@ void update_cgroup_charts(int update_every) { cg->prev_cpu_usage = cpu_usage; + rrdsetvar_custom_chart_variable_set(cg->st_cpu, cg->chart_var_cpu_limit, value); rrdset_done(cg->st_cpu_limit); } else { - rrdsetvar_custom_chart_variable_set(cg->chart_var_cpu_limit, NAN); if(unlikely(cg->st_cpu_limit)) { rrdset_is_obsolete(cg->st_cpu_limit); cg->st_cpu_limit = NULL; } + rrdsetvar_custom_chart_variable_set(cg->st_cpu, cg->chart_var_cpu_limit, NAN); } } } @@ -3942,7 +3843,6 @@ void update_cgroup_charts(int update_every) { rrdset_update_rrdlabels(cg->st_cpu_nr_throttled, cg->chart_labels); rrddim_add(cg->st_cpu_nr_throttled, "throttled", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else { - rrdset_next(cg->st_cpu_nr_throttled); rrddim_set(cg->st_cpu_nr_throttled, "throttled", cg->cpuacct_cpu_throttling.nr_throttled_perc); rrdset_done(cg->st_cpu_nr_throttled); } @@ -3968,7 +3868,6 @@ void update_cgroup_charts(int update_every) { rrdset_update_rrdlabels(cg->st_cpu_throttled_time, cg->chart_labels); rrddim_add(cg->st_cpu_throttled_time, "duration", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL); } else { - rrdset_next(cg->st_cpu_throttled_time); rrddim_set(cg->st_cpu_throttled_time, "duration", cg->cpuacct_cpu_throttling.throttled_time); rrdset_done(cg->st_cpu_throttled_time); } @@ -3996,7 +3895,6 @@ void update_cgroup_charts(int update_every) { rrdset_update_rrdlabels(cg->st_cpu_shares, cg->chart_labels); rrddim_add(cg->st_cpu_shares, "shares", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else { - rrdset_next(cg->st_cpu_shares); rrddim_set(cg->st_cpu_shares, "shares", cg->cpuacct_cpu_shares.shares); rrdset_done(cg->st_cpu_shares); } @@ -4031,8 +3929,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_cpu_per_core, id, NULL, 100, 1000000000, RRD_ALGORITHM_INCREMENTAL); } } - else - rrdset_next(cg->st_cpu_per_core); for(i = 0; i < cg->cpuacct_usage.cpus ;i++) { snprintfz(id, RRD_ID_LENGTH_MAX, "cpu%u", i); @@ -4080,8 +3976,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_mem, "file", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } } - else - rrdset_next(cg->st_mem); if(!(cg->options & CGROUP_OPTIONS_IS_UNIFIED)) { rrddim_set(cg->st_mem, "cache", cg->memory.total_cache); @@ -4127,8 +4021,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_writeback, "writeback", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(cg->st_writeback); if(cg->memory.detailed_has_dirty) rrddim_set(cg->st_writeback, "dirty", cg->memory.total_dirty); @@ -4160,8 +4052,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_mem_activity, "pgpgin", "in", system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(cg->st_mem_activity, "pgpgout", "out", -system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_mem_activity); rrddim_set(cg->st_mem_activity, "pgpgin", cg->memory.total_pgpgin); rrddim_set(cg->st_mem_activity, "pgpgout", cg->memory.total_pgpgout); @@ -4191,8 +4081,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_pgfaults, "pgfault", NULL, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(cg->st_pgfaults, "pgmajfault", "swap", -system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_pgfaults); rrddim_set(cg->st_pgfaults, "pgfault", cg->memory.total_pgfault); rrddim_set(cg->st_pgfaults, "pgmajfault", cg->memory.total_pgmajfault); @@ -4223,8 +4111,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_mem_usage, "ram", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(cg->st_mem_usage, "swap", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(cg->st_mem_usage); rrddim_set(cg->st_mem_usage, "ram", cg->memory.usage_in_bytes); if(!(cg->options & CGROUP_OPTIONS_IS_UNIFIED)) { @@ -4290,8 +4176,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_mem_usage_limit, "available", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(cg->st_mem_usage_limit, "used", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(cg->st_mem_usage_limit); rrdset_isnot_obsolete(cg->st_mem_usage_limit); @@ -4320,8 +4204,7 @@ void update_cgroup_charts(int update_every) { rrdset_update_rrdlabels(cg->st_mem_utilization, cg->chart_labels); rrddim_add(cg->st_mem_utilization, "utilization", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(cg->st_mem_utilization); + } if (memory_limit) { rrdset_isnot_obsolete(cg->st_mem_utilization); @@ -4370,8 +4253,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_mem_failcnt, "failures", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_mem_failcnt); rrddim_set(cg->st_mem_failcnt, "failures", cg->memory.failcnt); rrdset_done(cg->st_mem_failcnt); @@ -4401,8 +4282,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_io, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(cg->st_io, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_io); rrddim_set(cg->st_io, "read", cg->io_service_bytes.Read); rrddim_set(cg->st_io, "write", cg->io_service_bytes.Write); @@ -4433,8 +4312,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_serviced_ops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(cg->st_serviced_ops, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_serviced_ops); rrddim_set(cg->st_serviced_ops, "read", cg->io_serviced.Read); rrddim_set(cg->st_serviced_ops, "write", cg->io_serviced.Write); @@ -4465,8 +4342,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_throttle_io, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(cg->st_throttle_io, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_throttle_io); rrddim_set(cg->st_throttle_io, "read", cg->throttle_io_service_bytes.Read); rrddim_set(cg->st_throttle_io, "write", cg->throttle_io_service_bytes.Write); @@ -4497,8 +4372,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_throttle_serviced_ops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(cg->st_throttle_serviced_ops, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_throttle_serviced_ops); rrddim_set(cg->st_throttle_serviced_ops, "read", cg->throttle_io_serviced.Read); rrddim_set(cg->st_throttle_serviced_ops, "write", cg->throttle_io_serviced.Write); @@ -4529,8 +4402,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_queued_ops, "read", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(cg->st_queued_ops, "write", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(cg->st_queued_ops); rrddim_set(cg->st_queued_ops, "read", cg->io_queued.Read); rrddim_set(cg->st_queued_ops, "write", cg->io_queued.Write); @@ -4561,8 +4432,6 @@ void update_cgroup_charts(int update_every) { rrddim_add(cg->st_merged_ops, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(cg->st_merged_ops, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(cg->st_merged_ops); rrddim_set(cg->st_merged_ops, "read", cg->io_merged.Read); rrddim_set(cg->st_merged_ops, "write", cg->io_merged.Write); @@ -4597,9 +4466,8 @@ void update_cgroup_charts(int update_every) { pcs->share_time.rd10 = rrddim_add(chart, "some 10", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd60 = rrddim_add(chart, "some 60", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd300 = rrddim_add(chart, "some 300", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(pcs->share_time.st); } + if (unlikely(!pcs->total_time.st)) { RRDSET *chart; snprintfz(title, CHART_TITLE_MAX, "CPU some pressure stall time"); @@ -4619,9 +4487,8 @@ void update_cgroup_charts(int update_every) { ); rrdset_update_rrdlabels(chart = pcs->total_time.st, cg->chart_labels); pcs->total_time.rdtotal = rrddim_add(chart, "time", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else { - rrdset_next(pcs->total_time.st); } + update_pressure_charts(pcs); } if (likely(res->updated && res->full.enabled)) { @@ -4649,9 +4516,8 @@ void update_cgroup_charts(int update_every) { pcs->share_time.rd10 = rrddim_add(chart, "full 10", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd60 = rrddim_add(chart, "full 60", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd300 = rrddim_add(chart, "full 300", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(pcs->share_time.st); } + if (unlikely(!pcs->total_time.st)) { RRDSET *chart; snprintfz(title, CHART_TITLE_MAX, "CPU full pressure stall time"); @@ -4671,9 +4537,8 @@ void update_cgroup_charts(int update_every) { ); rrdset_update_rrdlabels(chart = pcs->total_time.st, cg->chart_labels); pcs->total_time.rdtotal = rrddim_add(chart, "time", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else { - rrdset_next(pcs->total_time.st); } + update_pressure_charts(pcs); } @@ -4704,9 +4569,8 @@ void update_cgroup_charts(int update_every) { pcs->share_time.rd10 = rrddim_add(chart, "some 10", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd60 = rrddim_add(chart, "some 60", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd300 = rrddim_add(chart, "some 300", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(pcs->share_time.st); } + if (unlikely(!pcs->total_time.st)) { RRDSET *chart; snprintfz(title, CHART_TITLE_MAX, "Memory some pressure stall time"); @@ -4726,9 +4590,8 @@ void update_cgroup_charts(int update_every) { ); rrdset_update_rrdlabels(chart = pcs->total_time.st, cg->chart_labels); pcs->total_time.rdtotal = rrddim_add(chart, "time", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else { - rrdset_next(pcs->total_time.st); } + update_pressure_charts(pcs); } @@ -4759,9 +4622,8 @@ void update_cgroup_charts(int update_every) { pcs->share_time.rd10 = rrddim_add(chart, "full 10", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd60 = rrddim_add(chart, "full 60", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd300 = rrddim_add(chart, "full 300", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(pcs->share_time.st); } + if (unlikely(!pcs->total_time.st)) { RRDSET *chart; snprintfz(title, CHART_TITLE_MAX, "Memory full pressure stall time"); @@ -4781,9 +4643,8 @@ void update_cgroup_charts(int update_every) { ); rrdset_update_rrdlabels(chart = pcs->total_time.st, cg->chart_labels); pcs->total_time.rdtotal = rrddim_add(chart, "time", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else { - rrdset_next(pcs->total_time.st); } + update_pressure_charts(pcs); } @@ -4814,9 +4675,8 @@ void update_cgroup_charts(int update_every) { pcs->share_time.rd10 = rrddim_add(chart, "some 10", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd60 = rrddim_add(chart, "some 60", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd300 = rrddim_add(chart, "some 300", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(pcs->share_time.st); } + if (unlikely(!pcs->total_time.st)) { RRDSET *chart; snprintfz(title, CHART_TITLE_MAX, "I/O some pressure stall time"); @@ -4836,9 +4696,8 @@ void update_cgroup_charts(int update_every) { ); rrdset_update_rrdlabels(chart = pcs->total_time.st, cg->chart_labels); pcs->total_time.rdtotal = rrddim_add(chart, "time", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else { - rrdset_next(pcs->total_time.st); } + update_pressure_charts(pcs); } @@ -4867,9 +4726,8 @@ void update_cgroup_charts(int update_every) { pcs->share_time.rd10 = rrddim_add(chart, "full 10", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd60 = rrddim_add(chart, "full 60", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd300 = rrddim_add(chart, "full 300", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(pcs->share_time.st); } + if (unlikely(!pcs->total_time.st)) { RRDSET *chart; snprintfz(title, CHART_TITLE_MAX, "I/O full pressure stall time"); @@ -4889,9 +4747,8 @@ void update_cgroup_charts(int update_every) { ); rrdset_update_rrdlabels(chart = pcs->total_time.st, cg->chart_labels); pcs->total_time.rdtotal = rrddim_add(chart, "time", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else { - rrdset_next(pcs->total_time.st); } + update_pressure_charts(pcs); } } diff --git a/collectors/cgroups.plugin/tests/test_doubles.c b/collectors/cgroups.plugin/tests/test_doubles.c index 6203d444c..498f649f5 100644 --- a/collectors/cgroups.plugin/tests/test_doubles.c +++ b/collectors/cgroups.plugin/tests/test_doubles.c @@ -101,7 +101,7 @@ collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number return 0; } -RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name) +const RRDSETVAR_ACQUIRED *rrdsetvar_custom_chart_variable_add_and_acquire(RRDSET *st, const char *name) { UNUSED(st); UNUSED(name); @@ -109,9 +109,10 @@ RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name) return NULL; } -void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rs, NETDATA_DOUBLE value) +void rrdsetvar_custom_chart_variable_set(RRDSET *st, const RRDSETVAR_ACQUIRED *rsa, NETDATA_DOUBLE value) { - UNUSED(rs); + UNUSED(st); + UNUSED(rsa); UNUSED(value); } @@ -146,10 +147,11 @@ void netdev_rename_device_del(const char *host_device) UNUSED(host_device); } -void sql_store_chart_label(uuid_t *chart_uuid, int source_type, char *label, char *value) +void rrdcalc_update_rrdlabels(RRDSET *st) { + (void)st; +} + +void db_execute(const char *cmd) { - UNUSED(chart_uuid); - UNUSED(source_type); - UNUSED(label); - UNUSED(value); + UNUSED(cmd); } diff --git a/collectors/charts.d.plugin/sensors/README.md b/collectors/charts.d.plugin/sensors/README.md index ab7a8b660..1b98b1a70 100644 --- a/collectors/charts.d.plugin/sensors/README.md +++ b/collectors/charts.d.plugin/sensors/README.md @@ -5,17 +5,12 @@ custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/chart # Linux machine sensors monitoring with Netdata -> THIS MODULE IS OBSOLETE. -> USE [THE PYTHON ONE](/collectors/python.d.plugin/sensors) - IT SUPPORTS MULTIPLE JOBS AND IT IS MORE EFFICIENT -> -> Unlike the python one, this module can collect temperature on RPi. +Use this collector when `lm-sensors` doesn't work on your device (e.g. for RPi temperatures). +For all other cases use the [Python collector](/collectors/python.d.plugin/sensors), which supports multiple +jobs, is more efficient and performs calculations on top of the kernel provided values. -The plugin will provide charts for all configured system sensors - -> This plugin is reading sensors directly from the kernel. -> The `lm-sensors` package is able to perform calculations on the -> kernel provided values, this plugin will not perform. -> So, the values graphed, are the raw hardware values of the sensors. +This plugin will provide charts for all configured system sensors, by reading sensors directly from the kernel. +The values graphed are the raw hardware values of the sensors. The plugin will create Netdata charts for: diff --git a/collectors/checks.plugin/README.md b/collectors/checks.plugin/README.md deleted file mode 100644 index 6e2cf5dea..000000000 --- a/collectors/checks.plugin/README.md +++ /dev/null @@ -1,10 +0,0 @@ -<!-- -title: "checks.plugin" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/checks.plugin/README.md ---> - -# checks.plugin - -A debugging plugin (by default it is disabled) - - diff --git a/collectors/checks.plugin/plugin_checks.c b/collectors/checks.plugin/plugin_checks.c deleted file mode 100644 index 312515115..000000000 --- a/collectors/checks.plugin/plugin_checks.c +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "daemon/common.h" - -static void checks_main_cleanup(void *ptr) { - struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; - static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; - - info("cleaning up..."); - - static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; -} - -void *checks_main(void *ptr) { - netdata_thread_cleanup_push(checks_main_cleanup, ptr); - - usec_t usec = 0, susec = localhost->rrd_update_every * USEC_PER_SEC, loop_usec = 0, total_susec = 0; - struct timeval now, last, loop; - - RRDSET *check1, *check2, *check3, *apps_cpu = NULL; - - check1 = rrdset_create_localhost( - "netdata" - , "check1" - , NULL - , "netdata" - , NULL - , "Caller gives microseconds" - , "a million !" - , "checks.plugin" - , "" - , NETDATA_CHART_PRIO_CHECKS - , 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 !" - , "checks.plugin" - , "" - , NETDATA_CHART_PRIO_CHECKS - , 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" - , "checks.plugin" - , "" - , NETDATA_CHART_PRIO_CHECKS - , 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); - - now_realtime_timeval(&last); - while(!netdata_exit) { - usleep(susec); - - // find the time to sleep in order to wait exactly update_every seconds - now_realtime_timeval(&now); - loop_usec = dt_usec(&now, &last); - usec = loop_usec - susec; - debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, slept for %llu).", loop_usec, usec, susec); - - if(usec < (localhost->rrd_update_every * USEC_PER_SEC / 2ULL)) susec = (localhost->rrd_update_every * USEC_PER_SEC) - usec; - else susec = localhost->rrd_update_every * USEC_PER_SEC / 2ULL; - - // -------------------------------------------------------------------- - // Calculate loop time - - last.tv_sec = now.tv_sec; - last.tv_usec = now.tv_usec; - total_susec += loop_usec; - - // -------------------------------------------------------------------- - // check chart 1 - - if(check1->counter_done) rrdset_next_usec(check1, loop_usec); - rrddim_set(check1, "absolute", 1000000); - rrddim_set(check1, "incremental", total_susec); - rrdset_done(check1); - - // -------------------------------------------------------------------- - // check chart 2 - - if(check2->counter_done) rrdset_next(check2); - rrddim_set(check2, "absolute", 1000000); - rrddim_set(check2, "incremental", total_susec); - rrdset_done(check2); - - // -------------------------------------------------------------------- - // check chart 3 - - if(!apps_cpu) apps_cpu = rrdset_find_localhost("apps.cpu"); - if(check3->counter_done) rrdset_next_usec(check3, loop_usec); - now_realtime_timeval(&loop); - rrddim_set(check3, "caller", (long long) dt_usec(&loop, &check1->last_collected_time)); - rrddim_set(check3, "netdata", (long long) dt_usec(&loop, &check2->last_collected_time)); - if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) dt_usec(&loop, &apps_cpu->last_collected_time)); - rrdset_done(check3); - } - - netdata_thread_cleanup_pop(1); - return NULL; -} diff --git a/collectors/cups.plugin/README.md b/collectors/cups.plugin/README.md index e3d2e1661..f3b2a28d1 100644 --- a/collectors/cups.plugin/README.md +++ b/collectors/cups.plugin/README.md @@ -11,9 +11,11 @@ custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/cups. This plugin needs a running local CUPS daemon (`cupsd`). This plugin does not need any configuration. Supports cups since version 1.7. +If you installed Netdata using our native packages, you will have to additionaly install `netdata-plugin-cups` to use this plugin for data collection. It is not installed by default due to the large number of dependencies it requires. + ## Charts -`cups.plugin` provides one common section `destinations` and one section per destination. +`cups.plugin` provides one common section `destinations` and one section per destination. > Destinations in CUPS represent individual printers or classes (collections or pools) of printers (<https://www.cups.org/doc/cupspm.html#working-with-destinations>) diff --git a/collectors/cups.plugin/cups_plugin.c b/collectors/cups.plugin/cups_plugin.c index 77bd3e0ed..9a200c31d 100644 --- a/collectors/cups.plugin/cups_plugin.c +++ b/collectors/cups.plugin/cups_plugin.c @@ -137,10 +137,7 @@ getIntegerOption( return ((int)intvalue); } -static int reset_job_metrics(const char *name, void *entry, void *data) { - (void)name; - (void)data; - +static int reset_job_metrics(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data __maybe_unused) { struct job_metrics *jm = (struct job_metrics *)entry; jm->is_collected = 0; @@ -175,8 +172,8 @@ struct job_metrics *get_job_metrics(char *dest) { return jm; } -int collect_job_metrics(const char *name, void *entry, void *data) { - (void)data; +int collect_job_metrics(const DICTIONARY_ITEM *item, void *entry, void *data __maybe_unused) { + const char *name = dictionary_acquired_item_name(item); struct job_metrics *jm = (struct job_metrics *)entry; @@ -205,7 +202,7 @@ int collect_job_metrics(const char *name, void *entry, void *data) { printf("DIMENSION pending '' absolute 1 1\n"); printf("DIMENSION held '' absolute 1 1\n"); printf("DIMENSION processing '' absolute 1 1\n"); - dictionary_del_having_write_lock(dict_dest_job_metrics, name); + dictionary_del(dict_dest_job_metrics, name); } return 0; @@ -243,7 +240,7 @@ int main(int argc, char **argv) { errno = 0; - dict_dest_job_metrics = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + dict_dest_job_metrics = dictionary_create(DICT_OPTION_SINGLE_THREADED); // ------------------------------------------------------------------------ // the main loop diff --git a/collectors/diskspace.plugin/plugin_diskspace.c b/collectors/diskspace.plugin/plugin_diskspace.c index 5bdf8bc61..5f610983b 100644 --- a/collectors/diskspace.plugin/plugin_diskspace.c +++ b/collectors/diskspace.plugin/plugin_diskspace.c @@ -95,8 +95,8 @@ int mount_point_cleanup(const char *name, void *entry, int slow) { return 0; } -int mount_point_cleanup_cb(const char *name, void *entry, void *data) { - UNUSED(data); +int mount_point_cleanup_cb(const DICTIONARY_ITEM *item, void *entry, void *data __maybe_unused) { + const char *name = dictionary_acquired_item_name(item); return mount_point_cleanup(name, (struct mount_point_metadata *)entry, 0); } @@ -204,8 +204,6 @@ static void calculate_values_and_show_charts( 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); #endif - // -------------------------------------------------------------------------- - int rendered = 0; if(m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && @@ -239,8 +237,6 @@ static void calculate_values_and_show_charts( m->rd_space_used = rrddim_add(m->st_space, "used", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(m->st_space); rrddim_set_by_pointer(m->st_space, m->rd_space_avail, (collected_number)bavail); rrddim_set_by_pointer(m->st_space, m->rd_space_used, (collected_number)bused); @@ -250,8 +246,6 @@ static void calculate_values_and_show_charts( rendered++; } - // -------------------------------------------------------------------------- - if(m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (favail || freserved_root || fused || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -283,8 +277,6 @@ static void calculate_values_and_show_charts( m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); m->rd_inodes_reserved = rrddim_add(m->st_inodes, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(m->st_inodes); rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_avail, (collected_number)favail); rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_used, (collected_number)fused); @@ -294,8 +286,6 @@ static void calculate_values_and_show_charts( rendered++; } - // -------------------------------------------------------------------------- - if(likely(rendered)) m->collected++; } @@ -330,7 +320,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { , SIMPLE_PATTERN_EXACT ); - dict_mountpoints = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + dict_mountpoints = dictionary_create(DICT_OPTION_SINGLE_THREADED); } struct mount_point_metadata *m = dictionary_get(dict_mountpoints, mi->mount_point); @@ -521,12 +511,19 @@ void *diskspace_slow_worker(void *ptr) netdata_thread_cleanup_push(diskspace_slow_worker_cleanup, data->slow_thread); usec_t step = slow_update_every * USEC_PER_SEC; + usec_t real_step = USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); while(!netdata_exit) { worker_is_idle(); - heartbeat_next(&hb, step); + heartbeat_next(&hb, USEC_PER_SEC); + + if (real_step < step) { + real_step += USEC_PER_SEC; + continue; + } + real_step = USEC_PER_SEC; usec_t start_time = now_monotonic_high_precision_usec(); @@ -581,6 +578,7 @@ void *diskspace_slow_worker(void *ptr) } static void diskspace_main_cleanup(void *ptr) { + rrd_collector_finished(); worker_unregister(); struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; @@ -612,6 +610,8 @@ void *diskspace_main(void *ptr) { worker_register_job_name(WORKER_JOB_MOUNTPOINT, "mountpoint"); worker_register_job_name(WORKER_JOB_CLEANUP, "cleanup"); + rrd_collector_started(); + netdata_thread_cleanup_push(diskspace_main_cleanup, ptr); cleanup_mount_points = config_get_boolean(CONFIG_SECTION_DISKSPACE, "remove charts of unmounted disks" , cleanup_mount_points); diff --git a/collectors/ebpf.plugin/README.md b/collectors/ebpf.plugin/README.md index 550982ad2..7762ed34f 100644 --- a/collectors/ebpf.plugin/README.md +++ b/collectors/ebpf.plugin/README.md @@ -137,6 +137,25 @@ If you do not need to monitor specific metrics for your `cgroups`, you can enabl `ebpf.d.conf`, and then disable the plugin for a specific `thread` by following the steps in the [Configuration](#configuring-ebpfplugin) section. +#### Collect PID + +When one of the previous integrations is enabled, `ebpf.plugin` will use Process Identifier (`PID`) to identify the +process group for which it needs to plot data. + +There are different ways to collect PID, and you can select the way `ebpf.plugin` collects data with the following +values: + +- `real parent`: This is the default mode. Collection will aggregate data for the real parent, the thread that creates + child threads. +- `parent`: Parent and real parent are the same when a process starts, but this value can be changed during run time. +- `all`: This option will store all PIDs that run on the host. Note, this method can be expensive for the host, + because more memory needs to be allocated and parsed. + +The threads that have integration with other collectors have an internal clean up wherein they attach either a +`trampoline` or a `kprobe` to `release_task` internal function. To avoid `overload` on this function, `ebpf.plugin` +will only enable these threads integrated with other collectors when the kernel is compiled with +`CONFIG_DEBUG_INFO_BTF`, unless you enable them manually. + #### Integration Dashboard Elements When an integration is enabled, your dashboard will also show the following cgroups and apps charts using low-level diff --git a/collectors/ebpf.plugin/ebpf.c b/collectors/ebpf.plugin/ebpf.c index 65c96f672..00b53a57d 100644 --- a/collectors/ebpf.plugin/ebpf.c +++ b/collectors/ebpf.plugin/ebpf.c @@ -27,177 +27,317 @@ struct config collector_config = { .first_section = NULL, int running_on_kernel = 0; int ebpf_nprocs; int isrh = 0; +int main_thread_id = 0; pthread_mutex_t lock; +pthread_mutex_t ebpf_exit_cleanup; pthread_mutex_t collect_data_mutex; pthread_cond_t collect_data_cond_var; ebpf_module_t ebpf_modules[] = { { .thread_name = "process", .config_name = "process", .enabled = 0, .start_routine = ebpf_process_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_process_create_apps_charts, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &process_config, .config_file = NETDATA_PROCESS_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10 | + NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "socket", .config_name = "socket", .enabled = 0, .start_routine = ebpf_socket_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_socket_create_apps_charts, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &socket_config, .config_file = NETDATA_NETWORK_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, - .apps_routine = ebpf_cachestat_create_apps_charts, .maps = NULL, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = ebpf_cachestat_create_apps_charts, .maps = cachestat_maps, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &cachestat_config, .config_file = NETDATA_CACHESTAT_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18| NETDATA_V5_4 | NETDATA_V5_15 | - NETDATA_V5_16, - .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18| + NETDATA_V5_4 | NETDATA_V5_14 | NETDATA_V5_15 | NETDATA_V5_16, + .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, - .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &sync_config, + .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &sync_config, .config_file = NETDATA_SYNC_CONFIG_FILE, // All syscalls have the same kernels - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "dc", .config_name = "dc", .enabled = 0, .start_routine = ebpf_dcstat_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, - .apps_routine = ebpf_dcstat_create_apps_charts, .maps = NULL, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = ebpf_dcstat_create_apps_charts, .maps = dcstat_maps, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config, .config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_swap_create_apps_charts, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config, .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config, .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, - .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config, + .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config, .config_file = NETDATA_FILESYSTEM_CONFIG_FILE, //We are setting kernels as zero, because we load eBPF programs according the kernel running. - .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL }, + .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL }, { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, - .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config, + .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config, .config_file = NETDATA_DISK_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, - .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config, + .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config, .config_file = NETDATA_MOUNT_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_fd_create_apps_charts, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fd_config, .config_file = NETDATA_FD_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11 | + NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, - .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config, + .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config, .config_file = NETDATA_HARDIRQ_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "softirq", .config_name = "softirq", .enabled = 0, .start_routine = ebpf_softirq_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, - .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config, + .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config, .config_file = NETDATA_SOFTIRQ_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "oomkill", .config_name = "oomkill", .enabled = 0, .start_routine = ebpf_oomkill_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_oomkill_create_apps_charts, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &oomkill_config, .config_file = NETDATA_OOMKILL_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_shm_create_apps_charts, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config, .config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = "mdflush", .config_name = "mdflush", .enabled = 0, .start_routine = ebpf_mdflush_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, - .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, - .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config, + .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, + .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config, .config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE, - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL}, + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL}, { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY, - .global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .cgroup_charts = CONFIG_BOOLEAN_NO, - .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL, - .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, - .objects = NULL}, + .global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .apps_level = NETDATA_APPS_NOT_SET, + .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, + .pid_map_size = 0, .names = NULL, .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY, + .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL}, }; struct netdata_static_thread ebpf_threads[] = { - {"EBPF PROCESS", NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF SOCKET" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF CACHESTAT" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF SYNC" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF DCSTAT" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF SWAP" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF VFS" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF FILESYSTEM" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF DISK" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF MOUNT" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF FD" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF HARDIRQ" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF SOFTIRQ" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF OOMKILL" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF SHM" , NULL, NULL, 1, - NULL, NULL, NULL}, - {"EBPF MDFLUSH" , NULL, NULL, 1, - NULL, NULL, NULL}, - {NULL , NULL, NULL, 0, - NULL, NULL, NULL} + { + .name = "EBPF PROCESS", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF SOCKET", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF CACHESTAT", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF SYNC", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF DCSTAT", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF SWAP", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF VFS", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF FILESYSTEM", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF DISK", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF MOUNT", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF FD", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF HARDIRQ", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF SOFTIRQ", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF OOMKILL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF SHM", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = "EBPF MDFLUSH", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, + { + .name = NULL, + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 0, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL + }, }; ebpf_filesystem_partitions_t localfs[] = @@ -294,6 +434,7 @@ ebpf_sync_syscalls_t local_syscalls[] = { } }; + // Link with apps.plugin ebpf_process_stat_t *global_process_stat = NULL; @@ -312,6 +453,8 @@ ebpf_plugin_stats_t plugin_statistics = {.core = 0, .legacy = 0, .running = 0, . #ifdef LIBBPF_MAJOR_VERSION struct btf *default_btf = NULL; +#else +void *default_btf = NULL; #endif char *btf_path = NULL; @@ -323,16 +466,16 @@ char *btf_path = NULL; /** * Close the collector gracefully - * - * @param sig is the signal number used to close the collector */ -static void ebpf_exit(int sig) +static void ebpf_exit() { #ifdef LIBBPF_MAJOR_VERSION + pthread_mutex_lock(&ebpf_exit_cleanup); if (default_btf) { btf__free(default_btf); default_btf = NULL; } + pthread_mutex_unlock(&ebpf_exit_cleanup); #endif char filename[FILENAME_MAX + 1]; @@ -340,7 +483,7 @@ static void ebpf_exit(int sig) if (unlink(filename)) error("Cannot remove PID file %s", filename); - exit(sig); + exit(0); } /** @@ -373,44 +516,66 @@ int ebpf_exit_plugin = 0; */ static void ebpf_stop_threads(int sig) { - ebpf_exit_plugin = 1; + UNUSED(sig); + static int only_one = 0; + int i; - for (i = 0; ebpf_threads[i].name != NULL; i++); + // Child thread should be closed by itself. + pthread_mutex_lock(&ebpf_exit_cleanup); + if (main_thread_id != gettid() || only_one) { + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + only_one = 1; + for (i = 0; ebpf_threads[i].name != NULL; i++) { + if (ebpf_threads[i].enabled != NETDATA_THREAD_EBPF_STOPPED) + netdata_thread_cancel(*ebpf_threads[i].thread); + } + pthread_mutex_unlock(&ebpf_exit_cleanup); - usec_t max = 2 * USEC_PER_SEC, step = 100000; + ebpf_exit_plugin = 1; + usec_t max = 3 * USEC_PER_SEC, step = 100000; while (i && max) { max -= step; sleep_usec(step); i = 0; int j; + pthread_mutex_lock(&ebpf_exit_cleanup); for (j = 0; ebpf_threads[j].name != NULL; j++) { - if (ebpf_threads[j].enabled != NETDATA_MAIN_THREAD_EXITED) + if (ebpf_threads[j].enabled != NETDATA_THREAD_EBPF_STOPPED) i++; } + pthread_mutex_unlock(&ebpf_exit_cleanup); } //Unload threads(except sync and filesystem) + pthread_mutex_lock(&ebpf_exit_cleanup); for (i = 0; ebpf_threads[i].name != NULL; i++) { - if (ebpf_threads[i].enabled == NETDATA_MAIN_THREAD_EXITED && i != EBPF_MODULE_FILESYSTEM_IDX && + if (ebpf_threads[i].enabled == NETDATA_THREAD_EBPF_STOPPED && i != EBPF_MODULE_FILESYSTEM_IDX && i != EBPF_MODULE_SYNC_IDX) ebpf_unload_legacy_code(ebpf_modules[i].objects, ebpf_modules[i].probe_links); } + pthread_mutex_unlock(&ebpf_exit_cleanup); //Unload filesystem - if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_MAIN_THREAD_EXITED) { + pthread_mutex_lock(&ebpf_exit_cleanup); + if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) { for (i = 0; localfs[i].filesystem != NULL; i++) { ebpf_unload_legacy_code(localfs[i].objects, localfs[i].probe_links); } } + pthread_mutex_unlock(&ebpf_exit_cleanup); //Unload Sync - if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_MAIN_THREAD_EXITED) { + pthread_mutex_lock(&ebpf_exit_cleanup); + if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) { for (i = 0; local_syscalls[i].syscall != NULL; i++) { ebpf_unload_legacy_code(local_syscalls[i].objects, local_syscalls[i].probe_links); } } + pthread_mutex_unlock(&ebpf_exit_cleanup); - ebpf_exit(sig); + ebpf_exit(); } /***************************************************************** @@ -1170,6 +1335,7 @@ static void read_local_addresses() int ebpf_start_pthread_variables() { pthread_mutex_init(&lock, NULL); + pthread_mutex_init(&ebpf_exit_cleanup, NULL); pthread_mutex_init(&collect_data_mutex, NULL); if (pthread_cond_init(&collect_data_cond_var, NULL)) { @@ -1261,35 +1427,28 @@ static void ebpf_update_table_size() /** * Set Load mode * - * @param load default load mode. + * @param origin specify the configuration file loaded */ -static inline void ebpf_set_load_mode(netdata_ebpf_load_mode_t load) +static inline void ebpf_set_load_mode(netdata_ebpf_load_mode_t load, netdata_ebpf_load_mode_t origin) { -#ifdef LIBBPF_MAJOR_VERSION - if (load == EBPF_LOAD_CORE || load == EBPF_LOAD_PLAY_DICE) { - load = (!default_btf) ? EBPF_LOAD_LEGACY : EBPF_LOAD_CORE; - } -#else - load = EBPF_LOAD_LEGACY; -#endif - int i; for (i = 0; ebpf_modules[i].thread_name; i++) { - // TO DO: Use `load` variable after we change all threads. - ebpf_modules[i].load = EBPF_LOAD_LEGACY; // load ; + ebpf_modules[i].load &= ~NETDATA_EBPF_LOAD_METHODS; + ebpf_modules[i].load |= load | origin ; } } /** * Update mode * - * @param str value read from configuration file. + * @param str value read from configuration file. + * @param origin specify the configuration file loaded */ -static inline void epbf_update_load_mode(char *str) +static inline void epbf_update_load_mode(char *str, netdata_ebpf_load_mode_t origin) { netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(str); - ebpf_set_load_mode(load); + ebpf_set_load_mode(load, origin); } /** @@ -1297,9 +1456,11 @@ static inline void epbf_update_load_mode(char *str) * * @param disable_apps variable to store information related to apps. * @param disable_cgroups variable to store information related to cgroups. - * @param update_every value to overwrite the update frequency set by the server. + * @param update_every value to overwrite the update frequency set by the server. + * @param origin specify the configuration file loaded */ -static void read_collector_values(int *disable_apps, int *disable_cgroups, int update_every) +static void read_collector_values(int *disable_apps, int *disable_cgroups, + int update_every, netdata_ebpf_load_mode_t origin) { // Read global section char *value; @@ -1321,7 +1482,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups, int u value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, EBPF_CFG_DEFAULT_PROGRAM); - epbf_update_load_mode(value); + epbf_update_load_mode(value, origin); ebpf_update_interval(update_every); @@ -1499,6 +1660,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups, int u static int load_collector_config(char *path, int *disable_apps, int *disable_cgroups, int update_every) { char lpath[4096]; + netdata_ebpf_load_mode_t origin; snprintf(lpath, 4095, "%s/%s", path, NETDATA_EBPF_CONFIG_FILE); if (!appconfig_load(&collector_config, lpath, 0, NULL)) { @@ -1506,9 +1668,11 @@ static int load_collector_config(char *path, int *disable_apps, int *disable_cgr if (!appconfig_load(&collector_config, lpath, 0, NULL)) { return -1; } - } + origin = EBPF_LOADED_FROM_STOCK; + } else + origin = EBPF_LOADED_FROM_USER; - read_collector_values(disable_apps, disable_cgroups, update_every); + read_collector_values(disable_apps, disable_cgroups, update_every, origin); return 0; } @@ -1552,7 +1716,7 @@ static inline void ebpf_load_thread_config() { int i; for (i = 0; ebpf_modules[i].thread_name; i++) { - ebpf_update_module(&ebpf_modules[i]); + ebpf_update_module(&ebpf_modules[i], default_btf, running_on_kernel, isrh); } } @@ -1771,14 +1935,14 @@ static void ebpf_parse_args(int argc, char **argv) break; } case EBPF_OPTION_LEGACY: { - ebpf_set_load_mode(EBPF_LOAD_LEGACY); + ebpf_set_load_mode(EBPF_LOAD_LEGACY, EBPF_LOADED_FROM_USER); #ifdef NETDATA_INTERNAL_CHECKS info("EBPF running with \"LEGACY\" code, because it was started with the option \"[-]-legacy\"."); #endif break; } case EBPF_OPTION_CORE: { - ebpf_set_load_mode(EBPF_LOAD_CORE); + ebpf_set_load_mode(EBPF_LOAD_CORE, EBPF_LOADED_FROM_USER); #ifdef NETDATA_INTERNAL_CHECKS info("EBPF running with \"CO-RE\" code, because it was started with the option \"[-]-core\"."); #endif @@ -1816,7 +1980,7 @@ static void ebpf_parse_args(int argc, char **argv) &apps_groups_default_target, &apps_groups_root_target, ebpf_stock_config_dir, "groups")) { error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", ebpf_stock_config_dir); - ebpf_exit(1); + ebpf_exit(); } } else info("Loaded config file '%s/apps_groups.conf'", ebpf_user_config_dir); @@ -1995,6 +2159,7 @@ static void ebpf_manage_pid(pid_t pid) int main(int argc, char **argv) { clocks_init(); + main_thread_id = gettid(); set_global_variables(); ebpf_parse_args(argc, argv); @@ -2035,7 +2200,7 @@ int main(int argc, char **argv) if (ebpf_start_pthread_variables()) { error("Cannot start mutex to control overall charts."); - ebpf_exit(5); + ebpf_exit(); } netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX"); @@ -2058,18 +2223,25 @@ int main(int argc, char **argv) int i; for (i = 0; ebpf_threads[i].name != NULL; i++) { struct netdata_static_thread *st = &ebpf_threads[i]; - st->thread = mallocz(sizeof(netdata_thread_t)); ebpf_module_t *em = &ebpf_modules[i]; - em->thread_id = i; - netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em); + em->thread = st; + // We always initialize process, because it is responsible to take care of apps integration + if (em->enabled || !i) { + st->thread = mallocz(sizeof(netdata_thread_t)); + em->thread_id = i; + st->enabled = NETDATA_THREAD_EBPF_RUNNING; + netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em); + } else { + st->enabled = NETDATA_THREAD_EBPF_STOPPED; + } } - usec_t step = 60 * USEC_PER_SEC; + usec_t step = EBPF_DEFAULT_UPDATE_EVERY * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); //Plugin will be killed when it receives a signal - for (;;) { + while (!ebpf_exit_plugin) { (void)heartbeat_next(&hb, step); } diff --git a/collectors/ebpf.plugin/ebpf.d.conf b/collectors/ebpf.plugin/ebpf.d.conf index aeba473ed..cf5c740fc 100644 --- a/collectors/ebpf.plugin/ebpf.d.conf +++ b/collectors/ebpf.plugin/ebpf.d.conf @@ -26,16 +26,16 @@ # # eBPF Programs # -# The eBPF collector enables and runs the following eBPF programs by default: +# The eBPF collector has the following eBPF programs: # # `cachestat` : Make charts for kernel functions related to page cache. # `dcstat` : Make charts for kernel functions related to directory cache. # `disk` : Monitor I/O latencies for disks # `fd` : This eBPF program creates charts that show information about file manipulation. -# `mdflush` : Monitors flush counts for multi-devices. -# `mount` : Monitor calls for syscalls mount and umount # `filesystem`: Monitor calls for functions used to manipulate specific filesystems # `hardirq` : Monitor latency of serving hardware interrupt requests (hard IRQs). +# `mdflush` : Monitors flush counts for multi-devices. +# `mount` : Monitor calls for syscalls mount and umount # `oomkill` : This eBPF program creates a chart that shows which process got OOM killed and when. # `process` : This eBPF program creates charts that show information about process life. # `shm` : Monitor calls for syscalls shmget, shmat, shmdt and shmctl. @@ -46,6 +46,9 @@ # `swap` : Monitor calls for internal swap functions. # `vfs` : This eBPF program creates charts that show information about process VFS IO, VFS file manipulation and # files removed. +# +# When plugin detects that system has support to BTF, it enables integration with apps.plugin. +# [ebpf programs] cachestat = no dcstat = no @@ -57,7 +60,7 @@ mount = yes oomkill = yes process = yes - shm = yes + shm = no socket = yes softirq = yes sync = yes diff --git a/collectors/ebpf.plugin/ebpf.d/cachestat.conf b/collectors/ebpf.plugin/ebpf.d/cachestat.conf index e2418394e..52466be51 100644 --- a/collectors/ebpf.plugin/ebpf.d/cachestat.conf +++ b/collectors/ebpf.plugin/ebpf.d/cachestat.conf @@ -19,6 +19,11 @@ # `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host. # `probe` : This is the same as legacy code. # +# The `collect pid` option defines the PID stored inside hash tables and accepts the following options: +# `real parent`: Only stores real parent inside PID +# `parent` : Only stores parent PID. +# `all` : Stores all PIDs used by software. This is the most expensive option. +# # Uncomment lines to define specific options for thread. [global] # ebpf load mode = entry @@ -28,3 +33,4 @@ # pid table size = 32768 ebpf type format = auto ebpf co-re tracing = trampoline + collect pid = real parent diff --git a/collectors/ebpf.plugin/ebpf.d/dcstat.conf b/collectors/ebpf.plugin/ebpf.d/dcstat.conf index 3986ae4f8..8aed8f783 100644 --- a/collectors/ebpf.plugin/ebpf.d/dcstat.conf +++ b/collectors/ebpf.plugin/ebpf.d/dcstat.conf @@ -17,6 +17,11 @@ # `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host. # `probe` : This is the same as legacy code. # +# The `collect pid` option defines the PID stored inside hash tables and accepts the following options: +# `real parent`: Only stores real parent inside PID +# `parent` : Only stores parent PID. +# `all` : Stores all PIDs used by software. This is the most expensive option. +# # Uncomment lines to define specific options for thread. [global] # ebpf load mode = entry @@ -26,3 +31,4 @@ # pid table size = 32768 ebpf type format = auto ebpf co-re tracing = trampoline + collect pid = real parent diff --git a/collectors/ebpf.plugin/ebpf.d/fd.conf b/collectors/ebpf.plugin/ebpf.d/fd.conf index f6edd3d93..8333520fc 100644 --- a/collectors/ebpf.plugin/ebpf.d/fd.conf +++ b/collectors/ebpf.plugin/ebpf.d/fd.conf @@ -11,9 +11,11 @@ # The `pid table size` defines the maximum number of PIDs stored inside the hash table. # # Uncomment lines to define specific options for thread. -#[global] +[global] # ebpf load mode = entry # apps = yes # cgroups = no # update every = 10 # pid table size = 32768 + ebpf type format = auto + ebpf co-re tracing = trampoline diff --git a/collectors/ebpf.plugin/ebpf.d/process.conf b/collectors/ebpf.plugin/ebpf.d/process.conf index f6edd3d93..1da5f84d3 100644 --- a/collectors/ebpf.plugin/ebpf.d/process.conf +++ b/collectors/ebpf.plugin/ebpf.d/process.conf @@ -9,6 +9,11 @@ # the setting `apps` and `cgroups` to 'no'. # # The `pid table size` defines the maximum number of PIDs stored inside the hash table. +# +# The `collect pid` option defines the PID stored inside hash tables and accepts the following options: +# `real parent`: Only stores real parent inside PID +# `parent` : Only stores parent PID. +# `all` : Stores all PIDs used by software. This is the most expensive option. # # Uncomment lines to define specific options for thread. #[global] @@ -17,3 +22,4 @@ # cgroups = no # update every = 10 # pid table size = 32768 +# collect pid = real parent diff --git a/collectors/ebpf.plugin/ebpf.d/vfs.conf b/collectors/ebpf.plugin/ebpf.d/vfs.conf index a65e0acbc..fa5d5b4e9 100644 --- a/collectors/ebpf.plugin/ebpf.d/vfs.conf +++ b/collectors/ebpf.plugin/ebpf.d/vfs.conf @@ -9,9 +9,11 @@ # the setting `apps` and `cgroups` to 'no'. # # Uncomment lines to define specific options for thread. -#[global] +[global] # ebpf load mode = entry # apps = yes # cgroups = no # update every = 10 # pid table size = 32768 + ebpf type format = auto + ebpf co-re tracing = trampoline diff --git a/collectors/ebpf.plugin/ebpf.h b/collectors/ebpf.plugin/ebpf.h index c23ca332d..28b04ce48 100644 --- a/collectors/ebpf.plugin/ebpf.h +++ b/collectors/ebpf.plugin/ebpf.h @@ -163,11 +163,12 @@ enum ebpf_algorithms_list { }; // Threads -extern void *ebpf_process_thread(void *ptr); -extern void *ebpf_socket_thread(void *ptr); +void *ebpf_process_thread(void *ptr); +void *ebpf_socket_thread(void *ptr); // Common variables extern pthread_mutex_t lock; +extern pthread_mutex_t ebpf_exit_cleanup; extern int ebpf_nprocs; extern int running_on_kernel; extern int isrh; @@ -177,14 +178,14 @@ extern pthread_mutex_t collect_data_mutex; extern pthread_cond_t collect_data_cond_var; // Common functions -extern void ebpf_global_labels(netdata_syscall_stat_t *is, +void ebpf_global_labels(netdata_syscall_stat_t *is, netdata_publish_syscall_t *pio, char **dim, char **name, int *algorithm, int end); -extern void ebpf_write_chart_cmd(char *type, +void ebpf_write_chart_cmd(char *type, char *id, char *title, char *units, @@ -195,11 +196,11 @@ extern void ebpf_write_chart_cmd(char *type, int update_every, char *module); -extern void ebpf_write_global_dimension(char *name, char *id, char *algorithm); +void ebpf_write_global_dimension(char *name, char *id, char *algorithm); -extern void ebpf_create_global_dimension(void *ptr, int end); +void ebpf_create_global_dimension(void *ptr, int end); -extern void ebpf_create_chart(char *type, +void ebpf_create_chart(char *type, char *id, char *title, char *units, @@ -213,18 +214,18 @@ extern void ebpf_create_chart(char *type, int update_every, char *module); -extern void write_begin_chart(char *family, char *name); +void write_begin_chart(char *family, char *name); -extern void write_chart_dimension(char *dim, long long value); +void write_chart_dimension(char *dim, long long value); -extern void write_count_chart(char *name, char *family, netdata_publish_syscall_t *move, uint32_t end); +void write_count_chart(char *name, char *family, netdata_publish_syscall_t *move, uint32_t end); -extern void write_err_chart(char *name, char *family, netdata_publish_syscall_t *move, int end); +void write_err_chart(char *name, char *family, netdata_publish_syscall_t *move, int end); -extern void write_io_chart(char *chart, char *family, char *dwrite, long long vwrite, +void write_io_chart(char *chart, char *family, char *dwrite, long long vwrite, char *dread, long long vread); -extern void ebpf_create_charts_on_apps(char *name, +void ebpf_create_charts_on_apps(char *name, char *title, char *units, char *family, @@ -235,15 +236,15 @@ extern void ebpf_create_charts_on_apps(char *name, int update_every, char *module); -extern void write_end_chart(); +void write_end_chart(); -extern void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps); +void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps); -extern int ebpf_enable_tracepoint(ebpf_tracepoint_t *tp); -extern int ebpf_disable_tracepoint(ebpf_tracepoint_t *tp); -extern uint32_t ebpf_enable_tracepoints(ebpf_tracepoint_t *tps); +int ebpf_enable_tracepoint(ebpf_tracepoint_t *tp); +int ebpf_disable_tracepoint(ebpf_tracepoint_t *tp); +uint32_t ebpf_enable_tracepoints(ebpf_tracepoint_t *tps); -extern void ebpf_pid_file(char *filename, size_t length); +void ebpf_pid_file(char *filename, size_t length); #define EBPF_PROGRAMS_SECTION "ebpf programs" @@ -271,19 +272,23 @@ extern sem_t *shm_sem_ebpf_cgroup; extern pthread_mutex_t mutex_cgroup_shm; extern size_t all_pids_count; extern ebpf_plugin_stats_t plugin_statistics; +#ifdef LIBBPF_MAJOR_VERSION extern struct btf *default_btf; +#else +extern void *default_btf; +#endif // Socket functions and variables // Common functions -extern void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr); -extern void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr); -extern void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *root); -extern void ebpf_one_dimension_write_charts(char *family, char *chart, char *dim, long long v1); -extern collected_number get_value_from_structure(char *basis, size_t offset); -extern void ebpf_update_pid_table(ebpf_local_maps_t *pid, ebpf_module_t *em); -extern void ebpf_write_chart_obsolete(char *type, char *id, char *title, char *units, char *family, +void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr); +void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr); +void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *root); +void ebpf_one_dimension_write_charts(char *family, char *chart, char *dim, long long v1); +collected_number get_value_from_structure(char *basis, size_t offset); +void ebpf_update_pid_table(ebpf_local_maps_t *pid, ebpf_module_t *em); +void ebpf_write_chart_obsolete(char *type, char *id, char *title, char *units, char *family, char *charttype, char *context, int order, int update_every); -extern void write_histogram_chart(char *family, char *name, const netdata_idx_t *hist, char **dimensions, uint32_t end); +void write_histogram_chart(char *family, char *name, const netdata_idx_t *hist, char **dimensions, uint32_t end); void ebpf_update_disabled_plugin_stats(ebpf_module_t *em); extern ebpf_filesystem_partitions_t localfs[]; extern ebpf_sync_syscalls_t local_syscalls[]; diff --git a/collectors/ebpf.plugin/ebpf_apps.h b/collectors/ebpf.plugin/ebpf_apps.h index f65a137b5..0bea9122f 100644 --- a/collectors/ebpf.plugin/ebpf_apps.h +++ b/collectors/ebpf.plugin/ebpf_apps.h @@ -408,30 +408,30 @@ static inline void debug_log_int(const char *fmt, ...) // extern struct pid_stat **all_pids; -extern int ebpf_read_apps_groups_conf(struct target **apps_groups_default_target, +int ebpf_read_apps_groups_conf(struct target **apps_groups_default_target, struct target **apps_groups_root_target, const char *path, const char *file); -extern void clean_apps_groups_target(struct target *apps_groups_root_target); +void clean_apps_groups_target(struct target *apps_groups_root_target); -extern size_t zero_all_targets(struct target *root); +size_t zero_all_targets(struct target *root); -extern int am_i_running_as_root(); +int am_i_running_as_root(); -extern void cleanup_exited_pids(); +void cleanup_exited_pids(); -extern int ebpf_read_hash_table(void *ep, int fd, uint32_t pid); +int ebpf_read_hash_table(void *ep, int fd, uint32_t pid); -extern int get_pid_comm(pid_t pid, size_t n, char *dest); +int get_pid_comm(pid_t pid, size_t n, char *dest); -extern size_t read_processes_statistic_using_pid_on_target(ebpf_process_stat_t **ep, +size_t read_processes_statistic_using_pid_on_target(ebpf_process_stat_t **ep, int fd, struct pid_on_target *pids); -extern size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct pid_on_target *pids); +size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct pid_on_target *pids); -extern void collect_data_for_all_processes(int tbl_pid_stats_fd); +void collect_data_for_all_processes(int tbl_pid_stats_fd); extern ebpf_process_stat_t **global_process_stats; extern ebpf_process_publish_apps_t **current_apps_data; diff --git a/collectors/ebpf.plugin/ebpf_cachestat.c b/collectors/ebpf.plugin/ebpf_cachestat.c index 14669bf68..4c410647d 100644 --- a/collectors/ebpf.plugin/ebpf_cachestat.c +++ b/collectors/ebpf.plugin/ebpf_cachestat.c @@ -15,11 +15,16 @@ netdata_cachestat_pid_t *cachestat_vector = NULL; static netdata_idx_t cachestat_hash_values[NETDATA_CACHESTAT_END]; static netdata_idx_t *cachestat_values = NULL; -struct netdata_static_thread cachestat_threads = {"CACHESTAT KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL}; - -static ebpf_local_maps_t cachestat_maps[] = {{.name = "cstat_global", .internal_input = NETDATA_CACHESTAT_END, +struct netdata_static_thread cachestat_threads = {.name = "CACHESTAT KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL}; + +ebpf_local_maps_t cachestat_maps[] = {{.name = "cstat_global", .internal_input = NETDATA_CACHESTAT_END, .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC, .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}, {.name = "cstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE, @@ -39,7 +44,6 @@ struct config cachestat_config = { .first_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER, .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare }, .rwlock = AVL_LOCK_INITIALIZER } }; -static enum ebpf_threads_status ebpf_cachestat_exited = NETDATA_THREAD_EBPF_RUNNING; netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru", .mode = EBPF_LOAD_TRAMPOLINE}, {.name = "mark_page_accessed", .mode = EBPF_LOAD_TRAMPOLINE}, @@ -67,6 +71,7 @@ static void ebpf_cachestat_disable_probe(struct cachestat_bpf *obj) bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false); bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false); bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_kprobe, false); } /* @@ -105,6 +110,7 @@ static void ebpf_cachestat_disable_trampoline(struct cachestat_bpf *obj) bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false); bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false); bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false); } /* @@ -156,6 +162,9 @@ static inline void netdata_set_trampoline_target(struct cachestat_bpf *obj) bpf_program__set_attach_target(obj->progs.netdata_mark_buffer_dirty_fentry, 0, cachestat_targets[NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY].name); + + bpf_program__set_attach_target(obj->progs.netdata_release_task_fentry, 0, + EBPF_COMMON_FNCT_CLEAN_UP); } /** @@ -210,6 +219,13 @@ static int ebpf_cachestat_attach_probe(struct cachestat_bpf *obj) if (ret) return -1; + obj->links.netdata_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_kprobe, + false, + EBPF_COMMON_FNCT_CLEAN_UP); + ret = libbpf_get_error(obj->links.netdata_release_task_kprobe); + if (ret) + return -1; + return 0; } @@ -242,6 +258,19 @@ static void ebpf_cachestat_set_hash_tables(struct cachestat_bpf *obj) } /** + * Disable Release Task + * + * Disable release task when apps is not enabled. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_cachestat_disable_release_task(struct cachestat_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_release_task_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false); +} + +/** * Load and attach * * Load and attach the eBPF code in kernel. @@ -266,13 +295,16 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf ebpf_cachestat_disable_specific_probe(obj); } + ebpf_cachestat_adjust_map_size(obj, em); + + if (!em->apps_charts && !em->cgroup_charts) + ebpf_cachestat_disable_release_task(obj); + int ret = cachestat_bpf__load(obj); if (ret) { return ret; } - ebpf_cachestat_adjust_map_size(obj, em); - ret = (test == EBPF_LOAD_TRAMPOLINE) ? cachestat_bpf__attach(obj) : ebpf_cachestat_attach_probe(obj); if (!ret) { ebpf_cachestat_set_hash_tables(obj); @@ -290,6 +322,38 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf *****************************************************************/ /** + * Cachestat Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_cachestat_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated); + + freez(cachestat_vector); + freez(cachestat_values); + freez(cachestat_threads.thread); + +#ifdef LIBBPF_MAJOR_VERSION + if (bpf_obj) + cachestat_bpf__destroy(bpf_obj); +#endif + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** * Cachestat exit. * * Cancel child and exit. @@ -299,12 +363,8 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf static void ebpf_cachestat_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*cachestat_threads.thread); + ebpf_cachestat_free(em); } /** @@ -317,21 +377,7 @@ static void ebpf_cachestat_exit(void *ptr) static void ebpf_cachestat_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_cachestat_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated); - - freez(cachestat_vector); - freez(cachestat_values); - freez(cachestat_threads.thread); - -#ifdef LIBBPF_MAJOR_VERSION - if (bpf_obj) - cachestat_bpf__destroy(bpf_obj); -#endif - cachestat_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_cachestat_free(em); } /***************************************************************** @@ -649,17 +695,12 @@ void *ebpf_cachestat_read_hash(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_LATENCY_CACHESTAT_SLEEP_MS * em->update_every; - while (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -872,21 +913,16 @@ static void ebpf_create_systemd_cachestat_charts(int update_every) * Send Cache Stat charts * * Send collected data to Netdata. - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_cachestat_charts() +static void ebpf_send_systemd_cachestat_charts() { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_CACHESTAT_HIT_RATIO_CHART); for (ect = ebpf_cgroup_pids; ect; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long)ect->publish_cachestat.ratio); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -913,8 +949,6 @@ static int ebpf_send_systemd_cachestat_charts() } } write_end_chart(); - - return ret; } /** @@ -1038,13 +1072,11 @@ void ebpf_cachestat_send_cgroup_data(int update_every) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_cachestat_charts(update_every); - systemd_charts = 1; } - systemd_charts = ebpf_send_systemd_cachestat_charts(); + ebpf_send_systemd_cachestat_charts(); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -1227,7 +1259,8 @@ static void ebpf_cachestat_set_internal_value() static int ebpf_cachestat_load_bpf(ebpf_module_t *em) { int ret = 0; - if (em->load == EBPF_LOAD_LEGACY) { + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].mode); + if (em->load & EBPF_LOAD_LEGACY) { em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { ret = -1; @@ -1267,16 +1300,13 @@ void *ebpf_cachestat_thread(void *ptr) ebpf_update_pid_table(&cachestat_maps[NETDATA_CACHESTAT_PID_STATS], em); - if (!em->enabled) - goto endcachestat; - ebpf_cachestat_set_internal_value(); #ifdef LIBBPF_MAJOR_VERSION ebpf_adjust_thread_load(em, default_btf); #endif if (ebpf_cachestat_load_bpf(em)) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endcachestat; } @@ -1298,8 +1328,7 @@ void *ebpf_cachestat_thread(void *ptr) cachestat_collector(em); endcachestat: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_cachestat.h b/collectors/ebpf.plugin/ebpf_cachestat.h index fdd88464a..07f0745d4 100644 --- a/collectors/ebpf.plugin/ebpf_cachestat.h +++ b/collectors/ebpf.plugin/ebpf_cachestat.h @@ -81,9 +81,10 @@ typedef struct netdata_publish_cachestat { netdata_cachestat_pid_t prev; } netdata_publish_cachestat_t; -extern void *ebpf_cachestat_thread(void *ptr); +void *ebpf_cachestat_thread(void *ptr); extern struct config cachestat_config; extern netdata_ebpf_targets_t cachestat_targets[]; +extern ebpf_local_maps_t cachestat_maps[]; #endif // NETDATA_EBPF_CACHESTAT_H diff --git a/collectors/ebpf.plugin/ebpf_cgroup.c b/collectors/ebpf.plugin/ebpf_cgroup.c index 24469c642..42c045368 100644 --- a/collectors/ebpf.plugin/ebpf_cgroup.c +++ b/collectors/ebpf.plugin/ebpf_cgroup.c @@ -6,6 +6,7 @@ #include "ebpf_cgroup.h" ebpf_cgroup_target_t *ebpf_cgroup_pids = NULL; +int send_cgroup_chart = 0; // -------------------------------------------------------------------------------------------------------------------- // Map shared memory @@ -99,24 +100,6 @@ void ebpf_map_cgroup_shared_memory() // Close and Cleanup /** - * Close shared memory - */ -void ebpf_close_cgroup_shm() -{ - if (shm_sem_ebpf_cgroup != SEM_FAILED) { - sem_close(shm_sem_ebpf_cgroup); - sem_unlink(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME); - shm_sem_ebpf_cgroup = SEM_FAILED; - } - - if (shm_fd_ebpf_cgroup > 0) { - close(shm_fd_ebpf_cgroup); - shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME); - shm_fd_ebpf_cgroup = -1; - } -} - -/** * Clean Specific cgroup pid * * Clean all PIDs associated with cgroup. @@ -259,7 +242,7 @@ static void ebpf_update_pid_link_list(ebpf_cgroup_target_t *ect, char *path) * * Set variable remove. If this variable is not reset, the structure will be removed from link list. */ - void ebpf_reset_updated_var() +void ebpf_reset_updated_var() { ebpf_cgroup_target_t *ect; for (ect = ebpf_cgroup_pids; ect; ect = ect->next) { @@ -274,6 +257,7 @@ static void ebpf_update_pid_link_list(ebpf_cgroup_target_t *ect, char *path) */ void ebpf_parse_cgroup_shm_data() { + static int previous = 0; if (shm_ebpf_cgroup.header) { sem_wait(shm_sem_ebpf_cgroup); int i, end = shm_ebpf_cgroup.header->cgroup_root_count; @@ -291,6 +275,11 @@ void ebpf_parse_cgroup_shm_data() ebpf_update_pid_link_list(ect, ptr->path); } } + send_cgroup_chart = previous != shm_ebpf_cgroup.header->cgroup_root_count; + previous = shm_ebpf_cgroup.header->cgroup_root_count; +#ifdef NETDATA_DEV_MODE + error("Updating cgroup %d (Previous: %d, Current: %d)", send_cgroup_chart, previous, shm_ebpf_cgroup.header->cgroup_root_count); +#endif pthread_mutex_unlock(&mutex_cgroup_shm); sem_post(shm_sem_ebpf_cgroup); diff --git a/collectors/ebpf.plugin/ebpf_cgroup.h b/collectors/ebpf.plugin/ebpf_cgroup.h index cca9a950d..19da7fca9 100644 --- a/collectors/ebpf.plugin/ebpf_cgroup.h +++ b/collectors/ebpf.plugin/ebpf_cgroup.h @@ -60,10 +60,10 @@ typedef struct ebpf_cgroup_target { struct ebpf_cgroup_target *next; } ebpf_cgroup_target_t; -extern void ebpf_map_cgroup_shared_memory(); -extern void ebpf_parse_cgroup_shm_data(); -extern void ebpf_close_cgroup_shm(); -extern void ebpf_create_charts_on_systemd(char *id, char *title, char *units, char *family, char *charttype, int order, +void ebpf_map_cgroup_shared_memory(); +void ebpf_parse_cgroup_shm_data(); +void ebpf_create_charts_on_systemd(char *id, char *title, char *units, char *family, char *charttype, int order, char *algorithm, char *context, char *module, int update_every); +extern int send_cgroup_chart; #endif /* NETDATA_EBPF_CGROUP_H */ diff --git a/collectors/ebpf.plugin/ebpf_dcstat.c b/collectors/ebpf.plugin/ebpf_dcstat.c index 8cf063ca1..71169e153 100644 --- a/collectors/ebpf.plugin/ebpf_dcstat.c +++ b/collectors/ebpf.plugin/ebpf_dcstat.c @@ -20,11 +20,15 @@ struct config dcstat_config = { .first_section = NULL, .rwlock = AVL_LOCK_INITIALIZER } }; struct netdata_static_thread dcstat_threads = {"DCSTAT KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL}; -static enum ebpf_threads_status ebpf_dcstat_exited = NETDATA_THREAD_EBPF_RUNNING; - -static ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END, + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL}; + +ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END, .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC, .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}, {.name = "dcstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE, @@ -65,6 +69,7 @@ static inline void ebpf_dc_disable_probes(struct dc_bpf *obj) { bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false); bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false); } /* @@ -78,6 +83,7 @@ static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj) { bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false); bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false); } /** @@ -94,6 +100,9 @@ static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj) bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0, dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name); + + bpf_program__set_attach_target(obj->progs.netdata_dcstat_release_task_fentry, 0, + EBPF_COMMON_FNCT_CLEAN_UP); } /** @@ -125,6 +134,13 @@ static int ebpf_dc_attach_probes(struct dc_bpf *obj) if (ret) return -1; + obj->links.netdata_dcstat_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_dcstat_release_task_kprobe, + false, + EBPF_COMMON_FNCT_CLEAN_UP); + ret = libbpf_get_error(obj->links.netdata_dcstat_release_task_kprobe); + if (ret) + return -1; + return 0; } @@ -180,6 +196,19 @@ netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em) } /** + * Disable Release Task + * + * Disable release task when apps is not enabled. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_dc_disable_release_task(struct dc_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false); +} + +/** * Load and attach * * Load and attach the eBPF code in kernel. @@ -200,13 +229,16 @@ static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em) ebpf_dc_disable_trampoline(obj); } + ebpf_dc_adjust_map_size(obj, em); + + if (!em->apps_charts && !em->cgroup_charts) + ebpf_dc_disable_release_task(obj); + int ret = dc_bpf__load(obj); if (ret) { return ret; } - ebpf_dc_adjust_map_size(obj, em); - ret = (test == EBPF_LOAD_TRAMPOLINE) ? dc_bpf__attach(obj) : ebpf_dc_attach_probes(obj); if (!ret) { ebpf_dc_set_hash_tables(obj); @@ -262,33 +294,21 @@ void ebpf_dcstat_clean_names() } /** - * DCstat exit + * DCstat Free * - * Cancel child and exit. + * Cleanup variables after child threads to stop * * @param ptr thread data. */ -static void ebpf_dcstat_exit(void *ptr) +static void ebpf_dcstat_free(ebpf_module_t *em ) { - ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); return; } - - ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPING; -} - -/** - * Clean up the main thread. - * - * @param ptr thread data. - */ -static void ebpf_dcstat_cleanup(void *ptr) -{ - ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_dcstat_exited != NETDATA_THREAD_EBPF_STOPPED) - return; + pthread_mutex_unlock(&ebpf_exit_cleanup); freez(dcstat_vector); freez(dcstat_values); @@ -303,8 +323,34 @@ static void ebpf_dcstat_cleanup(void *ptr) dc_bpf__destroy(bpf_obj); #endif - dcstat_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** + * DCstat exit + * + * Cancel child and exit. + * + * @param ptr thread data. + */ +static void ebpf_dcstat_exit(void *ptr) +{ + ebpf_module_t *em = (ebpf_module_t *)ptr; + netdata_thread_cancel(*dcstat_threads.thread); + ebpf_dcstat_free(em); +} + +/** + * Clean up the main thread. + * + * @param ptr thread data. + */ +static void ebpf_dcstat_cleanup(void *ptr) +{ + ebpf_module_t *em = (ebpf_module_t *)ptr; + ebpf_dcstat_free(em); } /***************************************************************** @@ -531,17 +577,12 @@ void *ebpf_dcstat_read_hash(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_LATENCY_DCSTAT_SLEEP_MS * em->update_every; - while (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -860,21 +901,16 @@ static void ebpf_create_systemd_dc_charts(int update_every) * Send Directory Cache charts * * Send collected data to Netdata. - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_dc_charts() +static void ebpf_send_systemd_dc_charts() { - int ret = 1; collected_number value; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_HIT_CHART); for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long) ect->publish_dc.ratio); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -910,8 +946,6 @@ static int ebpf_send_systemd_dc_charts() } } write_end_chart(); - - return ret; } /** @@ -966,13 +1000,11 @@ void ebpf_dc_send_cgroup_data(int update_every) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_dc_charts(update_every); - systemd_charts = 1; } - systemd_charts = ebpf_send_systemd_dc_charts(); + ebpf_send_systemd_dc_charts(); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -1116,7 +1148,8 @@ static void ebpf_dcstat_allocate_global_vectors(int apps) static int ebpf_dcstat_load_bpf(ebpf_module_t *em) { int ret = 0; - if (em->load == EBPF_LOAD_LEGACY) { + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode); + if (em->load & EBPF_LOAD_LEGACY) { em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { ret = -1; @@ -1158,14 +1191,11 @@ void *ebpf_dcstat_thread(void *ptr) ebpf_update_names(dc_optional_name, em); - if (!em->enabled) - goto enddcstat; - #ifdef LIBBPF_MAJOR_VERSION ebpf_adjust_thread_load(em, default_btf); #endif if (ebpf_dcstat_load_bpf(em)) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto enddcstat; } @@ -1188,8 +1218,7 @@ void *ebpf_dcstat_thread(void *ptr) dcstat_collector(em); enddcstat: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_dcstat.h b/collectors/ebpf.plugin/ebpf_dcstat.h index 5c4a80cd7..d8687f968 100644 --- a/collectors/ebpf.plugin/ebpf_dcstat.h +++ b/collectors/ebpf.plugin/ebpf_dcstat.h @@ -75,9 +75,10 @@ typedef struct netdata_publish_dcstat { netdata_dcstat_pid_t prev; } netdata_publish_dcstat_t; -extern void *ebpf_dcstat_thread(void *ptr); -extern void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr); +void *ebpf_dcstat_thread(void *ptr); +void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr); extern struct config dcstat_config; extern netdata_ebpf_targets_t dc_targets[]; +extern ebpf_local_maps_t dcstat_maps[]; #endif // NETDATA_EBPF_DCSTAT_H diff --git a/collectors/ebpf.plugin/ebpf_disk.c b/collectors/ebpf.plugin/ebpf_disk.c index 96b1705ce..a27bd81e3 100644 --- a/collectors/ebpf.plugin/ebpf_disk.c +++ b/collectors/ebpf.plugin/ebpf_disk.c @@ -33,10 +33,16 @@ static netdata_syscall_stat_t disk_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS]; static netdata_publish_syscall_t disk_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS]; static netdata_idx_t *disk_hash_values = NULL; -static struct netdata_static_thread disk_threads = {"DISK KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL }; -static enum ebpf_threads_status ebpf_disk_exited = NETDATA_THREAD_EBPF_RUNNING; +static struct netdata_static_thread disk_threads = { + .name = "DISK KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; ebpf_publish_disk_t *plot_disks = NULL; pthread_mutex_t plot_mutex; @@ -424,6 +430,40 @@ static void ebpf_cleanup_disk_list() } /** + * DISK Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_disk_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + ebpf_disk_disable_tracepoints(); + + if (dimensions) + ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS); + + freez(disk_hash_values); + freez(disk_threads.thread); + pthread_mutex_destroy(&plot_mutex); + + ebpf_cleanup_plot_disks(); + ebpf_cleanup_disk_list(); + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** * Disk exit. * * Cancel child and exit. @@ -433,12 +473,8 @@ static void ebpf_cleanup_disk_list() static void ebpf_disk_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*disk_threads.thread); + ebpf_disk_free(em); } /** @@ -451,23 +487,7 @@ static void ebpf_disk_exit(void *ptr) static void ebpf_disk_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_disk_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - ebpf_disk_disable_tracepoints(); - - if (dimensions) - ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS); - - freez(disk_hash_values); - freez(disk_threads.thread); - pthread_mutex_destroy(&plot_mutex); - - ebpf_cleanup_plot_disks(); - ebpf_cleanup_disk_list(); - - disk_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_disk_free(em); } /***************************************************************** @@ -590,17 +610,12 @@ void *ebpf_disk_read_hash(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_LATENCY_DISK_SLEEP_MS * em->update_every; - while (ebpf_disk_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_disk_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd); } - ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -805,29 +820,26 @@ void *ebpf_disk_thread(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; em->maps = disk_maps; - if (!em->enabled) - goto enddisk; - if (ebpf_disk_enable_tracepoints()) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto enddisk; } avl_init_lock(&disk_tree, ebpf_compare_disks); if (read_local_disks()) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto enddisk; } if (pthread_mutex_init(&plot_mutex, NULL)) { - em->enabled = 0; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; error("Cannot initialize local mutex"); goto enddisk; } em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { - em->enabled = 0; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto enddisk; } @@ -845,8 +857,7 @@ void *ebpf_disk_thread(void *ptr) disk_collector(em); enddisk: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); diff --git a/collectors/ebpf.plugin/ebpf_disk.h b/collectors/ebpf.plugin/ebpf_disk.h index 8e58174b9..c14b887f8 100644 --- a/collectors/ebpf.plugin/ebpf_disk.h +++ b/collectors/ebpf.plugin/ebpf_disk.h @@ -72,7 +72,7 @@ typedef struct netdata_ebpf_publish_disk { extern struct config disk_config; -extern void *ebpf_disk_thread(void *ptr); +void *ebpf_disk_thread(void *ptr); #endif /* NETDATA_EBPF_DISK_H */ diff --git a/collectors/ebpf.plugin/ebpf_fd.c b/collectors/ebpf.plugin/ebpf_fd.c index b4e577dad..30b7f22ce 100644 --- a/collectors/ebpf.plugin/ebpf_fd.c +++ b/collectors/ebpf.plugin/ebpf_fd.c @@ -29,15 +29,301 @@ struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare }, .rwlock = AVL_LOCK_INITIALIZER } }; -struct netdata_static_thread fd_thread = {"FD KERNEL", NULL, NULL, 1, NULL, - NULL, NULL}; -static enum ebpf_threads_status ebpf_fd_exited = NETDATA_THREAD_EBPF_RUNNING; +struct netdata_static_thread fd_thread = {"FD KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL}; + static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER]; static netdata_idx_t *fd_values = NULL; netdata_fd_stat_t *fd_vector = NULL; netdata_fd_stat_t **fd_pid = NULL; +netdata_ebpf_targets_t fd_targets[] = { {.name = "open", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "close", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}}; + +#ifdef LIBBPF_MAJOR_VERSION +#include "includes/fd.skel.h" // BTF code + +static struct fd_bpf *bpf_obj = NULL; + +/** + * Disable probe + * + * Disable all probes to use exclusively another method. + * + * @param obj is the main structure for bpf objects +*/ +static inline void ebpf_fd_disable_probes(struct fd_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_sys_open_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_sys_open_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false); + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) { + bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false); + } else { + bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false); + } +} + +/* + * Disable specific probe + * + * Disable probes according the kernel version + * + * @param obj is the main structure for bpf objects + */ +static inline void ebpf_disable_specific_probes(struct fd_bpf *obj) +{ + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) { + bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false); + } else { + bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false); + } +} + +/* + * Disable trampoline + * + * Disable all trampoline to use exclusively another method. + * + * @param obj is the main structure for bpf objects. + */ +static inline void ebpf_disable_trampoline(struct fd_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_sys_open_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_sys_open_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false); + bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false); + bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false); +} + +/* + * Disable specific trampoline + * + * Disable trampoline according to kernel version. + * + * @param obj is the main structure for bpf objects. + */ +static inline void ebpf_disable_specific_trampoline(struct fd_bpf *obj) +{ + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) { + bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false); + bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false); + } else { + bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false); + } +} + +/** + * Set trampoline target + * + * Set the targets we will monitor. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_set_trampoline_target(struct fd_bpf *obj) +{ + bpf_program__set_attach_target(obj->progs.netdata_sys_open_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name); + bpf_program__set_attach_target(obj->progs.netdata_sys_open_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name); + bpf_program__set_attach_target(obj->progs.netdata_release_task_fd_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP); + + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) { + bpf_program__set_attach_target( + obj->progs.netdata_close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + bpf_program__set_attach_target(obj->progs.netdata_close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + } else { + bpf_program__set_attach_target( + obj->progs.netdata___close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + bpf_program__set_attach_target( + obj->progs.netdata___close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + } +} + +/** + * Mount Attach Probe + * + * Attach probes to target + * + * @param obj is the main structure for bpf objects. + * + * @return It returns 0 on success and -1 otherwise. + */ +static int ebpf_fd_attach_probe(struct fd_bpf *obj) +{ + obj->links.netdata_sys_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kprobe, false, + fd_targets[NETDATA_FD_SYSCALL_OPEN].name); + int ret = libbpf_get_error(obj->links.netdata_sys_open_kprobe); + if (ret) + return -1; + + obj->links.netdata_sys_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kretprobe, true, + fd_targets[NETDATA_FD_SYSCALL_OPEN].name); + ret = libbpf_get_error(obj->links.netdata_sys_open_kretprobe); + if (ret) + return -1; + + obj->links.netdata_release_task_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_fd_kprobe, + false, + EBPF_COMMON_FNCT_CLEAN_UP); + ret = libbpf_get_error(obj->links.netdata_release_task_fd_kprobe); + if (ret) + return -1; + + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) { + obj->links.netdata_close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kretprobe, true, + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + ret = libbpf_get_error(obj->links.netdata_close_fd_kretprobe); + if (ret) + return -1; + + obj->links.netdata_close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kprobe, false, + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + ret = libbpf_get_error(obj->links.netdata_close_fd_kprobe); + if (ret) + return -1; + } else { + obj->links.netdata___close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kretprobe, + true, + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + ret = libbpf_get_error(obj->links.netdata___close_fd_kretprobe); + if (ret) + return -1; + + obj->links.netdata___close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kprobe, + false, + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name); + ret = libbpf_get_error(obj->links.netdata___close_fd_kprobe); + if (ret) + return -1; + } + + return 0; +} + +/** + * Set target values + * + * Set pointers used to laod data. + */ +static void ebpf_fd_set_target_values() +{ + static char *close_targets[] = {"close_fd", "__close_fd"}; + static char *open_targets[] = {"do_sys_openat2", "do_sys_open"}; + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) { + fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[0]; + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[0]; + } else { + fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[1]; + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[1]; + } +} + +/** + * Set hash tables + * + * Set the values for maps according the value given by kernel. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_fd_set_hash_tables(struct fd_bpf *obj) +{ + fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_global); + fd_maps[NETDATA_FD_PID_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_pid); + fd_maps[NETDATA_FD_CONTROLLER].map_fd = bpf_map__fd(obj->maps.fd_ctrl); +} + +/** + * Adjust Map Size + * + * Resize maps according input from users. + * + * @param obj is the main structure for bpf objects. + * @param em structure with configuration + */ +static void ebpf_fd_adjust_map_size(struct fd_bpf *obj, ebpf_module_t *em) +{ + ebpf_update_map_size(obj->maps.tbl_fd_pid, &fd_maps[NETDATA_FD_PID_STATS], + em, bpf_map__name(obj->maps.tbl_fd_pid)); +} + +/** + * Disable Release Task + * + * Disable release task when apps is not enabled. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_fd_disable_release_task(struct fd_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false); +} + +/** + * Load and attach + * + * Load and attach the eBPF code in kernel. + * + * @param obj is the main structure for bpf objects. + * @param em structure with configuration + * + * @return it returns 0 on succes and -1 otherwise + */ +static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em) +{ + netdata_ebpf_targets_t *mt = em->targets; + netdata_ebpf_program_loaded_t test = mt[NETDATA_FD_SYSCALL_OPEN].mode; + + ebpf_fd_set_target_values(); + if (test == EBPF_LOAD_TRAMPOLINE) { + ebpf_fd_disable_probes(obj); + ebpf_disable_specific_trampoline(obj); + + ebpf_set_trampoline_target(obj); + // TODO: Remove this in next PR, because this specific trampoline has an error. + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false); + } else { + ebpf_disable_trampoline(obj); + ebpf_disable_specific_probes(obj); + } + + ebpf_fd_adjust_map_size(obj, em); + + if (!em->apps_charts && !em->cgroup_charts) + ebpf_fd_disable_release_task(obj); + + int ret = fd_bpf__load(obj); + if (ret) { + return ret; + } + + ret = (test == EBPF_LOAD_TRAMPOLINE) ? fd_bpf__attach(obj) : ebpf_fd_attach_probe(obj); + if (!ret) { + ebpf_fd_set_hash_tables(obj); + + ebpf_update_controller(fd_maps[NETDATA_CACHESTAT_CTRL].map_fd, em); + } + + return ret; +} +#endif + /***************************************************************** * * FUNCTIONS TO CLOSE THE THREAD @@ -45,6 +331,38 @@ netdata_fd_stat_t **fd_pid = NULL; *****************************************************************/ /** + * FD Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_fd_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + ebpf_cleanup_publish_syscall(fd_publish_aggregated); + freez(fd_thread.thread); + freez(fd_values); + freez(fd_vector); + +#ifdef LIBBPF_MAJOR_VERSION + if (bpf_obj) + fd_bpf__destroy(bpf_obj); +#endif + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** * FD Exit * * Cancel child thread and exit. @@ -54,12 +372,8 @@ netdata_fd_stat_t **fd_pid = NULL; static void ebpf_fd_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*fd_thread.thread); + ebpf_fd_free(em); } /** @@ -70,16 +384,7 @@ static void ebpf_fd_exit(void *ptr) static void ebpf_fd_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_fd_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - ebpf_cleanup_publish_syscall(fd_publish_aggregated); - freez(fd_thread.thread); - freez(fd_values); - freez(fd_vector); - - fd_thread.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_fd_free(em); } /***************************************************************** @@ -153,17 +458,12 @@ void *ebpf_fd_read_hash(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_FD_SLEEP_MS * em->update_every; - while (ebpf_fd_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_fd_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -549,20 +849,15 @@ static void ebpf_create_systemd_fd_charts(ebpf_module_t *em) * Send collected data to Netdata. * * @param em the main collector structure - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_fd_charts(ebpf_module_t *em) +static void ebpf_send_systemd_fd_charts(ebpf_module_t *em) { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN); for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, ect->publish_systemd_fd.open_call); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -593,8 +888,6 @@ static int ebpf_send_systemd_fd_charts(ebpf_module_t *em) } write_end_chart(); } - - return ret; } /** @@ -615,13 +908,11 @@ static void ebpf_fd_send_cgroup_data(ebpf_module_t *em) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_fd_charts(em); - systemd_charts = 1; } - systemd_charts = ebpf_send_systemd_fd_charts(em); + ebpf_send_systemd_fd_charts(em); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -810,6 +1101,40 @@ static void ebpf_fd_allocate_global_vectors(int apps) fd_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t)); } +/* + * Load BPF + * + * Load BPF files. + * + * @param em the structure with configuration + */ +static int ebpf_fd_load_bpf(ebpf_module_t *em) +{ + int ret = 0; + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_FD_SYSCALL_OPEN].mode); + if (em->load & EBPF_LOAD_LEGACY) { + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); + if (!em->probe_links) { + em->enabled = CONFIG_BOOLEAN_NO; + ret = -1; + } + } +#ifdef LIBBPF_MAJOR_VERSION + else { + bpf_obj = fd_bpf__open(); + if (!bpf_obj) + ret = -1; + else + ret = ebpf_fd_load_and_attach(bpf_obj, em); + } +#endif + + if (ret) + error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name); + + return ret; +} + /** * Directory Cache thread * @@ -826,17 +1151,16 @@ void *ebpf_fd_thread(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; em->maps = fd_maps; - if (!em->enabled) +#ifdef LIBBPF_MAJOR_VERSION + ebpf_adjust_thread_load(em, default_btf); +#endif + if (ebpf_fd_load_bpf(em)) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endfd; + } ebpf_fd_allocate_global_vectors(em->apps_charts); - em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); - if (!em->probe_links) { - em->enabled = CONFIG_BOOLEAN_NO; - goto endfd; - } - int algorithms[NETDATA_FD_SYSCALL_END] = { NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX }; @@ -852,8 +1176,7 @@ void *ebpf_fd_thread(void *ptr) fd_collector(em); endfd: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_fd.h b/collectors/ebpf.plugin/ebpf_fd.h index 8742558df..914a34b98 100644 --- a/collectors/ebpf.plugin/ebpf_fd.h +++ b/collectors/ebpf.plugin/ebpf_fd.h @@ -75,10 +75,11 @@ enum fd_syscalls { }; -extern void *ebpf_fd_thread(void *ptr); -extern void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr); +void *ebpf_fd_thread(void *ptr); +void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr); extern struct config fd_config; extern netdata_fd_stat_t **fd_pid; +extern netdata_ebpf_targets_t fd_targets[]; #endif /* NETDATA_EBPF_FD_H */ diff --git a/collectors/ebpf.plugin/ebpf_filesystem.c b/collectors/ebpf.plugin/ebpf_filesystem.c index bc767fbc9..7dbec7410 100644 --- a/collectors/ebpf.plugin/ebpf_filesystem.c +++ b/collectors/ebpf.plugin/ebpf_filesystem.c @@ -30,10 +30,16 @@ static ebpf_local_maps_t fs_maps[] = {{.name = "tbl_ext4", .internal_input = NET .type = NETDATA_EBPF_MAP_CONTROLLER, .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}}; -struct netdata_static_thread filesystem_threads = {"EBPF FS READ", - NULL, NULL, 1, NULL, - NULL, NULL }; -static enum ebpf_threads_status ebpf_fs_exited = NETDATA_THREAD_EBPF_RUNNING; +struct netdata_static_thread filesystem_threads = { + .name = "EBPF FS READ", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS]; static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS]; @@ -317,22 +323,41 @@ void ebpf_filesystem_cleanup_ebpf_data() freez(efp->hadditional.name); freez(efp->hadditional.title); - - struct bpf_link **probe_links = efp->probe_links; - size_t j = 0 ; - struct bpf_program *prog; - bpf_object__for_each_program(prog, efp->objects) { - bpf_link__destroy(probe_links[j]); - j++; - } - freez(probe_links); - if (efp->objects) - bpf_object__close(efp->objects); } } } /** + * Filesystem Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_filesystem_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + freez(filesystem_threads.thread); + ebpf_cleanup_publish_syscall(filesystem_publish_aggregated); + + ebpf_filesystem_cleanup_ebpf_data(); + if (dimensions) + ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS); + freez(filesystem_hash_values); + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** * Filesystem exit * * Cancel child thread. @@ -342,12 +367,8 @@ void ebpf_filesystem_cleanup_ebpf_data() static void ebpf_filesystem_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*filesystem_threads.thread); + ebpf_filesystem_free(em); } /** @@ -360,19 +381,7 @@ static void ebpf_filesystem_exit(void *ptr) static void ebpf_filesystem_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_fs_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - freez(filesystem_threads.thread); - ebpf_cleanup_publish_syscall(filesystem_publish_aggregated); - - ebpf_filesystem_cleanup_ebpf_data(); - if (dimensions) - ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS); - freez(filesystem_hash_values); - - filesystem_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_filesystem_free(em); } /***************************************************************** @@ -483,11 +492,8 @@ void *ebpf_filesystem_read_hash(void *ptr) heartbeat_init(&hb); usec_t step = NETDATA_FILESYSTEM_READ_SLEEP_MS * em->update_every; int update_every = em->update_every; - while (ebpf_fs_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_fs_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); (void) ebpf_update_partitions(em); ebpf_obsolete_fs_charts(update_every); @@ -499,8 +505,6 @@ void *ebpf_filesystem_read_hash(void *ptr) read_filesystem_tables(); } - ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -603,9 +607,6 @@ void *ebpf_filesystem_thread(void *ptr) em->maps = fs_maps; ebpf_update_filesystem(); - if (!em->enabled) - goto endfilesystem; - // Initialize optional as zero, to identify when there are not partitions to monitor em->optional = 0; @@ -613,7 +614,7 @@ void *ebpf_filesystem_thread(void *ptr) if (em->optional) info("Netdata cannot monitor the filesystems used on this host."); - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endfilesystem; } @@ -630,8 +631,7 @@ void *ebpf_filesystem_thread(void *ptr) filesystem_collector(em); endfilesystem: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_filesystem.h b/collectors/ebpf.plugin/ebpf_filesystem.h index f6a10c874..0d558df7d 100644 --- a/collectors/ebpf.plugin/ebpf_filesystem.h +++ b/collectors/ebpf.plugin/ebpf_filesystem.h @@ -43,7 +43,7 @@ enum netdata_filesystem_table { NETDATA_ADDR_FS_TABLE }; -extern void *ebpf_filesystem_thread(void *ptr); +void *ebpf_filesystem_thread(void *ptr); extern struct config fs_config; #endif /* NETDATA_EBPF_FILESYSTEM_H */ diff --git a/collectors/ebpf.plugin/ebpf_hardirq.c b/collectors/ebpf.plugin/ebpf_hardirq.c index 41a881647..b07dd24ca 100644 --- a/collectors/ebpf.plugin/ebpf_hardirq.c +++ b/collectors/ebpf.plugin/ebpf_hardirq.c @@ -135,10 +135,43 @@ static hardirq_ebpf_val_t *hardirq_ebpf_vals = NULL; // tmp store for static hard IRQ values we get from a per-CPU eBPF map. static hardirq_ebpf_static_val_t *hardirq_ebpf_static_vals = NULL; -static struct netdata_static_thread hardirq_threads = {"HARDIRQ KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL }; -static enum ebpf_threads_status ebpf_hardirq_exited = NETDATA_THREAD_EBPF_RUNNING; +static struct netdata_static_thread hardirq_threads = { + .name = "HARDIRQ KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; + +/** + * Hardirq Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_hardirq_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + freez(hardirq_threads.thread); + for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) { + ebpf_disable_tracepoint(&hardirq_tracepoints[i]); + } + freez(hardirq_ebpf_vals); + freez(hardirq_ebpf_static_vals); + + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; +} /** * Hardirq Exit @@ -150,12 +183,8 @@ static enum ebpf_threads_status ebpf_hardirq_exited = NETDATA_THREAD_EBPF_RUNNIN static void hardirq_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*hardirq_threads.thread); + ebpf_hardirq_free(em); } /** @@ -168,19 +197,7 @@ static void hardirq_exit(void *ptr) static void hardirq_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - - if (ebpf_hardirq_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - freez(hardirq_threads.thread); - for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) { - ebpf_disable_tracepoint(&hardirq_tracepoints[i]); - } - freez(hardirq_ebpf_vals); - freez(hardirq_ebpf_static_vals); - - hardirq_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_hardirq_free(em); } /***************************************************************** @@ -323,16 +340,12 @@ static void *hardirq_reader(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_HARDIRQ_SLEEP_MS * em->update_every; - while (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - UNUSED(dt); - if (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); hardirq_read_latency_map(hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd); hardirq_read_latency_static_map(hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd); } - ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPED; netdata_thread_cleanup_pop(1); return NULL; @@ -472,26 +485,21 @@ void *ebpf_hardirq_thread(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; em->maps = hardirq_maps; - if (!em->enabled) { - goto endhardirq; - } - if (ebpf_enable_tracepoints(hardirq_tracepoints) == 0) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endhardirq; } em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endhardirq; } hardirq_collector(em); endhardirq: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); diff --git a/collectors/ebpf.plugin/ebpf_hardirq.h b/collectors/ebpf.plugin/ebpf_hardirq.h index 4c8a7a098..381da57d8 100644 --- a/collectors/ebpf.plugin/ebpf_hardirq.h +++ b/collectors/ebpf.plugin/ebpf_hardirq.h @@ -68,6 +68,6 @@ typedef struct hardirq_static_val { } hardirq_static_val_t; extern struct config hardirq_config; -extern void *ebpf_hardirq_thread(void *ptr); +void *ebpf_hardirq_thread(void *ptr); #endif /* NETDATA_EBPF_HARDIRQ_H */ diff --git a/collectors/ebpf.plugin/ebpf_mdflush.c b/collectors/ebpf.plugin/ebpf_mdflush.c index 4dca04505..dc805da23 100644 --- a/collectors/ebpf.plugin/ebpf_mdflush.c +++ b/collectors/ebpf.plugin/ebpf_mdflush.c @@ -35,10 +35,39 @@ static avl_tree_lock mdflush_pub; // tmp store for mdflush values we get from a per-CPU eBPF map. static mdflush_ebpf_val_t *mdflush_ebpf_vals = NULL; -static struct netdata_static_thread mdflush_threads = {"MDFLUSH KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL }; -static enum ebpf_threads_status ebpf_mdflush_exited = NETDATA_THREAD_EBPF_RUNNING; +static struct netdata_static_thread mdflush_threads = { + .name = "MDFLUSH KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; + +/** + * MDflush Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_mdflush_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + freez(mdflush_ebpf_vals); + freez(mdflush_threads.thread); + + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; +} /** * MDflush exit @@ -50,12 +79,7 @@ static enum ebpf_threads_status ebpf_mdflush_exited = NETDATA_THREAD_EBPF_RUNNIN static void mdflush_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_mdflush_exited = NETDATA_THREAD_EBPF_STOPPING; + ebpf_mdflush_free(em); } /** @@ -68,14 +92,8 @@ static void mdflush_exit(void *ptr) static void mdflush_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_mdflush_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - freez(mdflush_ebpf_vals); - freez(mdflush_threads.thread); - - mdflush_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + netdata_thread_cancel(*mdflush_threads.thread); + ebpf_mdflush_free(em); } /** @@ -182,17 +200,12 @@ static void *mdflush_reader(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_MDFLUSH_SLEEP_MS * em->update_every; - while (ebpf_mdflush_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - UNUSED(dt); - if (ebpf_mdflush_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); mdflush_read_count_map(); } - ebpf_mdflush_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -295,26 +308,25 @@ void *ebpf_mdflush_thread(void *ptr) char *md_flush_request = ebpf_find_symbol("md_flush_request"); if (!md_flush_request) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; error("Cannot monitor MD devices, because md is not loaded."); } freez(md_flush_request); - if (!em->enabled) { + if (em->thread->enabled == NETDATA_THREAD_EBPF_STOPPED) { goto endmdflush; } em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { - em->enabled = CONFIG_BOOLEAN_NO; + em->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endmdflush; } mdflush_collector(em); endmdflush: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); diff --git a/collectors/ebpf.plugin/ebpf_mdflush.h b/collectors/ebpf.plugin/ebpf_mdflush.h index 59856ad67..b04eefd28 100644 --- a/collectors/ebpf.plugin/ebpf_mdflush.h +++ b/collectors/ebpf.plugin/ebpf_mdflush.h @@ -35,7 +35,7 @@ typedef struct netdata_mdflush { uint64_t cnt; } netdata_mdflush_t; -extern void *ebpf_mdflush_thread(void *ptr); +void *ebpf_mdflush_thread(void *ptr); extern struct config mdflush_config; diff --git a/collectors/ebpf.plugin/ebpf_mount.c b/collectors/ebpf.plugin/ebpf_mount.c index bca467bce..ec1f07a65 100644 --- a/collectors/ebpf.plugin/ebpf_mount.c +++ b/collectors/ebpf.plugin/ebpf_mount.c @@ -22,14 +22,20 @@ static netdata_idx_t *mount_values = NULL; static netdata_idx_t mount_hash_values[NETDATA_MOUNT_END]; -struct netdata_static_thread mount_thread = {"MOUNT KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL}; +struct netdata_static_thread mount_thread = { + .name = "MOUNT KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; netdata_ebpf_targets_t mount_targets[] = { {.name = "mount", .mode = EBPF_LOAD_TRAMPOLINE}, {.name = "umount", .mode = EBPF_LOAD_TRAMPOLINE}, {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}}; -static enum ebpf_threads_status ebpf_mount_exited = NETDATA_THREAD_EBPF_RUNNING; #ifdef LIBBPF_MAJOR_VERSION #include "includes/mount.skel.h" // BTF code @@ -224,6 +230,36 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_ *****************************************************************/ /** + * Mount Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_mount_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + freez(mount_thread.thread); + freez(mount_values); + +#ifdef LIBBPF_MAJOR_VERSION + if (bpf_obj) + mount_bpf__destroy(bpf_obj); +#endif + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** * Mount Exit * * Cancel child thread. @@ -233,12 +269,8 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_ static void ebpf_mount_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_mount_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*mount_thread.thread); + ebpf_mount_free(em); } /** @@ -251,19 +283,7 @@ static void ebpf_mount_exit(void *ptr) static void ebpf_mount_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_mount_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - freez(mount_thread.thread); - freez(mount_values); - -#ifdef LIBBPF_MAJOR_VERSION - if (bpf_obj) - mount_bpf__destroy(bpf_obj); -#endif - - mount_thread.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_mount_free(em); } /***************************************************************** @@ -317,17 +337,12 @@ void *ebpf_mount_read_hash(void *ptr) usec_t step = NETDATA_LATENCY_MOUNT_SLEEP_MS * em->update_every; //This will be cancelled by its parent - while (ebpf_mount_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_mount_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_mount_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -435,7 +450,7 @@ static void ebpf_create_mount_charts(int update_every) static int ebpf_mount_load_bpf(ebpf_module_t *em) { int ret = 0; - if (em->load == EBPF_LOAD_LEGACY) { + if (em->load & EBPF_LOAD_LEGACY) { em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { em->enabled = CONFIG_BOOLEAN_NO; @@ -474,14 +489,11 @@ void *ebpf_mount_thread(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; em->maps = mount_maps; - if (!em->enabled) - goto endmount; - #ifdef LIBBPF_MAJOR_VERSION ebpf_adjust_thread_load(em, default_btf); #endif if (ebpf_mount_load_bpf(em)) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endmount; } @@ -498,8 +510,7 @@ void *ebpf_mount_thread(void *ptr) mount_collector(em); endmount: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_mount.h b/collectors/ebpf.plugin/ebpf_mount.h index d4f48efd1..5a8d11a59 100644 --- a/collectors/ebpf.plugin/ebpf_mount.h +++ b/collectors/ebpf.plugin/ebpf_mount.h @@ -38,7 +38,7 @@ enum netdata_mount_syscalls { }; extern struct config mount_config; -extern void *ebpf_mount_thread(void *ptr); +void *ebpf_mount_thread(void *ptr); extern netdata_ebpf_targets_t mount_targets[]; #endif /* NETDATA_EBPF_MOUNT_H */ diff --git a/collectors/ebpf.plugin/ebpf_oomkill.c b/collectors/ebpf.plugin/ebpf_oomkill.c index 33f505b0e..d93e4159e 100644 --- a/collectors/ebpf.plugin/ebpf_oomkill.c +++ b/collectors/ebpf.plugin/ebpf_oomkill.c @@ -46,8 +46,7 @@ static netdata_publish_syscall_t oomkill_publish_aggregated = {.name = "oomkill" static void oomkill_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - - em->enabled = NETDATA_MAIN_THREAD_EXITED; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; } static void oomkill_write_data(int32_t *keys, uint32_t total) @@ -132,25 +131,18 @@ static void ebpf_create_systemd_oomkill_charts(int update_every) * Send Systemd charts * * Send collected data to Netdata. - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_oomkill_charts() +static void ebpf_send_systemd_oomkill_charts() { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_OOMKILL_CHART); for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long) ect->oomkill); ect->oomkill = 0; - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); - - return ret; } /* @@ -199,12 +191,10 @@ void ebpf_oomkill_send_cgroup_data(int update_every) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_oomkill_charts(update_every); - systemd_charts = 1; } - systemd_charts = ebpf_send_systemd_oomkill_charts(); + ebpf_send_systemd_oomkill_charts(); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -367,27 +357,33 @@ void *ebpf_oomkill_thread(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; em->maps = oomkill_maps; +#define NETDATA_DEFAULT_OOM_DISABLED_MSG "Disabling OOMKILL thread, because" if (unlikely(!all_pids || !em->apps_charts)) { // When we are not running integration with apps, we won't fill necessary variables for this thread to run, so // we need to disable it. - if (em->enabled) - info("Disabling OOMKILL thread, because apps integration is completely disabled."); + if (em->thread->enabled) + info("%s apps integration is completely disabled.", NETDATA_DEFAULT_OOM_DISABLED_MSG); + + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + } else if (running_on_kernel < NETDATA_EBPF_KERNEL_4_14) { + if (em->thread->enabled) + info("%s kernel does not have necessary tracepoints.", NETDATA_DEFAULT_OOM_DISABLED_MSG); - em->enabled = 0; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; } - if (!em->enabled) { + if (em->thread->enabled == NETDATA_THREAD_EBPF_STOPPED) { goto endoomkill; } if (ebpf_enable_tracepoints(oomkill_tracepoints) == 0) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endoomkill; } em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endoomkill; } @@ -398,8 +394,7 @@ void *ebpf_oomkill_thread(void *ptr) oomkill_collector(em); endoomkill: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); diff --git a/collectors/ebpf.plugin/ebpf_oomkill.h b/collectors/ebpf.plugin/ebpf_oomkill.h index b5f04c74c..786086384 100644 --- a/collectors/ebpf.plugin/ebpf_oomkill.h +++ b/collectors/ebpf.plugin/ebpf_oomkill.h @@ -26,7 +26,7 @@ typedef uint8_t oomkill_ebpf_val_t; #define NETDATA_CGROUP_OOMKILLS_CONTEXT "cgroup.oomkills" extern struct config oomkill_config; -extern void *ebpf_oomkill_thread(void *ptr); -extern void ebpf_oomkill_create_apps_charts(struct ebpf_module *em, void *ptr); +void *ebpf_oomkill_thread(void *ptr); +void ebpf_oomkill_create_apps_charts(struct ebpf_module *em, void *ptr); #endif /* NETDATA_EBPF_OOMKILL_H */ diff --git a/collectors/ebpf.plugin/ebpf_process.c b/collectors/ebpf.plugin/ebpf_process.c index f6b379a51..682577da7 100644 --- a/collectors/ebpf.plugin/ebpf_process.c +++ b/collectors/ebpf.plugin/ebpf_process.c @@ -46,6 +46,7 @@ ebpf_process_stat_t **global_process_stats = NULL; ebpf_process_publish_apps_t **current_apps_data = NULL; int process_enabled = 0; +bool publish_internal_metrics = true; struct config process_config = { .first_section = NULL, .last_section = NULL, @@ -53,13 +54,20 @@ struct config process_config = { .first_section = NULL, .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare }, .rwlock = AVL_LOCK_INITIALIZER } }; -static struct netdata_static_thread cgroup_thread = {"EBPF CGROUP", NULL, NULL, - 1, NULL, NULL, NULL}; -static enum ebpf_threads_status ebpf_process_exited = NETDATA_THREAD_EBPF_RUNNING; - static char *threads_stat[NETDATA_EBPF_THREAD_STAT_END] = {"total", "running"}; static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"}; +static struct netdata_static_thread cgroup_thread = { + .name = "EBPF CGROUP", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; + /***************************************************************** * * PROCESS DATA AND SEND TO NETDATA @@ -319,6 +327,55 @@ static void ebpf_process_update_apps_data() } /** + * Cgroup Exit + * + * Function used with netdata_thread_clean_push + * + * @param ptr unused argument + */ +static void ebpf_cgroup_exit(void *ptr) +{ + UNUSED(ptr); +} + +/** + * Cgroup update shm + * + * This is the thread callback. + * This thread is necessary, because we cannot freeze the whole plugin to read the data from shared memory. + * + * @param ptr It is a NULL value for this thread. + * + * @return It always returns NULL. + */ +void *ebpf_cgroup_update_shm(void *ptr) +{ + netdata_thread_cleanup_push(ebpf_cgroup_exit, ptr); + heartbeat_t hb; + heartbeat_init(&hb); + + usec_t step = 3 * USEC_PER_SEC; + int counter = NETDATA_EBPF_CGROUP_UPDATE - 1; + //This will be cancelled by its parent + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); + + // We are using a small heartbeat time to wake up thread, + // but we should not update so frequently the shared memory data + if (++counter >= NETDATA_EBPF_CGROUP_UPDATE) { + counter = 0; + if (!shm_ebpf_cgroup.header) + ebpf_map_cgroup_shared_memory(); + + ebpf_parse_cgroup_shm_data(); + } + } + + netdata_thread_cleanup_pop(1); + return NULL; +} + +/** * Update cgroup * * Update cgroup data based in @@ -493,6 +550,21 @@ static inline void ebpf_create_statistic_load_chart(ebpf_module_t *em) } /** + * Update Internal Metric variable + * + * By default eBPF.plugin sends internal metrics for netdata, but user can + * disable this. + * + * The function updates the variable used to send charts. + */ +static void update_internal_metric_variable() +{ + const char *s = getenv("NETDATA_INTERNALS_MONITORING"); + if (s && *s && strcmp(s, "NO") == 0) + publish_internal_metrics = false; +} + +/** * Create Statistics Charts * * Create charts that will show statistics related to eBPF plugin. @@ -501,6 +573,10 @@ static inline void ebpf_create_statistic_load_chart(ebpf_module_t *em) */ static void ebpf_create_statistic_charts(ebpf_module_t *em) { + update_internal_metric_variable(); + if (!publish_internal_metrics) + return; + ebpf_create_statistic_thread_chart(em); ebpf_create_statistic_load_chart(em); @@ -659,31 +735,17 @@ static void ebpf_process_disable_tracepoints() */ static void ebpf_process_exit(void *ptr) { - (void)ptr; - ebpf_process_exited = NETDATA_THREAD_EBPF_STOPPING; -} - -/** - * Process cleanup - * - * Cleanup allocated memory. - * - * @param ptr thread data. - */ -static void ebpf_process_cleanup(void *ptr) -{ ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_process_exited != NETDATA_THREAD_EBPF_STOPPED) - return; ebpf_cleanup_publish_syscall(process_publish_aggregated); freez(process_hash_values); - freez(cgroup_thread.thread); ebpf_process_disable_tracepoints(); - cgroup_thread.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); + pthread_cancel(*cgroup_thread.thread); } /***************************************************************** @@ -692,47 +754,6 @@ static void ebpf_process_cleanup(void *ptr) * *****************************************************************/ -/** - * Cgroup update shm - * - * This is the thread callback. - * This thread is necessary, because we cannot freeze the whole plugin to read the data from shared memory. - * - * @param ptr It is a NULL value for this thread. - * - * @return It always returns NULL. - */ -void *ebpf_cgroup_update_shm(void *ptr) -{ - netdata_thread_cleanup_push(ebpf_process_cleanup, ptr); - heartbeat_t hb; - heartbeat_init(&hb); - - usec_t step = 3 * USEC_PER_SEC; - int counter = NETDATA_EBPF_CGROUP_UPDATE - 1; - //This will be cancelled by its parent - while (ebpf_process_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_process_exited == NETDATA_THREAD_EBPF_STOPPING) - break; - - // We are using a small heartbeat time to wake up thread, - // but we should not update so frequently the shared memory data - if (++counter >= NETDATA_EBPF_CGROUP_UPDATE) { - counter = 0; - if (!shm_ebpf_cgroup.header) - ebpf_map_cgroup_shared_memory(); - - ebpf_parse_cgroup_shm_data(); - } - } - - ebpf_process_exited = NETDATA_THREAD_EBPF_STOPPED; - - netdata_thread_cleanup_pop(1); - return NULL; -} /** * Sum PIDs @@ -945,20 +966,15 @@ static void ebpf_create_systemd_process_charts(ebpf_module_t *em) * Send collected data to Netdata. * * @param em the structure with thread information - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_process_charts(ebpf_module_t *em) +static void ebpf_send_systemd_process_charts(ebpf_module_t *em) { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_PROCESS); for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, ect->publish_systemd_ps.create_process); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -995,8 +1011,6 @@ static int ebpf_send_systemd_process_charts(ebpf_module_t *em) } write_end_chart(); } - - return ret; } /** @@ -1018,13 +1032,11 @@ static void ebpf_process_send_cgroup_data(ebpf_module_t *em) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_chart = 0; - if (!systemd_chart) { + if (send_cgroup_chart) { ebpf_create_systemd_process_charts(em); - systemd_chart = 1; } - systemd_chart = ebpf_send_systemd_process_charts(em); + ebpf_send_systemd_process_charts(em); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -1071,6 +1083,9 @@ void ebpf_process_update_cgroup_algorithm() */ void ebpf_send_statistic_data() { + if (!publish_internal_metrics) + return; + write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_THREADS); write_chart_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_TOTAL], (long long)plugin_statistics.threads); write_chart_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_RUNNING], (long long)plugin_statistics.running); @@ -1089,11 +1104,12 @@ void ebpf_send_statistic_data() */ static void process_collector(ebpf_module_t *em) { + // Start cgroup integration before other threads cgroup_thread.thread = mallocz(sizeof(netdata_thread_t)); cgroup_thread.start_routine = ebpf_cgroup_update_shm; netdata_thread_create(cgroup_thread.thread, cgroup_thread.name, NETDATA_THREAD_OPTION_DEFAULT, - ebpf_cgroup_update_shm, em); + ebpf_cgroup_update_shm, NULL); heartbeat_t hb; heartbeat_init(&hb); @@ -1119,8 +1135,6 @@ static void process_collector(ebpf_module_t *em) update_apps_list = 0; cleanup_exited_pids(); collect_data_for_all_processes(pid_fd); - - ebpf_create_apps_charts(apps_groups_root_target); } pthread_mutex_unlock(&collect_data_mutex); @@ -1131,6 +1145,8 @@ static void process_collector(ebpf_module_t *em) netdata_apps_integration_flags_t apps_enabled = em->apps_charts; pthread_mutex_lock(&collect_data_mutex); + + ebpf_create_apps_charts(apps_groups_root_target); if (all_pids_count > 0) { if (apps_enabled) { ebpf_process_update_apps_data(); @@ -1211,34 +1227,6 @@ static void set_local_pointers() *****************************************************************/ /** - * - */ -static void wait_for_all_threads_die() -{ - ebpf_modules[EBPF_MODULE_PROCESS_IDX].enabled = 0; - - heartbeat_t hb; - heartbeat_init(&hb); - - int max = 10; - int i; - for (i = 0; i < max; i++) { - heartbeat_next(&hb, 200000); - - size_t j, counter = 0, compare = 0; - for (j = 0; ebpf_modules[j].thread_name; j++) { - if (!ebpf_modules[j].enabled) - counter++; - - compare++; - } - - if (counter == compare) - break; - } -} - -/** * Enable tracepoints * * Enable necessary tracepoints for thread. @@ -1334,7 +1322,6 @@ endprocess: if (!em->enabled) ebpf_update_disabled_plugin_stats(em); - wait_for_all_threads_die(); netdata_thread_cleanup_pop(1); return NULL; } diff --git a/collectors/ebpf.plugin/ebpf_shm.c b/collectors/ebpf.plugin/ebpf_shm.c index bd928cbdc..f81287d82 100644 --- a/collectors/ebpf.plugin/ebpf_shm.c +++ b/collectors/ebpf.plugin/ebpf_shm.c @@ -34,9 +34,16 @@ static ebpf_local_maps_t shm_maps[] = {{.name = "tbl_pid_shm", .internal_input = .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}, {.name = NULL, .internal_input = 0, .user_input = 0}}; -struct netdata_static_thread shm_threads = {"SHM KERNEL", NULL, NULL, 1, - NULL, NULL, NULL}; -static enum ebpf_threads_status ebpf_shm_exited = NETDATA_THREAD_EBPF_RUNNING; +struct netdata_static_thread shm_threads = { + .name = "SHM KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; netdata_ebpf_targets_t shm_targets[] = { {.name = "shmget", .mode = EBPF_LOAD_TRAMPOLINE}, {.name = "shmat", .mode = EBPF_LOAD_TRAMPOLINE}, @@ -83,6 +90,7 @@ static void ebpf_disable_probe(struct shm_bpf *obj) bpf_program__set_autoload(obj->progs.netdata_shmat_probe, false); bpf_program__set_autoload(obj->progs.netdata_shmdt_probe, false); bpf_program__set_autoload(obj->progs.netdata_shmctl_probe, false); + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false); } /* @@ -98,6 +106,7 @@ static void ebpf_disable_trampoline(struct shm_bpf *obj) bpf_program__set_autoload(obj->progs.netdata_shmat_fentry, false); bpf_program__set_autoload(obj->progs.netdata_shmdt_fentry, false); bpf_program__set_autoload(obj->progs.netdata_shmctl_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false); } /** @@ -130,6 +139,9 @@ static void ebpf_set_trampoline_target(struct shm_bpf *obj) shm_targets[NETDATA_KEY_SHMCTL_CALL].name, running_on_kernel); bpf_program__set_attach_target(obj->progs.netdata_shmctl_fentry, 0, syscall); + + bpf_program__set_attach_target(obj->progs.netdata_shm_release_task_fentry, 0, + EBPF_COMMON_FNCT_CLEAN_UP); } /** @@ -177,6 +189,13 @@ static int ebpf_shm_attach_probe(struct shm_bpf *obj) if (ret) return -1; + obj->links.netdata_shm_release_task_probe = bpf_program__attach_kprobe(obj->progs.netdata_shm_release_task_probe, + false, EBPF_COMMON_FNCT_CLEAN_UP); + ret = (int)libbpf_get_error(obj->links.netdata_shm_release_task_probe); + if (ret) + return -1; + + return 0; } @@ -193,6 +212,33 @@ static void ebpf_shm_set_hash_tables(struct shm_bpf *obj) } /** + * Disable Release Task + * + * Disable release task when apps is not enabled. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_shm_disable_release_task(struct shm_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false); + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false); +} + +/** + * Adjust Map Size + * + * Resize maps according input from users. + * + * @param obj is the main structure for bpf objects. + * @param em structure with configuration + */ +static void ebpf_shm_adjust_map_size(struct shm_bpf *obj, ebpf_module_t *em) +{ + ebpf_update_map_size(obj->maps.tbl_pid_shm, &shm_maps[NETDATA_PID_SHM_TABLE], + em, bpf_map__name(obj->maps.tbl_pid_shm)); +} + +/** * Load and attach * * Load and attach the eBPF code in kernel. @@ -221,6 +267,10 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e ebpf_disable_trampoline(obj); } + ebpf_shm_adjust_map_size(obj, em); + if (!em->apps_charts && !em->cgroup_charts) + ebpf_shm_disable_release_task(obj); + int ret = shm_bpf__load(obj); if (!ret) { if (test != EBPF_LOAD_PROBE && test != EBPF_LOAD_RETPROBE) @@ -240,6 +290,36 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e *****************************************************************/ /** + * SHM Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_shm_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + ebpf_cleanup_publish_syscall(shm_publish_aggregated); + + freez(shm_vector); + freez(shm_values); + +#ifdef LIBBPF_MAJOR_VERSION + if (bpf_obj) + shm_bpf__destroy(bpf_obj); +#endif + + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; +} + +/** * SHM Exit * * Cancel child thread. @@ -249,12 +329,8 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e static void ebpf_shm_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_shm_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*shm_threads.thread); + ebpf_shm_free(em); } /** @@ -267,21 +343,7 @@ static void ebpf_shm_exit(void *ptr) static void ebpf_shm_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_shm_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - ebpf_cleanup_publish_syscall(shm_publish_aggregated); - - freez(shm_vector); - freez(shm_values); - -#ifdef LIBBPF_MAJOR_VERSION - if (bpf_obj) - shm_bpf__destroy(bpf_obj); -#endif - - shm_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_shm_free(em); } /***************************************************************** @@ -463,17 +525,12 @@ void *ebpf_shm_read_hash(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_SHM_SLEEP_MS * em->update_every; - while (ebpf_shm_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_shm_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_shm_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -721,20 +778,15 @@ static void ebpf_create_systemd_shm_charts(int update_every) * Send Systemd charts * * Send collected data to Netdata. - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_shm_charts() +static void ebpf_send_systemd_shm_charts() { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMGET_CHART); for (ect = ebpf_cgroup_pids; ect; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long)ect->publish_shm.get); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -761,8 +813,6 @@ static int ebpf_send_systemd_shm_charts() } } write_end_chart(); - - return ret; } /* @@ -810,13 +860,11 @@ void ebpf_shm_send_cgroup_data(int update_every) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_shm_charts(update_every); - systemd_charts = 1; } - systemd_charts = ebpf_send_systemd_shm_charts(); + ebpf_send_systemd_shm_charts(); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -1008,7 +1056,9 @@ static void ebpf_create_shm_charts(int update_every) static int ebpf_shm_load_bpf(ebpf_module_t *em) { int ret = 0; - if (em->load == EBPF_LOAD_LEGACY) { + + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SHMGET_CALL].mode); + if (em->load & EBPF_LOAD_LEGACY) { em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { em->enabled = CONFIG_BOOLEAN_NO; @@ -1047,15 +1097,11 @@ void *ebpf_shm_thread(void *ptr) ebpf_update_pid_table(&shm_maps[NETDATA_PID_SHM_TABLE], em); - if (!em->enabled) { - goto endshm; - } - #ifdef LIBBPF_MAJOR_VERSION ebpf_adjust_thread_load(em, default_btf); #endif if (ebpf_shm_load_bpf(em)) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endshm; } @@ -1084,8 +1130,7 @@ void *ebpf_shm_thread(void *ptr) shm_collector(em); endshm: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_shm.h b/collectors/ebpf.plugin/ebpf_shm.h index 8e118a6f5..4e068819b 100644 --- a/collectors/ebpf.plugin/ebpf_shm.h +++ b/collectors/ebpf.plugin/ebpf_shm.h @@ -54,8 +54,8 @@ enum shm_counters { extern netdata_publish_shm_t **shm_pid; -extern void *ebpf_shm_thread(void *ptr); -extern void ebpf_shm_create_apps_charts(struct ebpf_module *em, void *ptr); +void *ebpf_shm_thread(void *ptr); +void ebpf_shm_create_apps_charts(struct ebpf_module *em, void *ptr); extern netdata_ebpf_targets_t shm_targets[]; extern struct config shm_config; diff --git a/collectors/ebpf.plugin/ebpf_socket.c b/collectors/ebpf.plugin/ebpf_socket.c index ba63934d5..3a023e4a4 100644 --- a/collectors/ebpf.plugin/ebpf_socket.c +++ b/collectors/ebpf.plugin/ebpf_socket.c @@ -23,7 +23,7 @@ static char *socket_id_names[NETDATA_MAX_SOCKET_VECTOR] = { "tcp_cleanup_rbuf", static ebpf_local_maps_t socket_maps[] = {{.name = "tbl_bandwidth", .internal_input = NETDATA_COMPILED_CONNECTIONS_ALLOWED, .user_input = NETDATA_MAXIMUM_CONNECTIONS_ALLOWED, - .type = NETDATA_EBPF_MAP_STATIC, + .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID, .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}, {.name = "tbl_global_sock", .internal_input = NETDATA_SOCKET_COUNTER, @@ -87,10 +87,16 @@ netdata_ebpf_targets_t socket_targets[] = { {.name = "inet_csk_accept", .mode = {.name = "tcp_v6_connect", .mode = EBPF_LOAD_TRAMPOLINE}, {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}}; -struct netdata_static_thread socket_threads = {"EBPF SOCKET READ", - NULL, NULL, 1, NULL, - NULL, NULL }; -static enum ebpf_threads_status ebpf_socket_exited = NETDATA_THREAD_EBPF_RUNNING; +struct netdata_static_thread socket_threads = { + .name = "EBPF SOCKET READ", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; #ifdef LIBBPF_MAJOR_VERSION #include "includes/socket.skel.h" // BTF code @@ -581,35 +587,21 @@ static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean) } /** - * Socket exit + * Socket Free * - * Clean up the main thread. + * Cleanup variables after child threads to stop * * @param ptr thread data. */ -static void ebpf_socket_exit(void *ptr) +static void ebpf_socket_free(ebpf_module_t *em ) { - ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); return; } - - ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPING; -} - -/** - * Socket cleanup - * - * Clean up allocated addresses. - * - * @param ptr thread data. - */ -void ebpf_socket_cleanup(void *ptr) -{ - ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_socket_exited != NETDATA_THREAD_EBPF_STOPPED) - return; + pthread_mutex_unlock(&ebpf_exit_cleanup); ebpf_cleanup_publish_syscall(socket_publish_aggregated); freez(socket_hash_values); @@ -639,8 +631,37 @@ void ebpf_socket_cleanup(void *ptr) if (bpf_obj) socket_bpf__destroy(bpf_obj); #endif - socket_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** + * Socket exit + * + * Clean up the main thread. + * + * @param ptr thread data. + */ +static void ebpf_socket_exit(void *ptr) +{ + ebpf_module_t *em = (ebpf_module_t *)ptr; + netdata_thread_cancel(*socket_threads.thread); + ebpf_socket_free(em); +} + +/** + * Socket cleanup + * + * Clean up allocated addresses. + * + * @param ptr thread data. + */ +void ebpf_socket_cleanup(void *ptr) +{ + ebpf_module_t *em = (ebpf_module_t *)ptr; + ebpf_socket_free(em); } /***************************************************************** @@ -2146,11 +2167,8 @@ void *ebpf_socket_read_hash(void *ptr) int fd_ipv4 = socket_maps[NETDATA_SOCKET_TABLE_IPV4].map_fd; int fd_ipv6 = socket_maps[NETDATA_SOCKET_TABLE_IPV6].map_fd; int network_connection = em->optional; - while (ebpf_socket_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_socket_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); pthread_mutex_lock(&nv_mutex); read_listen_table(); @@ -2160,8 +2178,6 @@ void *ebpf_socket_read_hash(void *ptr) pthread_mutex_unlock(&nv_mutex); } - ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -2702,20 +2718,15 @@ static void ebpf_create_systemd_socket_charts(int update_every) * Send Systemd charts * * Send collected data to Netdata. - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_socket_charts() +static void ebpf_send_systemd_socket_charts() { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_CONNECTION_TCP_V4); for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long)ect->publish_socket.call_tcp_v4_connection); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -2723,8 +2734,7 @@ static int ebpf_send_systemd_socket_charts() for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long)ect->publish_socket.call_tcp_v6_connection); - } else - ret = 0; + } } write_end_chart(); @@ -2732,8 +2742,7 @@ static int ebpf_send_systemd_socket_charts() for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long)ect->publish_socket.bytes_sent); - } else - ret = 0; + } } write_end_chart(); @@ -2784,8 +2793,6 @@ static int ebpf_send_systemd_socket_charts() } } write_end_chart(); - - return ret; } /** @@ -2821,12 +2828,10 @@ static void ebpf_socket_send_cgroup_data(int update_every) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_socket_charts(update_every); - systemd_charts = 1; } - systemd_charts = ebpf_send_systemd_socket_charts(); + ebpf_send_systemd_socket_charts(); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -3875,7 +3880,7 @@ static int ebpf_socket_load_bpf(ebpf_module_t *em) { int ret = 0; - if (em->load == EBPF_LOAD_LEGACY) { + if (em->load & EBPF_LOAD_LEGACY) { em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { ret = -1; @@ -3923,11 +3928,8 @@ void *ebpf_socket_thread(void *ptr) parse_service_name_section(&socket_config); parse_table_size_options(&socket_config); - if (!em->enabled) - goto endsocket; - if (pthread_mutex_init(&nv_mutex, NULL)) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; error("Cannot initialize local mutex"); goto endsocket; } @@ -3967,8 +3969,7 @@ void *ebpf_socket_thread(void *ptr) socket_collector((usec_t)(em->update_every * USEC_PER_SEC), em); endsocket: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_socket.h b/collectors/ebpf.plugin/ebpf_socket.h index 711225acf..ca6b193f0 100644 --- a/collectors/ebpf.plugin/ebpf_socket.h +++ b/collectors/ebpf.plugin/ebpf_socket.h @@ -356,12 +356,12 @@ typedef struct netdata_vector_plot { } netdata_vector_plot_t; -extern void clean_port_structure(ebpf_network_viewer_port_list_t **clean); +void clean_port_structure(ebpf_network_viewer_port_list_t **clean); extern ebpf_network_viewer_port_list_t *listen_ports; -extern void update_listen_table(uint16_t value, uint16_t proto, netdata_passive_connection_t *values); -extern void parse_network_viewer_section(struct config *cfg); -extern void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table); -extern void parse_service_name_section(struct config *cfg); +void update_listen_table(uint16_t value, uint16_t proto, netdata_passive_connection_t *values); +void parse_network_viewer_section(struct config *cfg); +void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table); +void parse_service_name_section(struct config *cfg); extern ebpf_socket_publish_apps_t **socket_bandwidth_curr; extern struct config socket_config; diff --git a/collectors/ebpf.plugin/ebpf_softirq.c b/collectors/ebpf.plugin/ebpf_softirq.c index ed13f027f..3b5d15921 100644 --- a/collectors/ebpf.plugin/ebpf_softirq.c +++ b/collectors/ebpf.plugin/ebpf_softirq.c @@ -54,10 +54,45 @@ static softirq_val_t softirq_vals[] = { // tmp store for soft IRQ values we get from a per-CPU eBPF map. static softirq_ebpf_val_t *softirq_ebpf_vals = NULL; -static struct netdata_static_thread softirq_threads = {"SOFTIRQ KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL }; -static enum ebpf_threads_status ebpf_softirq_exited = NETDATA_THREAD_EBPF_RUNNING; +static struct netdata_static_thread softirq_threads = { + .name = "SOFTIRQ KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; + +/** + * Cachestat Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_softirq_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + freez(softirq_threads.thread); + + for (int i = 0; softirq_tracepoints[i].class != NULL; i++) { + ebpf_disable_tracepoint(&softirq_tracepoints[i]); + } + freez(softirq_ebpf_vals); + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_MAIN_THREAD_EXITED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} /** * Exit @@ -69,12 +104,8 @@ static enum ebpf_threads_status ebpf_softirq_exited = NETDATA_THREAD_EBPF_RUNNIN static void softirq_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_softirq_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*softirq_threads.thread); + ebpf_softirq_free(em); } /** @@ -87,18 +118,7 @@ static void softirq_exit(void *ptr) static void softirq_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_softirq_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - freez(softirq_threads.thread); - - for (int i = 0; softirq_tracepoints[i].class != NULL; i++) { - ebpf_disable_tracepoint(&softirq_tracepoints[i]); - } - freez(softirq_ebpf_vals); - - softirq_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_softirq_free(em); } /***************************************************************** @@ -138,15 +158,11 @@ static void *softirq_reader(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_SOFTIRQ_SLEEP_MS * em->update_every; - while (ebpf_softirq_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - UNUSED(dt); - if (ebpf_softirq_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); softirq_read_latency_map(); } - ebpf_softirq_exited = NETDATA_THREAD_EBPF_STOPPED; netdata_thread_cleanup_pop(1); return NULL; @@ -252,26 +268,21 @@ void *ebpf_softirq_thread(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; em->maps = softirq_maps; - if (!em->enabled) { - goto endsoftirq; - } - if (ebpf_enable_tracepoints(softirq_tracepoints) == 0) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endsoftirq; } em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endsoftirq; } softirq_collector(em); endsoftirq: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); diff --git a/collectors/ebpf.plugin/ebpf_softirq.h b/collectors/ebpf.plugin/ebpf_softirq.h index a22751895..7dcddbb49 100644 --- a/collectors/ebpf.plugin/ebpf_softirq.h +++ b/collectors/ebpf.plugin/ebpf_softirq.h @@ -29,6 +29,6 @@ typedef struct sofirq_val { } softirq_val_t; extern struct config softirq_config; -extern void *ebpf_softirq_thread(void *ptr); +void *ebpf_softirq_thread(void *ptr); #endif /* NETDATA_EBPF_SOFTIRQ_H */ diff --git a/collectors/ebpf.plugin/ebpf_swap.c b/collectors/ebpf.plugin/ebpf_swap.c index 71d0c402b..8199573a9 100644 --- a/collectors/ebpf.plugin/ebpf_swap.c +++ b/collectors/ebpf.plugin/ebpf_swap.c @@ -34,9 +34,16 @@ static ebpf_local_maps_t swap_maps[] = {{.name = "tbl_pid_swap", .internal_input .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}, {.name = NULL, .internal_input = 0, .user_input = 0}}; -struct netdata_static_thread swap_threads = {"SWAP KERNEL", NULL, NULL, 1, - NULL, NULL, NULL}; -static enum ebpf_threads_status ebpf_swap_exited = NETDATA_THREAD_EBPF_RUNNING; +struct netdata_static_thread swap_threads = { + .name = "SWAP KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE}, {.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE}, @@ -71,6 +78,7 @@ static void ebpf_swap_disable_trampoline(struct swap_bpf *obj) { bpf_program__set_autoload(obj->progs.netdata_swap_readpage_fentry, false); bpf_program__set_autoload(obj->progs.netdata_swap_writepage_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false); } /** @@ -87,6 +95,9 @@ static void ebpf_swap_set_trampoline_target(struct swap_bpf *obj) bpf_program__set_attach_target(obj->progs.netdata_swap_writepage_fentry, 0, swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name); + + bpf_program__set_attach_target(obj->progs.netdata_release_task_fentry, 0, + EBPF_COMMON_FNCT_CLEAN_UP); } /** @@ -114,6 +125,13 @@ static int ebpf_swap_attach_kprobe(struct swap_bpf *obj) if (ret) return -1; + obj->links.netdata_release_task_probe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_probe, + false, + EBPF_COMMON_FNCT_CLEAN_UP); + ret = libbpf_get_error(obj->links.netdata_swap_writepage_probe); + if (ret) + return -1; + return 0; } @@ -146,6 +164,19 @@ static void ebpf_swap_adjust_map_size(struct swap_bpf *obj, ebpf_module_t *em) } /** + * Disable Release Task + * + * Disable release task when apps is not enabled. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_swap_disable_release_task(struct swap_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_release_task_probe, false); +} + +/** * Load and attach * * Load and attach the eBPF code in kernel. @@ -168,13 +199,16 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t ebpf_swap_disable_trampoline(obj); } + ebpf_swap_adjust_map_size(obj, em); + + if (!em->apps_charts && !em->cgroup_charts) + ebpf_swap_disable_release_task(obj); + int ret = swap_bpf__load(obj); if (ret) { return ret; } - ebpf_swap_adjust_map_size(obj, em); - ret = (test == EBPF_LOAD_TRAMPOLINE) ? swap_bpf__attach(obj) : ebpf_swap_attach_kprobe(obj); if (!ret) { ebpf_swap_set_hash_tables(obj); @@ -193,6 +227,38 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t *****************************************************************/ /** + * Cachestat Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_swap_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + ebpf_cleanup_publish_syscall(swap_publish_aggregated); + + freez(swap_vector); + freez(swap_values); + freez(swap_threads.thread); + +#ifdef LIBBPF_MAJOR_VERSION + if (bpf_obj) + swap_bpf__destroy(bpf_obj); +#endif + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + +/** * Swap exit * * Cancel thread and exit. @@ -202,12 +268,8 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t static void ebpf_swap_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_swap_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*swap_threads.thread); + ebpf_swap_free(em); } /** @@ -220,21 +282,7 @@ static void ebpf_swap_exit(void *ptr) static void ebpf_swap_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_swap_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - ebpf_cleanup_publish_syscall(swap_publish_aggregated); - - freez(swap_vector); - freez(swap_values); - freez(swap_threads.thread); - -#ifdef LIBBPF_MAJOR_VERSION - if (bpf_obj) - swap_bpf__destroy(bpf_obj); -#endif - swap_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_swap_free(em); } /***************************************************************** @@ -401,17 +449,12 @@ void *ebpf_swap_read_hash(void *ptr) ebpf_module_t *em = (ebpf_module_t *)ptr; usec_t step = NETDATA_SWAP_SLEEP_MS * em->update_every; - while (ebpf_swap_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_swap_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_swap_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -505,20 +548,15 @@ static void ebpf_swap_sum_cgroup_pids(netdata_publish_swap_t *swap, struct pid_o * Send Systemd charts * * Send collected data to Netdata. - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_swap_charts() +static void ebpf_send_systemd_swap_charts() { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_MEM_SWAP_READ_CHART); for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, (long long) ect->publish_systemd_swap.read); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -529,8 +567,6 @@ static int ebpf_send_systemd_swap_charts() } } write_end_chart(); - - return ret; } /** @@ -644,14 +680,11 @@ void ebpf_swap_send_cgroup_data(int update_every) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_swap_charts(update_every); - systemd_charts = 1; fflush(stdout); } - - systemd_charts = ebpf_send_systemd_swap_charts(); + ebpf_send_systemd_swap_charts(); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -812,7 +845,8 @@ static void ebpf_create_swap_charts(int update_every) static int ebpf_swap_load_bpf(ebpf_module_t *em) { int ret = 0; - if (em->load == EBPF_LOAD_LEGACY) { + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SWAP_READPAGE_CALL].mode); + if (em->load & EBPF_LOAD_LEGACY) { em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); if (!em->probe_links) { ret = -1; @@ -852,14 +886,11 @@ void *ebpf_swap_thread(void *ptr) ebpf_update_pid_table(&swap_maps[NETDATA_PID_SWAP_TABLE], em); - if (!em->enabled) - goto endswap; - #ifdef LIBBPF_MAJOR_VERSION ebpf_adjust_thread_load(em, default_btf); #endif if (ebpf_swap_load_bpf(em)) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endswap; } @@ -877,8 +908,7 @@ void *ebpf_swap_thread(void *ptr) swap_collector(em); endswap: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_swap.h b/collectors/ebpf.plugin/ebpf_swap.h index 80c2c8e94..79182e52e 100644 --- a/collectors/ebpf.plugin/ebpf_swap.h +++ b/collectors/ebpf.plugin/ebpf_swap.h @@ -44,8 +44,8 @@ enum swap_counters { extern netdata_publish_swap_t **swap_pid; -extern void *ebpf_swap_thread(void *ptr); -extern void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr); +void *ebpf_swap_thread(void *ptr); +void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr); extern struct config swap_config; extern netdata_ebpf_targets_t swap_targets[]; diff --git a/collectors/ebpf.plugin/ebpf_sync.c b/collectors/ebpf.plugin/ebpf_sync.c index 0e56f541d..840497533 100644 --- a/collectors/ebpf.plugin/ebpf_sync.c +++ b/collectors/ebpf.plugin/ebpf_sync.c @@ -10,8 +10,16 @@ static netdata_publish_syscall_t sync_counter_publish_aggregated[NETDATA_SYNC_ID static netdata_idx_t sync_hash_values[NETDATA_SYNC_IDX_END]; -struct netdata_static_thread sync_threads = {"SYNC KERNEL", NULL, NULL, 1, - NULL, NULL, NULL}; +struct netdata_static_thread sync_threads = { + .name = "SYNC KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; static ebpf_local_maps_t sync_maps[] = {{.name = "tbl_sync", .internal_input = NETDATA_SYNC_END, .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC, @@ -48,8 +56,6 @@ netdata_ebpf_targets_t sync_targets[] = { {.name = NETDATA_SYSCALLS_SYNC, .mode {.name = NETDATA_SYSCALLS_FDATASYNC, .mode = EBPF_LOAD_TRAMPOLINE}, {.name = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .mode = EBPF_LOAD_TRAMPOLINE}, {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}}; -static enum ebpf_threads_status ebpf_sync_exited = NETDATA_THREAD_EBPF_RUNNING; - #ifdef LIBBPF_MAJOR_VERSION /***************************************************************** @@ -183,6 +189,7 @@ static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t * *****************************************************************/ +#ifdef LIBBPF_MAJOR_VERSION /** * Cleanup Objects * @@ -193,22 +200,37 @@ void ebpf_sync_cleanup_objects() int i; for (i = 0; local_syscalls[i].syscall; i++) { ebpf_sync_syscalls_t *w = &local_syscalls[i]; - if (w->probe_links) { - struct bpf_program *prog; - size_t j = 0 ; - bpf_object__for_each_program(prog, w->objects) { - bpf_link__destroy(w->probe_links[j]); - j++; - } - freez(w->probe_links); - if (w->objects) - bpf_object__close(w->objects); - } -#ifdef LIBBPF_MAJOR_VERSION - else if (w->sync_obj) + if (w->sync_obj) sync_bpf__destroy(w->sync_obj); + } +} #endif + +/** + * Sync Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_sync_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; } + pthread_mutex_unlock(&ebpf_exit_cleanup); + +#ifdef LIBBPF_MAJOR_VERSION + ebpf_sync_cleanup_objects(); +#endif + freez(sync_threads.thread); + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); } /** @@ -221,12 +243,8 @@ void ebpf_sync_cleanup_objects() static void ebpf_sync_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_sync_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*sync_threads.thread); + ebpf_sync_free(em); } /** @@ -237,14 +255,7 @@ static void ebpf_sync_exit(void *ptr) static void ebpf_sync_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_sync_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - ebpf_sync_cleanup_objects(); - freez(sync_threads.thread); - - sync_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_sync_free(em); } /***************************************************************** @@ -291,7 +302,7 @@ static int ebpf_sync_initialize_syscall(ebpf_module_t *em) for (i = 0; local_syscalls[i].syscall; i++) { ebpf_sync_syscalls_t *w = &local_syscalls[i]; if (w->enabled) { - if (em->load == EBPF_LOAD_LEGACY) { + if (em->load & EBPF_LOAD_LEGACY) { if (ebpf_sync_load_legacy(w, em)) errors++; @@ -372,17 +383,12 @@ void *ebpf_sync_read_hash(void *ptr) heartbeat_init(&hb); usec_t step = NETDATA_EBPF_SYNC_SLEEP_MS * em->update_every; - while (ebpf_sync_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_sync_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_sync_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -572,14 +578,11 @@ void *ebpf_sync_thread(void *ptr) ebpf_sync_parse_syscalls(); - if (!em->enabled) - goto endsync; - #ifdef LIBBPF_MAJOR_VERSION ebpf_adjust_thread_load(em, default_btf); #endif if (ebpf_sync_initialize_syscall(em)) { - em->enabled = CONFIG_BOOLEAN_NO; + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endsync; } @@ -598,8 +601,7 @@ void *ebpf_sync_thread(void *ptr) sync_collector(em); endsync: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_sync.h b/collectors/ebpf.plugin/ebpf_sync.h index a52434c17..cace2a1cf 100644 --- a/collectors/ebpf.plugin/ebpf_sync.h +++ b/collectors/ebpf.plugin/ebpf_sync.h @@ -52,7 +52,7 @@ enum netdata_sync_table { NETDATA_SYNC_GLOBAL_TABLE }; -extern void *ebpf_sync_thread(void *ptr); +void *ebpf_sync_thread(void *ptr); extern struct config sync_config; extern netdata_ebpf_targets_t sync_targets[]; diff --git a/collectors/ebpf.plugin/ebpf_vfs.c b/collectors/ebpf.plugin/ebpf_vfs.c index 6746cc624..ad6de4a07 100644 --- a/collectors/ebpf.plugin/ebpf_vfs.c +++ b/collectors/ebpf.plugin/ebpf_vfs.c @@ -34,16 +34,402 @@ struct config vfs_config = { .first_section = NULL, .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare }, .rwlock = AVL_LOCK_INITIALIZER } }; -struct netdata_static_thread vfs_threads = {"VFS KERNEL", - NULL, NULL, 1, NULL, - NULL, NULL}; -static enum ebpf_threads_status ebpf_vfs_exited = NETDATA_THREAD_EBPF_RUNNING; +struct netdata_static_thread vfs_threads = { + .name = "VFS KERNEL", + .config_section = NULL, + .config_name = NULL, + .env_name = NULL, + .enabled = 1, + .thread = NULL, + .init_routine = NULL, + .start_routine = NULL +}; + +netdata_ebpf_targets_t vfs_targets[] = { {.name = "vfs_write", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "vfs_writev", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "vfs_read", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "vfs_readv", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "vfs_unlink", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "vfs_fsync", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "vfs_open", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "vfs_create", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "release_task", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}}; + +#ifdef LIBBPF_MAJOR_VERSION +#include "includes/vfs.skel.h" // BTF code + +static struct vfs_bpf *bpf_obj = NULL; + +/** + * Disable probe + * + * Disable all probes to use exclusively another method. + * + * @param obj is the main structure for bpf objects + */ +static void ebpf_vfs_disable_probes(struct vfs_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_vfs_write_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_write_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_read_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_read_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_open_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_open_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_create_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_create_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_kprobe, false); +} + +/* + * Disable trampoline + * + * Disable all trampoline to use exclusively another method. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_vfs_disable_trampoline(struct vfs_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_vfs_write_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_write_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_read_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_read_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_open_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_open_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_create_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_fentry, false); +} + +/** + * Set trampoline target + * + * Set the targets we will monitor. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_vfs_set_trampoline_target(struct vfs_bpf *obj) +{ + bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_unlink_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_UNLINK].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_create_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_CREATE].name); + + bpf_program__set_attach_target(obj->progs.netdata_vfs_release_task_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP); +} + +/** + * Attach Probe + * + * Attach probes to target + * + * @param obj is the main structure for bpf objects. + * + * @return It returns 0 on success and -1 otherwise. + */ +static int ebpf_vfs_attach_probe(struct vfs_bpf *obj) +{ + obj->links.netdata_vfs_write_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_write_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_WRITE].name); + int ret = libbpf_get_error(obj->links.netdata_vfs_write_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_write_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_write_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_WRITE].name); + ret = libbpf_get_error(obj->links.netdata_vfs_write_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_writev_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_writev_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_WRITEV].name); + ret = libbpf_get_error(obj->links.netdata_vfs_writev_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_writev_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_writev_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_WRITEV].name); + ret = libbpf_get_error(obj->links.netdata_vfs_writev_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_read_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_read_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_READ].name); + ret = libbpf_get_error(obj->links.netdata_vfs_read_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_read_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_read_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_READ].name); + ret = libbpf_get_error(obj->links.netdata_vfs_read_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_readv_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_readv_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_READV].name); + ret = libbpf_get_error(obj->links.netdata_vfs_readv_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_readv_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_readv_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_READV].name); + ret = libbpf_get_error(obj->links.netdata_vfs_readv_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_unlink_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_unlink_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_UNLINK].name); + ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_unlink_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_unlink_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_UNLINK].name); + ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_fsync_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name); + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_fsync_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name); + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_OPEN].name); + ret = libbpf_get_error(obj->links.netdata_vfs_open_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_OPEN].name); + ret = libbpf_get_error(obj->links.netdata_vfs_open_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_create_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_CREATE].name); + ret = libbpf_get_error(obj->links.netdata_vfs_create_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_create_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_CREATE].name); + ret = libbpf_get_error(obj->links.netdata_vfs_create_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_fsync_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name); + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_fsync_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name); + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_OPEN].name); + ret = libbpf_get_error(obj->links.netdata_vfs_open_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_OPEN].name); + ret = libbpf_get_error(obj->links.netdata_vfs_open_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_create_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kprobe, false, + vfs_targets[NETDATA_EBPF_VFS_CREATE].name); + ret = libbpf_get_error(obj->links.netdata_vfs_create_kprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_create_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kretprobe, true, + vfs_targets[NETDATA_EBPF_VFS_CREATE].name); + ret = libbpf_get_error(obj->links.netdata_vfs_create_kretprobe); + if (ret) + return -1; + + obj->links.netdata_vfs_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_release_task_fentry, + true, + EBPF_COMMON_FNCT_CLEAN_UP); + ret = libbpf_get_error(obj->links.netdata_vfs_release_task_kprobe); + if (ret) + return -1; + + return 0; +} + +/** + * Adjust Map Size + * + * Resize maps according input from users. + * + * @param obj is the main structure for bpf objects. + * @param em structure with configuration + */ +static void ebpf_vfs_adjust_map_size(struct vfs_bpf *obj, ebpf_module_t *em) +{ + ebpf_update_map_size(obj->maps.tbl_vfs_pid, &vfs_maps[NETDATA_VFS_PID], + em, bpf_map__name(obj->maps.tbl_vfs_pid)); +} + +/** + * Set hash tables + * + * Set the values for maps according the value given by kernel. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_vfs_set_hash_tables(struct vfs_bpf *obj) +{ + vfs_maps[NETDATA_VFS_ALL].map_fd = bpf_map__fd(obj->maps.tbl_vfs_stats); + vfs_maps[NETDATA_VFS_PID].map_fd = bpf_map__fd(obj->maps.tbl_vfs_pid); + vfs_maps[NETDATA_VFS_CTRL].map_fd = bpf_map__fd(obj->maps.vfs_ctrl); +} + +/** + * Disable Release Task + * + * Disable release task when apps is not enabled. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_vfs_disable_release_task(struct vfs_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_kprobe, false); +} + +/** + * Load and attach + * + * Load and attach the eBPF code in kernel. + * + * @param obj is the main structure for bpf objects. + * @param em structure with configuration + * + * @return it returns 0 on succes and -1 otherwise + */ +static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *em) +{ + netdata_ebpf_targets_t *mt = em->targets; + netdata_ebpf_program_loaded_t test = mt[NETDATA_EBPF_VFS_WRITE].mode; + + if (test == EBPF_LOAD_TRAMPOLINE) { + ebpf_vfs_disable_probes(obj); + + ebpf_vfs_set_trampoline_target(obj); + } else { + ebpf_vfs_disable_trampoline(obj); + } + + ebpf_vfs_adjust_map_size(obj, em); + + if (!em->apps_charts && !em->cgroup_charts) + ebpf_vfs_disable_release_task(obj); + + int ret = vfs_bpf__load(obj); + if (ret) { + return ret; + } + + ret = (test == EBPF_LOAD_TRAMPOLINE) ? vfs_bpf__attach(obj) : ebpf_vfs_attach_probe(obj); + if (!ret) { + ebpf_vfs_set_hash_tables(obj); + + ebpf_update_controller(vfs_maps[NETDATA_VFS_CTRL].map_fd, em); + } + + return ret; +} +#endif /***************************************************************** * * FUNCTIONS TO CLOSE THE THREAD * *****************************************************************/ + +/** + * Cachestat Free + * + * Cleanup variables after child threads to stop + * + * @param ptr thread data. + */ +static void ebpf_vfs_free(ebpf_module_t *em) +{ + pthread_mutex_lock(&ebpf_exit_cleanup); + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING; + pthread_mutex_unlock(&ebpf_exit_cleanup); + return; + } + pthread_mutex_unlock(&ebpf_exit_cleanup); + + freez(vfs_hash_values); + freez(vfs_vector); + freez(vfs_threads.thread); + +#ifdef LIBBPF_MAJOR_VERSION + if (bpf_obj) + vfs_bpf__destroy(bpf_obj); +#endif + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; + pthread_mutex_unlock(&ebpf_exit_cleanup); +} + /** * Exit * @@ -54,12 +440,8 @@ static enum ebpf_threads_status ebpf_vfs_exited = NETDATA_THREAD_EBPF_RUNNING; static void ebpf_vfs_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (!em->enabled) { - em->enabled = NETDATA_MAIN_THREAD_EXITED; - return; - } - - ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPING; + netdata_thread_cancel(*vfs_threads.thread); + ebpf_vfs_free(em); } /** @@ -70,15 +452,7 @@ static void ebpf_vfs_exit(void *ptr) static void ebpf_vfs_cleanup(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - if (ebpf_vfs_exited != NETDATA_THREAD_EBPF_STOPPED) - return; - - freez(vfs_hash_values); - freez(vfs_vector); - freez(vfs_threads.thread); - - vfs_threads.enabled = NETDATA_MAIN_THREAD_EXITED; - em->enabled = NETDATA_MAIN_THREAD_EXITED; + ebpf_vfs_free(em); } /***************************************************************** @@ -519,17 +893,12 @@ void *ebpf_vfs_read_hash(void *ptr) usec_t step = NETDATA_LATENCY_VFS_SLEEP_MS * em->update_every; //This will be cancelled by its parent - while (ebpf_vfs_exited == NETDATA_THREAD_EBPF_RUNNING) { - usec_t dt = heartbeat_next(&hb, step); - (void)dt; - if (ebpf_vfs_exited == NETDATA_THREAD_EBPF_STOPPING) - break; + while (!ebpf_exit_plugin) { + (void)heartbeat_next(&hb, step); read_global_table(); } - ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPED; - netdata_thread_cleanup_pop(1); return NULL; } @@ -976,20 +1345,15 @@ static void ebpf_create_systemd_vfs_charts(ebpf_module_t *em) * Send collected data to Netdata. * * @param em the main collector structure - * - * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned - * otherwise function returns 1 to avoid chart recreation */ -static int ebpf_send_systemd_vfs_charts(ebpf_module_t *em) +static void ebpf_send_systemd_vfs_charts(ebpf_module_t *em) { - int ret = 1; ebpf_cgroup_target_t *ect; write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_DELETED); for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { if (unlikely(ect->systemd) && unlikely(ect->updated)) { write_chart_dimension(ect->name, ect->publish_systemd_vfs.unlink_call); - } else if (unlikely(ect->systemd)) - ret = 0; + } } write_end_chart(); @@ -1105,8 +1469,6 @@ static int ebpf_send_systemd_vfs_charts(ebpf_module_t *em) } write_end_chart(); } - - return ret; } /** @@ -1127,13 +1489,10 @@ static void ebpf_vfs_send_cgroup_data(ebpf_module_t *em) int has_systemd = shm_ebpf_cgroup.header->systemd_enabled; if (has_systemd) { - static int systemd_charts = 0; - if (!systemd_charts) { + if (send_cgroup_chart) { ebpf_create_systemd_vfs_charts(em); - systemd_charts = 1; } - - systemd_charts = ebpf_send_systemd_vfs_charts(em); + ebpf_send_systemd_vfs_charts(em); } for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) { @@ -1543,6 +1902,36 @@ static void ebpf_vfs_allocate_global_vectors(int apps) * *****************************************************************/ +/* + * Load BPF + * + * Load BPF files. + * + * @param em the structure with configuration + */ +static int ebpf_vfs_load_bpf(ebpf_module_t *em) +{ + int ret = 0; + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_EBPF_VFS_WRITE].mode); + if (em->load & EBPF_LOAD_LEGACY) { + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); + if (!em->probe_links) { + ret = -1; + } + } +#ifdef LIBBPF_MAJOR_VERSION + else { + bpf_obj = vfs_bpf__open(); + if (!bpf_obj) + ret = -1; + else + ret = ebpf_vfs_load_and_attach(bpf_obj, em); + } +#endif + + return ret; +} + /** * Process thread * @@ -1563,12 +1952,11 @@ void *ebpf_vfs_thread(void *ptr) ebpf_vfs_allocate_global_vectors(em->apps_charts); - if (!em->enabled) - goto endvfs; - - em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects); - if (!em->probe_links) { - em->enabled = CONFIG_BOOLEAN_NO; +#ifdef LIBBPF_MAJOR_VERSION + ebpf_adjust_thread_load(em, default_btf); +#endif + if (ebpf_vfs_load_bpf(em)) { + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED; goto endvfs; } @@ -1588,8 +1976,7 @@ void *ebpf_vfs_thread(void *ptr) vfs_collector(em); endvfs: - if (!em->enabled) - ebpf_update_disabled_plugin_stats(em); + ebpf_update_disabled_plugin_stats(em); netdata_thread_cleanup_pop(1); return NULL; diff --git a/collectors/ebpf.plugin/ebpf_vfs.h b/collectors/ebpf.plugin/ebpf_vfs.h index 87a21e39c..2e3c7cc29 100644 --- a/collectors/ebpf.plugin/ebpf_vfs.h +++ b/collectors/ebpf.plugin/ebpf_vfs.h @@ -149,13 +149,28 @@ enum vfs_counters { enum netdata_vfs_tables { NETDATA_VFS_PID, - NETDATA_VFS_ALL + NETDATA_VFS_ALL, + NETDATA_VFS_CTRL +}; + +enum netdata_vfs_calls_name { + NETDATA_EBPF_VFS_WRITE, + NETDATA_EBPF_VFS_WRITEV, + NETDATA_EBPF_VFS_READ, + NETDATA_EBPF_VFS_READV, + NETDATA_EBPF_VFS_UNLINK, + NETDATA_EBPF_VFS_FSYNC, + NETDATA_EBPF_VFS_OPEN, + NETDATA_EBPF_VFS_CREATE, + + NETDATA_VFS_END_LIST }; extern netdata_publish_vfs_t **vfs_pid; -extern void *ebpf_vfs_thread(void *ptr); -extern void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr); +void *ebpf_vfs_thread(void *ptr); +void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr); +extern netdata_ebpf_targets_t vfs_targets[]; extern struct config vfs_config; diff --git a/collectors/fping.plugin/README.md b/collectors/fping.plugin/README.md index 626edf5d0..e32d3911b 100644 --- a/collectors/fping.plugin/README.md +++ b/collectors/fping.plugin/README.md @@ -8,22 +8,30 @@ custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/fping The fping plugin supports monitoring latency, packet loss and uptime of any number of network end points, by pinging them with `fping`. -A recent version of `fping` is required (one that supports option `-N`). -The supplied plugin can install it, by running: +This plugin requires version 5.1 or newer of `fping` (earlier versions may or may not work). Our static builds and +Docker images come bundled with a known working version of `fping`. Native packages and local builds will need to +have a working version installed before the plugin is usable. + +## Installing fping locally + +If your distribution’s repositories do not include a working version of `fping`, the supplied plugin can install +it, by running: ```sh /usr/libexec/netdata/plugins.d/fping.plugin install ``` -The above will download, build and install the right version as `/usr/local/bin/fping`. +The above will download, build and install the right version as `/usr/local/bin/fping`. This requires a working C +compiler, GNU autotools (at least autoconf and automake), and GNU make. On Debian or Ubuntu, you can pull in most +of the required tools by installing the `build-essential` package (this should include everything except automake +and autoconf). + +## Configuration Then you need to edit `/etc/netdata/fping.conf` (to edit it on your system run `/etc/netdata/edit-config fping.conf`) like this: ```sh -# uncomment the following line - it should already be there -fping="/usr/local/bin/fping" - # set here all the hosts you need to ping # I suggest to use hostnames and put their IPs in /etc/hosts hosts="host1 host2 host3" diff --git a/collectors/freebsd.plugin/freebsd_devstat.c b/collectors/freebsd.plugin/freebsd_devstat.c index 66a1e61d2..0f037741a 100644 --- a/collectors/freebsd.plugin/freebsd_devstat.c +++ b/collectors/freebsd.plugin/freebsd_devstat.c @@ -347,8 +347,6 @@ int do_kern_devstat(int update_every, usec_t dt) { 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] || @@ -375,8 +373,7 @@ int do_kern_devstat(int update_every, usec_t dt) { 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]); @@ -384,8 +381,6 @@ int do_kern_devstat(int update_every, usec_t dt) { 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] || @@ -417,8 +412,7 @@ int do_kern_devstat(int update_every, usec_t dt) { 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]); @@ -427,8 +421,6 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_done(dm->st_ops); } - // -------------------------------------------------------------------- - if(dm->do_qops == CONFIG_BOOLEAN_YES || (dm->do_qops == CONFIG_BOOLEAN_AUTO && (dstat[i].start_count || dstat[i].end_count || @@ -451,15 +443,12 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_flag_set(dm->st_qops, RRDSET_FLAG_DETAIL); dm->rd_qops = rrddim_add(dm->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(dm->st_qops); + } rrddim_set_by_pointer(dm->st_qops, dm->rd_qops, dstat[i].start_count - dstat[i].end_count); rrdset_done(dm->st_qops); } - // -------------------------------------------------------------------- - if(dm->do_util == CONFIG_BOOLEAN_YES || (dm->do_util == CONFIG_BOOLEAN_AUTO && (cur_dstat.busy_time_ms || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -482,15 +471,12 @@ int do_kern_devstat(int update_every, usec_t dt) { dm->rd_util = rrddim_add(dm->st_util, "utilization", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(dm->st_util); + } rrddim_set_by_pointer(dm->st_util, dm->rd_util, cur_dstat.busy_time_ms); rrdset_done(dm->st_util); } - // -------------------------------------------------------------------- - if(dm->do_iotime == CONFIG_BOOLEAN_YES || (dm->do_iotime == CONFIG_BOOLEAN_AUTO && (cur_dstat.duration_read_ms || cur_dstat.duration_write_ms || @@ -522,8 +508,7 @@ int do_kern_devstat(int update_every, usec_t dt) { 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); @@ -532,14 +517,10 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_done(dm->st_iotime); } - // -------------------------------------------------------------------- // calculate differential charts // only if this is not the first time we run if (likely(dt)) { - - // -------------------------------------------------------------------- - if(dm->do_await == CONFIG_BOOLEAN_YES || (dm->do_await == CONFIG_BOOLEAN_AUTO && (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE] || @@ -571,8 +552,7 @@ int do_kern_devstat(int update_every, usec_t dt) { 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); + } rrddim_set_by_pointer(dm->st_await, dm->rd_await_in, (dstat[i].operations[DEVSTAT_READ] - @@ -605,8 +585,6 @@ int do_kern_devstat(int update_every, usec_t dt) { 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] || @@ -635,8 +613,7 @@ int do_kern_devstat(int update_every, usec_t dt) { 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); + } rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_in, (dstat[i].operations[DEVSTAT_READ] - @@ -662,8 +639,6 @@ int do_kern_devstat(int update_every, usec_t dt) { 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] || @@ -689,8 +664,7 @@ int do_kern_devstat(int update_every, usec_t dt) { dm->rd_svctm = rrddim_add(dm->st_svctm, "svctm", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(dm->st_svctm); + } rrddim_set_by_pointer(dm->st_svctm, dm->rd_svctm, ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) + @@ -706,8 +680,6 @@ int do_kern_devstat(int update_every, usec_t dt) { rrdset_done(dm->st_svctm); } - // -------------------------------------------------------------------- - 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]; @@ -724,8 +696,6 @@ int do_kern_devstat(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if (likely(do_system_io)) { static RRDSET *st = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; @@ -747,8 +717,7 @@ int do_kern_devstat(int update_every, usec_t dt) { rd_in = rrddim_add(st, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, total_disk_kbytes_read); rrddim_set_by_pointer(st, rd_out, total_disk_kbytes_write); @@ -756,6 +725,7 @@ int do_kern_devstat(int update_every, usec_t dt) { } } } + if (unlikely(common_error)) { do_system_io = 0; error("DISABLED: system.io chart"); diff --git a/collectors/freebsd.plugin/freebsd_getifaddrs.c b/collectors/freebsd.plugin/freebsd_getifaddrs.c index 0c0c1e7ab..1e870c0db 100644 --- a/collectors/freebsd.plugin/freebsd_getifaddrs.c +++ b/collectors/freebsd.plugin/freebsd_getifaddrs.c @@ -226,8 +226,6 @@ int do_getifaddrs(int update_every, usec_t dt) { u_long ift_omcasts; } iftot = {0, 0, 0, 0, 0, 0}; - // -------------------------------------------------------------------- - if (likely(do_bandwidth_net)) { iftot.ift_ibytes = iftot.ift_obytes = 0; @@ -260,19 +258,16 @@ int do_getifaddrs(int update_every, usec_t dt) { rd_in = rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes); rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_packets_net)) { - iftot.ift_ipackets = iftot.ift_opackets = iftot.ift_imcasts = iftot.ift_omcasts = 0; + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; @@ -308,8 +303,7 @@ int do_getifaddrs(int update_every, usec_t dt) { rd_packets_out = rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_packets_m_in = rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_packets_m_out = rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_packets_in, iftot.ift_ipackets); rrddim_set_by_pointer(st, rd_packets_out, iftot.ift_opackets); @@ -318,8 +312,6 @@ int do_getifaddrs(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_bandwidth_ipv4)) { iftot.ift_ibytes = iftot.ift_obytes = 0; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { @@ -349,16 +341,13 @@ int do_getifaddrs(int update_every, usec_t dt) { rd_in = rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes); rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_bandwidth_ipv6)) { iftot.ift_ibytes = iftot.ift_obytes = 0; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { @@ -388,16 +377,13 @@ int do_getifaddrs(int update_every, usec_t dt) { rd_in = rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes); rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes); rrdset_done(st); } - // -------------------------------------------------------------------- - network_interfaces_found = 0; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { @@ -437,8 +423,6 @@ int do_getifaddrs(int update_every, usec_t dt) { if (unlikely(!ifm->enabled)) continue; - // -------------------------------------------------------------------- - if (ifm->do_bandwidth == CONFIG_BOOLEAN_YES || (ifm->do_bandwidth == CONFIG_BOOLEAN_AUTO && (IFA_DATA(ibytes) || IFA_DATA(obytes) || @@ -460,16 +444,13 @@ int do_getifaddrs(int update_every, usec_t dt) { ifm->rd_bandwidth_in = rrddim_add(ifm->st_bandwidth, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); ifm->rd_bandwidth_out = rrddim_add(ifm->st_bandwidth, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(ifm->st_bandwidth); + } rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_in, IFA_DATA(ibytes)); rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_out, IFA_DATA(obytes)); rrdset_done(ifm->st_bandwidth); } - // -------------------------------------------------------------------- - if (ifm->do_packets == CONFIG_BOOLEAN_YES || (ifm->do_packets == CONFIG_BOOLEAN_AUTO && (IFA_DATA(ipackets) || IFA_DATA(opackets) || @@ -501,8 +482,7 @@ int do_getifaddrs(int update_every, usec_t dt) { RRD_ALGORITHM_INCREMENTAL); ifm->rd_packets_m_out = rrddim_add(ifm->st_packets, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(ifm->st_packets); + } rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_in, IFA_DATA(ipackets)); rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_out, IFA_DATA(opackets)); @@ -511,8 +491,6 @@ int do_getifaddrs(int update_every, usec_t dt) { rrdset_done(ifm->st_packets); } - // -------------------------------------------------------------------- - if (ifm->do_errors == CONFIG_BOOLEAN_YES || (ifm->do_errors == CONFIG_BOOLEAN_AUTO && (IFA_DATA(ierrors) || IFA_DATA(oerrors) || @@ -536,14 +514,12 @@ int do_getifaddrs(int update_every, usec_t dt) { ifm->rd_errors_in = rrddim_add(ifm->st_errors, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); ifm->rd_errors_out = rrddim_add(ifm->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(ifm->st_errors); + } rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_in, IFA_DATA(ierrors)); rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_out, IFA_DATA(oerrors)); rrdset_done(ifm->st_errors); } - // -------------------------------------------------------------------- if (ifm->do_drops == CONFIG_BOOLEAN_YES || (ifm->do_drops == CONFIG_BOOLEAN_AUTO && (IFA_DATA(iqdrops) || @@ -572,8 +548,7 @@ int do_getifaddrs(int update_every, usec_t dt) { #if __FreeBSD__ >= 11 ifm->rd_drops_out = rrddim_add(ifm->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); #endif - } else - rrdset_next(ifm->st_drops); + } rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_in, IFA_DATA(iqdrops)); #if __FreeBSD__ >= 11 @@ -582,8 +557,6 @@ int do_getifaddrs(int update_every, usec_t dt) { rrdset_done(ifm->st_drops); } - // -------------------------------------------------------------------- - if (ifm->do_events == CONFIG_BOOLEAN_YES || (ifm->do_events == CONFIG_BOOLEAN_AUTO && (IFA_DATA(collisions) || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -606,8 +579,7 @@ int do_getifaddrs(int update_every, usec_t dt) { ifm->rd_events_coll = rrddim_add(ifm->st_events, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(ifm->st_events); + } rrddim_set_by_pointer(ifm->st_events, ifm->rd_events_coll, IFA_DATA(collisions)); rrdset_done(ifm->st_events); diff --git a/collectors/freebsd.plugin/freebsd_getmntinfo.c b/collectors/freebsd.plugin/freebsd_getmntinfo.c index f83a4a0db..e8feefc2b 100644 --- a/collectors/freebsd.plugin/freebsd_getmntinfo.c +++ b/collectors/freebsd.plugin/freebsd_getmntinfo.c @@ -212,8 +212,6 @@ int do_getmntinfo(int update_every, usec_t dt) { if (unlikely(mntbuf[i].f_flags & MNT_RDONLY && !m->collected)) continue; - // -------------------------------------------------------------------------- - int rendered = 0; if (m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && @@ -242,8 +240,7 @@ int do_getmntinfo(int update_every, usec_t dt) { mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(m->st_space); + } rrddim_set_by_pointer(m->st_space, m->rd_space_avail, (collected_number) mntbuf[i].f_bavail); rrddim_set_by_pointer(m->st_space, m->rd_space_used, (collected_number) (mntbuf[i].f_blocks - @@ -255,8 +252,6 @@ int do_getmntinfo(int update_every, usec_t dt) { rendered++; } - // -------------------------------------------------------------------------- - if (m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (mntbuf[i].f_files > 1 || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -279,8 +274,7 @@ int do_getmntinfo(int update_every, usec_t dt) { m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(m->st_inodes); + } rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_avail, (collected_number) mntbuf[i].f_ffree); rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_used, (collected_number) (mntbuf[i].f_files - diff --git a/collectors/freebsd.plugin/freebsd_ipfw.c b/collectors/freebsd.plugin/freebsd_ipfw.c index 16e9fd332..178eaa36c 100644 --- a/collectors/freebsd.plugin/freebsd_ipfw.c +++ b/collectors/freebsd.plugin/freebsd_ipfw.c @@ -149,8 +149,6 @@ int do_ipfw(int update_every, usec_t dt) { dynsz = 0; } - // -------------------------------------------------------------------- - if (likely(do_mem)) { static RRDSET *st_mem = NULL; static RRDDIM *rd_dyn_mem = NULL; @@ -174,22 +172,19 @@ int do_ipfw(int update_every, usec_t dt) { rd_dyn_mem = rrddim_add(st_mem, "dynamic", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rd_stat_mem = rrddim_add(st_mem, "static", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(st_mem); + } rrddim_set_by_pointer(st_mem, rd_dyn_mem, dynsz); rrddim_set_by_pointer(st_mem, rd_stat_mem, *optlen - dynsz); rrdset_done(st_mem); } - // -------------------------------------------------------------------- - static RRDSET *st_packets = NULL, *st_bytes = NULL; RRDDIM *rd_packets = NULL, *rd_bytes = NULL; if (likely(do_static || do_dynamic)) { if (likely(do_static)) { - if (unlikely(!st_packets)) + if (unlikely(!st_packets)) { st_packets = rrdset_create_localhost("ipfw", "packets", NULL, @@ -203,10 +198,9 @@ int do_ipfw(int update_every, usec_t dt) { update_every, RRDSET_TYPE_STACKED ); - else - rrdset_next(st_packets); + } - if (unlikely(!st_bytes)) + if (unlikely(!st_bytes)) { st_bytes = rrdset_create_localhost("ipfw", "bytes", NULL, @@ -220,8 +214,7 @@ int do_ipfw(int update_every, usec_t dt) { update_every, RRDSET_TYPE_STACKED ); - else - rrdset_next(st_bytes); + } } for (n = seen = 0; n < rcnt; n++, rbase = (ipfw_obj_tlv *) ((caddr_t) rbase + rbase->length)) { @@ -256,8 +249,6 @@ int do_ipfw(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - // go through dynamic rules configuration structures if (likely(do_dynamic && (dynsz > 0))) { @@ -305,12 +296,10 @@ int do_ipfw(int update_every, usec_t dt) { dynbase += tlv->length; } - // -------------------------------------------------------------------- - static RRDSET *st_active = NULL, *st_expired = NULL; RRDDIM *rd_active = NULL, *rd_expired = NULL; - if (unlikely(!st_active)) + if (unlikely(!st_active)) { st_active = rrdset_create_localhost("ipfw", "active", NULL, @@ -324,10 +313,9 @@ int do_ipfw(int update_every, usec_t dt) { update_every, RRDSET_TYPE_STACKED ); - else - rrdset_next(st_active); + } - if (unlikely(!st_expired)) + if (unlikely(!st_expired)) { st_expired = rrdset_create_localhost("ipfw", "expired", NULL, @@ -341,8 +329,7 @@ int do_ipfw(int update_every, usec_t dt) { update_every, RRDSET_TYPE_STACKED ); - else - rrdset_next(st_expired); + } for (srn = 0; (srn < (static_rules_num - 1)) && (dyn_rules_num[srn].rule_num != IPFW_DEFAULT_RULE); srn++) { sprintf(rule_num_str, "%d", dyn_rules_num[srn].rule_num); diff --git a/collectors/freebsd.plugin/freebsd_kstat_zfs.c b/collectors/freebsd.plugin/freebsd_kstat_zfs.c index 142fdb974..046a1e693 100644 --- a/collectors/freebsd.plugin/freebsd_kstat_zfs.c +++ b/collectors/freebsd.plugin/freebsd_kstat_zfs.c @@ -7,7 +7,6 @@ extern struct arcstats arcstats; unsigned long long zfs_arcstats_shrinkable_cache_size_bytes = 0; -// -------------------------------------------------------------------------------------------------------------------- // kstat.zfs.misc.arcstats int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt) { @@ -227,7 +226,6 @@ int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // kstat.zfs.misc.zio_trim int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt) { @@ -246,8 +244,6 @@ int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt) { return 1; } else { - // -------------------------------------------------------------------- - static RRDSET *st_bytes = NULL; static RRDDIM *rd_bytes = NULL; @@ -269,13 +265,10 @@ int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt) { 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; @@ -299,7 +292,6 @@ int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt) { 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); diff --git a/collectors/freebsd.plugin/freebsd_sysctl.c b/collectors/freebsd.plugin/freebsd_sysctl.c index 016a71e37..dd94a1615 100644 --- a/collectors/freebsd.plugin/freebsd_sysctl.c +++ b/collectors/freebsd.plugin/freebsd_sysctl.c @@ -90,7 +90,6 @@ typedef struct vmmeter vmmeter_t; #define NETDATA_COLLECT_LAUNDRY 1 #endif -// -------------------------------------------------------------------------------------------------------------------- // FreeBSD plugin initialization int freebsd_plugin_init() @@ -114,7 +113,6 @@ int freebsd_plugin_init() return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.loadavg // FreeBSD calculates load averages once every 5 seconds @@ -132,9 +130,6 @@ int do_vm_loadavg(int update_every, usec_t dt){ error("DISABLED: vm.loadavg module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd_load1 = NULL, *rd_load2 = NULL, *rd_load3 = NULL; @@ -156,8 +151,7 @@ int do_vm_loadavg(int update_every, usec_t dt){ rd_load1 = rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rd_load2 = rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rd_load3 = rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_load1, (collected_number) ((double) sysload.ldavg[0] / sysload.fscale * 1000)); rrddim_set_by_pointer(st, rd_load2, (collected_number) ((double) sysload.ldavg[1] / sysload.fscale * 1000)); @@ -173,7 +167,6 @@ int do_vm_loadavg(int update_every, usec_t dt){ return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.vmtotal int do_vm_vmtotal(int update_every, usec_t dt) { @@ -200,9 +193,6 @@ int do_vm_vmtotal(int update_every, usec_t dt) { error("DISABLED: vm.vmtotal module"); return 1; } else { - - // -------------------------------------------------------------------- - if (likely(do_all_processes)) { static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -224,14 +214,11 @@ int do_vm_vmtotal(int update_every, usec_t dt) { ); rd = rrddim_add(st, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, (vmtotal_data.t_rq + vmtotal_data.t_dw + vmtotal_data.t_pw + vmtotal_data.t_sl + vmtotal_data.t_sw)); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_processes)) { static RRDSET *st = NULL; static RRDDIM *rd_running = NULL, *rd_blocked = NULL; @@ -255,15 +242,12 @@ int do_vm_vmtotal(int update_every, usec_t dt) { rd_running = rrddim_add(st, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rd_blocked = rrddim_add(st, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_running, vmtotal_data.t_rq); rrddim_set_by_pointer(st, rd_blocked, (vmtotal_data.t_dw + vmtotal_data.t_pw)); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_mem_real)) { static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -287,7 +271,6 @@ int do_vm_vmtotal(int update_every, usec_t dt) { rd = rrddim_add(st, "used", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, vmtotal_data.t_rm); rrdset_done(st); @@ -301,7 +284,6 @@ int do_vm_vmtotal(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // kern.cp_time int do_kern_cp_time(int update_every, usec_t dt) { @@ -321,9 +303,6 @@ int do_kern_cp_time(int update_every, usec_t dt) { error("DISABLED: kern.cp_time module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd_nice = NULL, *rd_system = NULL, *rd_user = NULL, *rd_interrupt = NULL, *rd_idle = NULL; @@ -350,7 +329,6 @@ int do_kern_cp_time(int update_every, usec_t dt) { rd_idle = rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(st, "idle"); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_nice, cp_time[1]); rrddim_set_by_pointer(st, rd_system, cp_time[2]); @@ -364,7 +342,6 @@ int do_kern_cp_time(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // kern.cp_times int do_kern_cp_times(int update_every, usec_t dt) { @@ -388,9 +365,6 @@ int do_kern_cp_times(int update_every, usec_t dt) { error("DISABLED: kern.cp_times module"); return 1; } else { - - // -------------------------------------------------------------------- - int i; static struct cpu_chart { char cpuid[MAX_INT_DIGITS + 4]; @@ -436,7 +410,7 @@ int do_kern_cp_times(int update_every, usec_t dt) { all_cpu_charts[i].rd_idle = rrddim_add(all_cpu_charts[i].st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(all_cpu_charts[i].st, "idle"); - } else rrdset_next(all_cpu_charts[i].st); + } rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_nice, pcpu_cp_time[i * 5 + 1]); rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_system, pcpu_cp_time[i * 5 + 2]); @@ -453,7 +427,6 @@ int do_kern_cp_times(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // dev.cpu.temperature int do_dev_cpu_temperature(int update_every, usec_t dt) { @@ -482,8 +455,6 @@ int do_dev_cpu_temperature(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - static RRDSET *st; static RRDDIM **rd_pcpu_temperature; @@ -509,7 +480,6 @@ int do_dev_cpu_temperature(int update_every, usec_t dt) { RRDSET_TYPE_LINE ); } - else rrdset_next(st); for (i = 0; i < number_of_cpus; i++) { if (unlikely(!rd_pcpu_temperature[i])) { @@ -527,7 +497,6 @@ int do_dev_cpu_temperature(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // dev.cpu.0.freq int do_dev_cpu_0_freq(int update_every, usec_t dt) { @@ -540,9 +509,6 @@ int do_dev_cpu_0_freq(int update_every, usec_t dt) { error("DISABLED: dev.cpu.0.freq module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -564,7 +530,6 @@ int do_dev_cpu_0_freq(int update_every, usec_t dt) { 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); @@ -606,8 +571,6 @@ int do_hw_intcnt(int update_every, usec_t dt) { for (i = 0; i < nintr; i++) totalintr += intrcnt[i]; - // -------------------------------------------------------------------- - static RRDSET *st_intr = NULL; static RRDDIM *rd_intr = NULL; @@ -629,14 +592,11 @@ int do_hw_intcnt(int update_every, usec_t dt) { rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL); rd_intr = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st_intr); + } rrddim_set_by_pointer(st_intr, rd_intr, totalintr); rrdset_done(st_intr); - // -------------------------------------------------------------------- - size_t size; static int mib_hw_intrnames[2] = {0, 0}; static char *intrnames = NULL; @@ -655,12 +615,9 @@ int do_hw_intcnt(int update_every, usec_t dt) { error("DISABLED: hw.intrcnt module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st_interrupts = NULL; - if (unlikely(!st_interrupts)) + if (unlikely(!st_interrupts)) { st_interrupts = rrdset_create_localhost( "system", "interrupts", @@ -675,8 +632,7 @@ int do_hw_intcnt(int update_every, usec_t dt) { update_every, RRDSET_TYPE_STACKED ); - else - rrdset_next(st_interrupts); + } for (i = 0; i < nintr; i++) { void *p; @@ -702,7 +658,6 @@ int do_hw_intcnt(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.stats.sys.v_intr int do_vm_stats_sys_v_intr(int update_every, usec_t dt) { @@ -715,9 +670,6 @@ int do_vm_stats_sys_v_intr(int update_every, usec_t dt) { error("DISABLED: vm.stats.sys.v_intr module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -739,7 +691,6 @@ int do_vm_stats_sys_v_intr(int update_every, usec_t dt) { rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, int_number); rrdset_done(st); @@ -748,7 +699,6 @@ int do_vm_stats_sys_v_intr(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.stats.sys.v_soft int do_vm_stats_sys_v_soft(int update_every, usec_t dt) { @@ -761,9 +711,6 @@ int do_vm_stats_sys_v_soft(int update_every, usec_t dt) { error("DISABLED: vm.stats.sys.v_soft module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -785,7 +732,6 @@ int do_vm_stats_sys_v_soft(int update_every, usec_t dt) { rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, soft_intr_number); rrdset_done(st); @@ -794,7 +740,6 @@ int do_vm_stats_sys_v_soft(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.stats.sys.v_swtch int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) { @@ -807,9 +752,6 @@ int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) { error("DISABLED: vm.stats.sys.v_swtch module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -831,7 +773,6 @@ int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) { rd = rrddim_add(st, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, ctxt_number); rrdset_done(st); @@ -840,7 +781,6 @@ int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.stats.vm.v_forks int do_vm_stats_sys_v_forks(int update_every, usec_t dt) { @@ -879,7 +819,6 @@ int do_vm_stats_sys_v_forks(int update_every, usec_t dt) { rd = rrddim_add(st, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, forks_number); rrdset_done(st); @@ -888,7 +827,6 @@ int do_vm_stats_sys_v_forks(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.swap_info int do_vm_swap_info(int update_every, usec_t dt) { @@ -931,8 +869,6 @@ int do_vm_swap_info(int update_every, usec_t dt) { total_xsw.bytes_total += xsw.xsw_nblks; } - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd_free = NULL, *rd_used = NULL; @@ -957,7 +893,6 @@ int do_vm_swap_info(int update_every, usec_t dt) { rd_free = rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); rd_used = rrddim_add(st, "used", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_free, total_xsw.bytes_total - total_xsw.bytes_used); rrddim_set_by_pointer(st, rd_used, total_xsw.bytes_used); @@ -967,7 +902,6 @@ int do_vm_swap_info(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // system.ram int do_system_ram(int update_every, usec_t dt) { @@ -1002,9 +936,6 @@ int do_system_ram(int update_every, usec_t dt) { error("DISABLED: system.ram module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL, *st_mem_available = NULL; static RRDDIM *rd_free = NULL, *rd_active = NULL, *rd_inactive = NULL, *rd_wired = NULL, *rd_cache = NULL, *rd_buffers = NULL, *rd_avail = NULL; @@ -1039,7 +970,6 @@ int do_system_ram(int update_every, usec_t dt) { #endif rd_buffers = rrddim_add(st, "buffers", NULL, 1, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_free, vmmeter_data.v_free_count); rrddim_set_by_pointer(st, rd_active, vmmeter_data.v_active_count); @@ -1074,7 +1004,6 @@ int do_system_ram(int update_every, usec_t dt) { rd_avail = rrddim_add(st_mem_available, "MemAvailable", "avail", system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_available); #if __FreeBSD_version < 1200016 rrddim_set_by_pointer(st_mem_available, rd_avail, vmmeter_data.v_inactive_count + vmmeter_data.v_free_count + vmmeter_data.v_cache_count + zfs_arcstats_shrinkable_cache_size_bytes / system_pagesize); @@ -1088,7 +1017,6 @@ int do_system_ram(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.stats.vm.v_swappgs int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) { @@ -1102,9 +1030,6 @@ int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) { error("DISABLED: vm.stats.vm.v_swappgs module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; @@ -1127,7 +1052,6 @@ int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) { rd_in = rrddim_add(st, "in", NULL, system_pagesize, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "out", NULL, -system_pagesize, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_in, vmmeter_data.v_swappgsin); rrddim_set_by_pointer(st, rd_out, vmmeter_data.v_swappgsout); @@ -1137,7 +1061,6 @@ int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // vm.stats.vm.v_pgfaults int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) { @@ -1155,9 +1078,6 @@ int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) { error("DISABLED: vm.stats.vm.v_pgfaults module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd_memory = NULL, *rd_io_requiring = NULL, *rd_cow = NULL, *rd_cow_optimized = NULL, *rd_in_transit = NULL; @@ -1186,7 +1106,6 @@ int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) { rd_cow_optimized = rrddim_add(st, "cow_optimized", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_transit = rrddim_add(st, "in_transit", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_memory, vmmeter_data.v_vm_faults); rrddim_set_by_pointer(st, rd_io_requiring, vmmeter_data.v_io_faults); @@ -1240,8 +1159,6 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - static RRDSET *st_semaphores = NULL, *st_semaphore_arrays = NULL; static RRDDIM *rd_semaphores = NULL, *rd_semaphore_arrays = NULL; @@ -1263,13 +1180,10 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { rd_semaphores = rrddim_add(st_semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_semaphores); rrddim_set_by_pointer(st_semaphores, rd_semaphores, ipc_sem.semaphores); rrdset_done(st_semaphores); - // -------------------------------------------------------------------- - if (unlikely(!st_semaphore_arrays)) { st_semaphore_arrays = rrdset_create_localhost( "system", @@ -1288,7 +1202,6 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { rd_semaphore_arrays = rrddim_add(st_semaphore_arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_semaphore_arrays); rrddim_set_by_pointer(st_semaphore_arrays, rd_semaphore_arrays, ipc_sem.sets); rrdset_done(st_semaphore_arrays); @@ -1298,7 +1211,6 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // kern.ipc.shm int do_kern_ipc_shm(int update_every, usec_t dt) { @@ -1340,8 +1252,6 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - static RRDSET *st_segs = NULL, *st_size = NULL; static RRDDIM *rd_segments = NULL, *rd_allocated = NULL; @@ -1363,13 +1273,10 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { rd_segments = rrddim_add(st_segs, "segments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_segs); rrddim_set_by_pointer(st_segs, rd_segments, ipc_shm.segs); rrdset_done(st_segs); - // -------------------------------------------------------------------- - if (unlikely(!st_size)) { st_size = rrdset_create_localhost( "system", @@ -1388,7 +1295,6 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, KILO_FACTOR, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_size); rrddim_set_by_pointer(st_size, rd_allocated, ipc_shm.segsize); rrdset_done(st_size); @@ -1398,7 +1304,6 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // kern.ipc.msq int do_kern_ipc_msq(int update_every, usec_t dt) { @@ -1446,8 +1351,6 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - static RRDSET *st_queues = NULL, *st_messages = NULL, *st_size = NULL; static RRDDIM *rd_queues = NULL, *rd_messages = NULL, *rd_allocated = NULL, *rd_used = NULL; @@ -1469,13 +1372,10 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { rd_queues = rrddim_add(st_queues, "queues", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_queues); rrddim_set_by_pointer(st_queues, rd_queues, ipc_msq.queues); rrdset_done(st_queues); - // -------------------------------------------------------------------- - if (unlikely(!st_messages)) { st_messages = rrdset_create_localhost( "system", @@ -1494,13 +1394,10 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { rd_messages = rrddim_add(st_messages, "messages", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_messages); rrddim_set_by_pointer(st_messages, rd_messages, ipc_msq.messages); rrdset_done(st_messages); - // -------------------------------------------------------------------- - if (unlikely(!st_size)) { st_size = rrdset_create_localhost( "system", @@ -1520,7 +1417,6 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rd_used = rrddim_add(st_size, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_size); rrddim_set_by_pointer(st_size, rd_allocated, ipc_msq.allocsize); rrddim_set_by_pointer(st_size, rd_used, ipc_msq.usedsize); @@ -1531,7 +1427,6 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // uptime int do_uptime(int update_every, usec_t dt) { @@ -1540,8 +1435,6 @@ int do_uptime(int update_every, usec_t dt) { clock_gettime(CLOCK_UPTIME, &up_time); - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -1563,15 +1456,12 @@ int do_uptime(int update_every, usec_t dt) { rd = rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, up_time.tv_sec); rrdset_done(st); - return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.isr int do_net_isr(int update_every, usec_t dt) { @@ -1668,8 +1558,6 @@ int do_net_isr(int update_every, usec_t dt) { return 1; } - // -------------------------------------------------------------------- - if (likely(do_netisr)) { static RRDSET *st = NULL; static RRDDIM *rd_dispatched = NULL, *rd_hybrid_dispatched = NULL, *rd_qdrops = NULL, *rd_queued = NULL; @@ -1695,7 +1583,6 @@ int do_net_isr(int update_every, usec_t dt) { rd_qdrops = rrddim_add(st, "qdrops", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_queued = rrddim_add(st, "queued", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_dispatched, netisr_stats[number_of_cpus].dispatched); rrddim_set_by_pointer(st, rd_hybrid_dispatched, netisr_stats[number_of_cpus].hybrid_dispatched); @@ -1704,8 +1591,6 @@ int do_net_isr(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_netisr_per_core)) { static struct softnet_chart { char netisr_cpuid[MAX_INT_DIGITS + 17]; @@ -1752,7 +1637,6 @@ int do_net_isr(int update_every, usec_t dt) { all_softnet_charts[i].rd_queued = rrddim_add(all_softnet_charts[i].st, "queued", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(all_softnet_charts[i].st); rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_dispatched, netisr_stats[i].dispatched); @@ -1769,7 +1653,6 @@ int do_net_isr(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.inet.tcp.states int do_net_inet_tcp_states(int update_every, usec_t dt) { @@ -1783,9 +1666,6 @@ int do_net_inet_tcp_states(int update_every, usec_t dt) { error("DISABLED: net.inet.tcp.states module"); return 1; } else { - - // -------------------------------------------------------------------- - static RRDSET *st = NULL; static RRDDIM *rd = NULL; @@ -1806,8 +1686,7 @@ int do_net_inet_tcp_states(int update_every, usec_t dt) { ); rd = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd, tcps_states[TCPS_ESTABLISHED]); rrdset_done(st); @@ -1816,7 +1695,6 @@ int do_net_inet_tcp_states(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.inet.tcp.stats int do_net_inet_tcp_stats(int update_every, usec_t dt) { @@ -1866,9 +1744,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { error("DISABLED: net.inet.tcp.stats module"); return 1; } else { - - // -------------------------------------------------------------------- - if (likely(do_tcp_packets)) { static RRDSET *st = NULL; static RRDDIM *rd_in_segs = NULL, *rd_out_segs = NULL; @@ -1891,16 +1766,13 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rd_in_segs = rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_segs = rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_segs, tcpstat.tcps_rcvtotal); rrddim_set_by_pointer(st, rd_out_segs, tcpstat.tcps_sndtotal); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_tcp_errors)) { static RRDSET *st = NULL; static RRDDIM *rd_in_errs = NULL, *rd_in_csum_errs = NULL, *rd_retrans_segs = NULL; @@ -1926,8 +1798,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rd_in_errs = rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_csum_errs = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_retrans_segs = rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } #if __FreeBSD__ >= 11 rrddim_set_by_pointer(st, rd_in_errs, tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvreassfull + @@ -1940,8 +1811,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_tcp_handshake)) { static RRDSET *st = NULL; static RRDDIM *rd_estab_resets = NULL, *rd_active_opens = NULL, *rd_passive_opens = NULL, @@ -1969,8 +1838,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rd_active_opens = rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_passive_opens = rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_attempt_fails = rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_estab_resets, tcpstat.tcps_drops); rrddim_set_by_pointer(st, rd_active_opens, tcpstat.tcps_connattempt); @@ -1979,8 +1847,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || @@ -2016,7 +1882,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rd_on_timeout = rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_on_linger = rrddim_add(st, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_on_data, tcpstat.tcps_rcvpackafterwin); rrddim_set_by_pointer(st, rd_on_close, tcpstat.tcps_rcvafterclose); @@ -2026,8 +1891,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvoopack || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -2054,14 +1917,11 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rd_ofo_queue = rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_ofo_queue, tcpstat.tcps_rcvoopack); rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_tcpext_syncookies == CONFIG_BOOLEAN_YES || (do_tcpext_syncookies == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || @@ -2092,7 +1952,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rd_send = rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_failed = rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_recv, tcpstat.tcps_sc_recvcookie); rrddim_set_by_pointer(st, rd_send, tcpstat.tcps_sc_sendcookie); @@ -2100,8 +1959,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_listendrop || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -2129,16 +1986,11 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { 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); } - // -------------------------------------------------------------------- - if (do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_ecn_ce || tcpstat.tcps_ecn_ect0 || @@ -2172,7 +2024,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { rd_ect0 = rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_ect1 = rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_ce, tcpstat.tcps_ecn_ce); rrddim_set_by_pointer(st, rd_no_ect, tcpstat.tcps_ecn_ce - (tcpstat.tcps_ecn_ect0 + @@ -2191,7 +2042,6 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.inet.udp.stats int do_net_inet_udp_stats(int update_every, usec_t dt) { @@ -2216,9 +2066,6 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { error("DISABLED: net.inet.udp.stats module"); return 1; } else { - - // -------------------------------------------------------------------- - if (likely(do_udp_packets)) { static RRDSET *st = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; @@ -2241,16 +2088,13 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { rd_in = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, udpstat.udps_ipackets); rrddim_set_by_pointer(st, rd_out, udpstat.udps_opackets); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_udp_errors)) { static RRDSET *st = NULL; static RRDDIM *rd_in_errors = NULL, *rd_no_ports = NULL, *rd_recv_buf_errors = NULL, @@ -2279,8 +2123,7 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { rd_recv_buf_errors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_csum_errors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_ignored_multi = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_errors, udpstat.udps_hdrops + udpstat.udps_badlen); rrddim_set_by_pointer(st, rd_no_ports, udpstat.udps_noport); @@ -2298,7 +2141,6 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.inet.icmp.stats int do_net_inet_icmp_stats(int update_every, usec_t dt) { @@ -2337,8 +2179,6 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { } icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort; - // -------------------------------------------------------------------- - if (likely(do_icmp_packets)) { static RRDSET *st = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; @@ -2361,17 +2201,13 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { rd_in = rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, icmp_total.msgs_in); rrddim_set_by_pointer(st, rd_out, icmp_total.msgs_out); - rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_icmp_errors)) { static RRDSET *st = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_csum = NULL; @@ -2395,8 +2231,7 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { rd_in = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_csum = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort); @@ -2406,8 +2241,6 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_icmpmsg)) { static RRDSET *st = NULL; static RRDDIM *rd_in_reps = NULL, *rd_out_reps = NULL, *rd_in = NULL, *rd_out = NULL; @@ -2432,14 +2265,12 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { rd_out_reps = rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in = rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_reps, icmpstat.icps_inhist[ICMP_ECHOREPLY]); rrddim_set_by_pointer(st, rd_out_reps, icmpstat.icps_outhist[ICMP_ECHOREPLY]); rrddim_set_by_pointer(st, rd_in, icmpstat.icps_inhist[ICMP_ECHO]); rrddim_set_by_pointer(st, rd_out, icmpstat.icps_outhist[ICMP_ECHO]); - rrdset_done(st); } } @@ -2451,7 +2282,6 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.inet.ip.stats int do_net_inet_ip_stats(int update_every, usec_t dt) { @@ -2482,9 +2312,6 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { error("DISABLED: net.inet.ip.stats module"); return 1; } else { - - // -------------------------------------------------------------------- - if (likely(do_ip_packets)) { static RRDSET *st = NULL; static RRDDIM *rd_in_receives = NULL, *rd_out_requests = NULL, *rd_forward_datagrams = NULL, @@ -2510,8 +2337,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { rd_out_requests = rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_forward_datagrams = rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_delivers = rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_receives, ipstat.ips_total); rrddim_set_by_pointer(st, rd_out_requests, ipstat.ips_localout); @@ -2520,8 +2346,6 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_ip_fragsout)) { static RRDSET *st = NULL; static RRDDIM *rd_ok = NULL, *rd_fails = NULL, *rd_created = NULL; @@ -2547,8 +2371,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { rd_ok = rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_fails = rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_created = rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_ok, ipstat.ips_fragmented); rrddim_set_by_pointer(st, rd_fails, ipstat.ips_cantfrag); @@ -2556,8 +2379,6 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_ip_fragsin)) { static RRDSET *st = NULL; static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL; @@ -2583,8 +2404,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { 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_all = rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_ok, ipstat.ips_fragments); rrddim_set_by_pointer(st, rd_failed, ipstat.ips_fragdropped); @@ -2592,8 +2412,6 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_ip_errors)) { static RRDSET *st = NULL; static RRDDIM *rd_in_discards = NULL, *rd_out_discards = NULL, @@ -2624,8 +2442,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { rd_out_no_routes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_addr_errors = rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_unknown_protos = rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_discards, ipstat.ips_badsum + ipstat.ips_tooshort + ipstat.ips_toosmall + ipstat.ips_toolong); @@ -2646,7 +2463,6 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.inet6.ip6.stats int do_net_inet6_ip6_stats(int update_every, usec_t dt) { @@ -2680,9 +2496,6 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { error("DISABLED: net.inet6.ip6.stats module"); return 1; } else { - - // -------------------------------------------------------------------- - if (do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_localout || ip6stat.ip6s_total || @@ -2714,8 +2527,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { rd_sent = rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_forwarded = rrddim_add(st, "forwarded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_delivers = rrddim_add(st, "delivers", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_sent, ip6stat.ip6s_localout); rrddim_set_by_pointer(st, rd_received, ip6stat.ip6s_total); @@ -2724,8 +2536,6 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag || @@ -2757,8 +2567,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { rd_ok = rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_failed = rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_all = rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_ok, ip6stat.ip6s_fragmented); rrddim_set_by_pointer(st, rd_failed, ip6stat.ip6s_cantfrag); @@ -2766,8 +2575,6 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped || @@ -2801,8 +2608,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { rd_failed = rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_timeout = rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_all = rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_ok, ip6stat.ip6s_reassembled); rrddim_set_by_pointer(st, rd_failed, ip6stat.ip6s_fragdropped); @@ -2811,8 +2617,6 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_toosmall || ip6stat.ip6s_odropped || @@ -2856,8 +2660,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { rd_in_truncated_pkts = rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_no_routes = rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_no_routes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_discards, ip6stat.ip6s_toosmall); rrddim_set_by_pointer(st, rd_out_discards, ip6stat.ip6s_odropped); @@ -2878,7 +2681,6 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { return 0; } -// -------------------------------------------------------------------------------------------------------------------- // net.inet6.icmp6.stats int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { @@ -2966,17 +2768,13 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_sent = rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_received, icmp6_total.msgs_out); rrddim_set_by_pointer(st, rd_sent, icmp6_total.msgs_in); - rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT] || @@ -3004,16 +2802,13 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_sent = rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_received, icmp6stat.icp6s_outhist[ND_REDIRECT]); rrddim_set_by_pointer(st, rd_sent, icmp6stat.icp6s_inhist[ND_REDIRECT]); rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_badcode || icmp6stat.icp6s_badlen || @@ -3060,8 +2855,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rd_out_dest_unreachs = rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_time_excds = rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_parm_problems = rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_errors, icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort); @@ -3077,8 +2871,6 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] || icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] || @@ -3110,8 +2902,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rd_out = rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_replies = rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_replies = rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in, icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]); rrddim_set_by_pointer(st, rd_out, icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]); @@ -3120,8 +2911,6 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] || icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] || @@ -3154,8 +2943,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rd_out_solicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_advertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_solicits, icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]); rrddim_set_by_pointer(st, rd_out_solicits, icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]); @@ -3164,8 +2952,6 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] || icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] || @@ -3198,8 +2984,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rd_out_solicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_in_advertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_solicits, icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]); rrddim_set_by_pointer(st, rd_out_solicits, icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]); @@ -3208,8 +2993,6 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[1] || icmp6stat.icp6s_inhist[128] || @@ -3255,8 +3038,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { rd_out_133 = rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_135 = rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out_143 = rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set_by_pointer(st, rd_in_1, icmp6stat.icp6s_inhist[1]); rrddim_set_by_pointer(st, rd_in_128, icmp6stat.icp6s_inhist[128]); diff --git a/collectors/freebsd.plugin/plugin_freebsd.h b/collectors/freebsd.plugin/plugin_freebsd.h index 3a4ec13a7..af7d0822e 100644 --- a/collectors/freebsd.plugin/plugin_freebsd.h +++ b/collectors/freebsd.plugin/plugin_freebsd.h @@ -13,41 +13,41 @@ #define MAX_INT_DIGITS 10 // maximum number of digits for int -extern int freebsd_plugin_init(); - -extern int do_vm_loadavg(int update_every, usec_t dt); -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); -extern int do_vm_stats_sys_v_swtch(int update_every, usec_t dt); -extern int do_vm_stats_sys_v_forks(int update_every, usec_t dt); -extern int do_vm_swap_info(int update_every, usec_t dt); -extern int do_system_ram(int update_every, usec_t dt); -extern int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt); -extern int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt); -extern int do_kern_ipc_sem(int update_every, usec_t dt); -extern int do_kern_ipc_shm(int update_every, usec_t dt); -extern int do_kern_ipc_msq(int update_every, usec_t dt); -extern int do_uptime(int update_every, usec_t dt); -extern int do_net_isr(int update_every, usec_t dt); -extern int do_net_inet_tcp_states(int update_every, usec_t dt); -extern int do_net_inet_tcp_stats(int update_every, usec_t dt); -extern int do_net_inet_udp_stats(int update_every, usec_t dt); -extern int do_net_inet_icmp_stats(int update_every, usec_t dt); -extern int do_net_inet_ip_stats(int update_every, usec_t dt); -extern int do_net_inet6_ip6_stats(int update_every, usec_t dt); -extern int do_net_inet6_icmp6_stats(int update_every, usec_t dt); -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); +int freebsd_plugin_init(); + +int do_vm_loadavg(int update_every, usec_t dt); +int do_vm_vmtotal(int update_every, usec_t dt); +int do_kern_cp_time(int update_every, usec_t dt); +int do_kern_cp_times(int update_every, usec_t dt); +int do_dev_cpu_temperature(int update_every, usec_t dt); +int do_dev_cpu_0_freq(int update_every, usec_t dt); +int do_hw_intcnt(int update_every, usec_t dt); +int do_vm_stats_sys_v_intr(int update_every, usec_t dt); +int do_vm_stats_sys_v_soft(int update_every, usec_t dt); +int do_vm_stats_sys_v_swtch(int update_every, usec_t dt); +int do_vm_stats_sys_v_forks(int update_every, usec_t dt); +int do_vm_swap_info(int update_every, usec_t dt); +int do_system_ram(int update_every, usec_t dt); +int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt); +int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt); +int do_kern_ipc_sem(int update_every, usec_t dt); +int do_kern_ipc_shm(int update_every, usec_t dt); +int do_kern_ipc_msq(int update_every, usec_t dt); +int do_uptime(int update_every, usec_t dt); +int do_net_isr(int update_every, usec_t dt); +int do_net_inet_tcp_states(int update_every, usec_t dt); +int do_net_inet_tcp_stats(int update_every, usec_t dt); +int do_net_inet_udp_stats(int update_every, usec_t dt); +int do_net_inet_icmp_stats(int update_every, usec_t dt); +int do_net_inet_ip_stats(int update_every, usec_t dt); +int do_net_inet6_ip6_stats(int update_every, usec_t dt); +int do_net_inet6_icmp6_stats(int update_every, usec_t dt); +int do_getifaddrs(int update_every, usec_t dt); +int do_getmntinfo(int update_every, usec_t dt); +int do_kern_devstat(int update_every, usec_t dt); +int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt); +int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt); +int do_ipfw(int update_every, usec_t dt); // metrics that need to be shared among data collectors extern unsigned long long zfs_arcstats_shrinkable_cache_size_bytes; diff --git a/collectors/freeipmi.plugin/README.md b/collectors/freeipmi.plugin/README.md index 13958784e..ff13717d9 100644 --- a/collectors/freeipmi.plugin/README.md +++ b/collectors/freeipmi.plugin/README.md @@ -9,20 +9,30 @@ Netdata has a [freeipmi](https://www.gnu.org/software/freeipmi/) plugin. > FreeIPMI provides in-band and out-of-band IPMI software based on the IPMI v1.5/2.0 specification. The IPMI specification defines a set of interfaces for platform management and is implemented by a number vendors for system management. The features of IPMI that most users will be interested in are sensor monitoring, system event monitoring, power control, and serial-over-LAN (SOL). -## Compile `freeipmi.plugin` +## Installing the FreeIPMI plugin -1. install `libipmimonitoring-dev` or `libipmimonitoring-devel` (`freeipmi-devel` on RHEL based OS) using the package manager of your system. +When using our official DEB/RPM packages, the FreeIPMI plugin is included in a separate package named +`netdata-plugin-freeipmi` which needs to be manually installed using your system package manager. It is not +installed automatically due to the large number of dependencies it requires. -2. re-install Netdata from source. The installer will detect that the required libraries are now available and will also build `freeipmi.plugin`. +When using a static build of Netdata, the FreeIPMI plugin will be included and installed automatically, though +you will still need to have FreeIPMI installed on your system to be able to use the plugin. -> ❗ In some distributions `libipmimonitoring.pc` is located in an unregistered directory. -> In that case you should find the file and link it to the standard pkg-config directory. Usually, running -> `sudo ln -s /usr/lib/x86_64-linux-gnu/pkgconfig/libipmimonitoring.pc/libipmimonitoring.pc /usr/lib/pkgconfig/libipmimonitoring.pc` -> resolves the issue. +When using a local build of Netdata, you need to ensure that the FreeIPMI development packages (typically called `libipmimonitoring-dev`, `libipmimonitoring-devel`, or `freeipmi-devel`) are installed when building Netdata. -Keep in mind IPMI requires root access, so the plugin is setuid to root. +### Special Considerations -If you just installed the required IPMI tools, please run at least once the command `ipmimonitoring` and verify it returns sensors information. This command initialises IPMI configuration, so that the Netdata plugin will be able to work. +Accessing IPMI requires root access, so the FreeIPMI plugin is automatically installed setuid root. + +FreeIPMI does not work correctly on IBM POWER systems, thus Netdata’s FreeIPMI plugin is not usable on such systems. + +If you have not previously used IPMI on your system, you will probably need to run the `ipmimonitoring` command as root to initiailze IPMI settings so that the Netdata plugin works correctly. It should return information about available seensors on the system. + +In some distributions `libipmimonitoring.pc` is located in a non-standard directory, which +can cause building the plugin to fail when building Netdata from source. In that case you +should find the file and link it to the standard pkg-config directory. Usually, running `sudo ln -s +/usr/lib/$(uname -m)-linux-gnu/pkgconfig/libipmimonitoring.pc/libipmimonitoring.pc /usr/lib/pkgconfig/libipmimonitoring.pc` +resolves this issue. ## Netdata use @@ -190,5 +200,3 @@ If you need to disable IPMI for Netdata, edit `/etc/netdata/netdata.conf` and se [plugins] freeipmi = no ``` - - diff --git a/collectors/idlejitter.plugin/plugin_idlejitter.c b/collectors/idlejitter.plugin/plugin_idlejitter.c index 535819c69..b6339cc0f 100644 --- a/collectors/idlejitter.plugin/plugin_idlejitter.c +++ b/collectors/idlejitter.plugin/plugin_idlejitter.c @@ -47,18 +47,15 @@ void *cpuidlejitter_main(void *ptr) { usec_t update_every_ut = localhost->rrd_update_every * USEC_PER_SEC; struct timeval before, after; - unsigned long long counter; - for(counter = 0; 1 ;counter++) { + while (!netdata_exit) { int iterations = 0; usec_t error_total = 0, error_min = 0, error_max = 0, elapsed = 0; - if(netdata_exit) break; - - while(elapsed < update_every_ut) { + while (elapsed < update_every_ut) { now_monotonic_high_precision_timeval(&before); worker_is_idle(); sleep_usec(sleep_ut); @@ -82,10 +79,7 @@ void *cpuidlejitter_main(void *ptr) { iterations++; } - if(netdata_exit) break; - if(iterations) { - if (likely(counter)) rrdset_next(st); rrddim_set_by_pointer(st, rd_min, error_min); rrddim_set_by_pointer(st, rd_max, error_max); rrddim_set_by_pointer(st, rd_avg, error_total / iterations); diff --git a/collectors/macos.plugin/macos_fw.c b/collectors/macos.plugin/macos_fw.c index 08d1ddadd..07f7d773d 100644 --- a/collectors/macos.plugin/macos_fw.c +++ b/collectors/macos.plugin/macos_fw.c @@ -168,14 +168,11 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); prev_diskstat.bytes_read = rrddim_set(st, "reads", diskstat.bytes_read); prev_diskstat.bytes_write = rrddim_set(st, "writes", diskstat.bytes_write); rrdset_done(st); - // -------------------------------------------------------------------- - /* Get number of reads. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.reads); @@ -207,14 +204,11 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); prev_diskstat.operations_read = rrddim_set(st, "reads", diskstat.reads); prev_diskstat.operations_write = rrddim_set(st, "writes", diskstat.writes); rrdset_done(st); - // -------------------------------------------------------------------- - /* Get reads time. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_read); @@ -245,14 +239,11 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "utilization", NULL, 1, 10000000, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); cur_diskstat.busy_time_ns = (diskstat.time_read + diskstat.time_write); prev_diskstat.busy_time_ns = rrddim_set(st, "utilization", cur_diskstat.busy_time_ns); rrdset_done(st); - // -------------------------------------------------------------------- - /* Get reads latency. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_read); @@ -284,7 +275,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); cur_diskstat.duration_read_ns = diskstat.time_read + diskstat.latency_read; cur_diskstat.duration_write_ns = diskstat.time_write + diskstat.latency_write; @@ -292,14 +282,10 @@ int do_macos_iokit(int update_every, usec_t dt) { prev_diskstat.duration_write_ns = rrddim_set(st, "writes", cur_diskstat.duration_write_ns); rrdset_done(st); - // -------------------------------------------------------------------- // calculate differential charts // only if this is not the first time we run if (likely(dt)) { - - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("disk_await", diskstat.name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -321,7 +307,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ? (cur_diskstat.duration_read_ns - prev_diskstat.duration_read_ns) / (diskstat.reads - prev_diskstat.operations_read) : 0); @@ -329,8 +314,6 @@ int do_macos_iokit(int update_every, usec_t dt) { (cur_diskstat.duration_write_ns - prev_diskstat.duration_write_ns) / (diskstat.writes - prev_diskstat.operations_write) : 0); rrdset_done(st); - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("disk_avgsz", diskstat.name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -352,7 +335,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ? (diskstat.bytes_read - prev_diskstat.bytes_read) / (diskstat.reads - prev_diskstat.operations_read) : 0); @@ -360,8 +342,6 @@ int do_macos_iokit(int update_every, usec_t dt) { (diskstat.bytes_write - prev_diskstat.bytes_write) / (diskstat.writes - prev_diskstat.operations_write) : 0); rrdset_done(st); - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("disk_svctm", diskstat.name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -382,7 +362,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "svctm", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set(st, "svctm", ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) ? (cur_diskstat.busy_time_ns - prev_diskstat.busy_time_ns) / ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) : 0); @@ -423,7 +402,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "in", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "out", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "in", total_disk_reads); rrddim_set(st, "out", total_disk_writes); @@ -431,7 +409,6 @@ int do_macos_iokit(int update_every, usec_t dt) { } // Can be merged with FreeBSD plugin - // -------------------------------------------------------------------------- if (likely(do_space || do_inodes)) { // there is no mount info in sysctl MIBs @@ -477,8 +454,7 @@ int do_macos_iokit(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "avail", (collected_number) mntbuf[i].f_bavail); rrddim_set(st, "used", (collected_number) (mntbuf[i].f_blocks - mntbuf[i].f_bfree)); @@ -510,8 +486,7 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(st); + } rrddim_set(st, "avail", (collected_number) mntbuf[i].f_ffree); rrddim_set(st, "used", (collected_number) (mntbuf[i].f_files - mntbuf[i].f_ffree)); @@ -522,7 +497,6 @@ int do_macos_iokit(int update_every, usec_t dt) { } // Can be merged with FreeBSD plugin - // -------------------------------------------------------------------- if (likely(do_bandwidth)) { if (unlikely(getifaddrs(&ifap))) { @@ -534,8 +508,6 @@ int do_macos_iokit(int update_every, usec_t dt) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("net", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -556,14 +528,11 @@ int do_macos_iokit(int update_every, usec_t dt) { 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); } - else rrdset_next(st); rrddim_set(st, "received", IFA_DATA(ibytes)); rrddim_set(st, "sent", IFA_DATA(obytes)); rrdset_done(st); - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("net_packets", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -587,7 +556,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "received", IFA_DATA(ipackets)); rrddim_set(st, "sent", IFA_DATA(opackets)); @@ -595,8 +563,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_set(st, "multicast_sent", IFA_DATA(omcasts)); rrdset_done(st); - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("net_errors", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -618,14 +584,11 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "inbound", IFA_DATA(ierrors)); rrddim_set(st, "outbound", IFA_DATA(oerrors)); rrdset_done(st); - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("net_drops", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -646,13 +609,10 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "inbound", IFA_DATA(iqdrops)); rrdset_done(st); - // -------------------------------------------------------------------- - st = rrdset_find_active_bytype_localhost("net_events", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -675,7 +635,6 @@ int do_macos_iokit(int update_every, usec_t dt) { rrddim_add(st, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "collisions", IFA_DATA(collisions)); rrdset_done(st); @@ -685,6 +644,5 @@ int do_macos_iokit(int update_every, usec_t dt) { } } - return 0; } diff --git a/collectors/macos.plugin/macos_mach_smi.c b/collectors/macos.plugin/macos_mach_smi.c index f2c4623c9..53b2607b4 100644 --- a/collectors/macos.plugin/macos_mach_smi.c +++ b/collectors/macos.plugin/macos_mach_smi.c @@ -39,8 +39,6 @@ int do_macos_mach_smi(int update_every, usec_t dt) { if (unlikely(kr != KERN_SUCCESS)) return -1; - // -------------------------------------------------------------------- - if (likely(do_cpu)) { if (unlikely(HOST_CPU_LOAD_INFO_COUNT != 4)) { error("MACOS: There are %d CPU states (4 was expected)", HOST_CPU_LOAD_INFO_COUNT); @@ -78,7 +76,6 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(st, "idle"); } - else rrdset_next(st); rrddim_set(st, "user", cp_time[CPU_STATE_USER]); rrddim_set(st, "nice", cp_time[CPU_STATE_NICE]); @@ -87,9 +84,7 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrdset_done(st); } } - } - - // -------------------------------------------------------------------- + } if (likely(do_ram || do_swapio || do_pgfaults)) { #if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) @@ -137,7 +132,6 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrddim_add(st, "speculative", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "free", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set(st, "active", vm_statistics.active_count); rrddim_set(st, "wired", vm_statistics.wire_count); @@ -153,8 +147,6 @@ int do_macos_mach_smi(int update_every, usec_t dt) { } #if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) - // -------------------------------------------------------------------- - if (likely(do_swapio)) { st = rrdset_find_active_localhost("system.swapio"); if (unlikely(!st)) { @@ -176,7 +168,6 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrddim_add(st, "in", NULL, system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "in", vm_statistics.swapins); rrddim_set(st, "out", vm_statistics.swapouts); @@ -184,8 +175,6 @@ int do_macos_mach_smi(int update_every, usec_t dt) { } #endif - // -------------------------------------------------------------------- - if (likely(do_pgfaults)) { st = rrdset_find_active_localhost("mem.pgfaults"); if (unlikely(!st)) { @@ -217,7 +206,6 @@ int do_macos_mach_smi(int update_every, usec_t dt) { rrddim_add(st, "reactivate", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "purge", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "memory", vm_statistics.faults); rrddim_set(st, "cow", vm_statistics.cow_faults); @@ -235,7 +223,5 @@ int do_macos_mach_smi(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - return 0; } diff --git a/collectors/macos.plugin/macos_sysctl.c b/collectors/macos.plugin/macos_sysctl.c index 34d3f0b3e..1f04f6e41 100644 --- a/collectors/macos.plugin/macos_sysctl.c +++ b/collectors/macos.plugin/macos_sysctl.c @@ -218,8 +218,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { // NEEDED BY: do_uptime struct timespec boot_time, cur_time; - // -------------------------------------------------------------------- - if (next_loadavg_dt <= dt) { if (likely(do_loadavg)) { if (unlikely(GETSYSCTL_BY_NAME("vm.loadavg", sysload))) { @@ -247,7 +245,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set(st, "load1", (collected_number) ((double)sysload.ldavg[0] / sysload.fscale * 1000)); rrddim_set(st, "load5", (collected_number) ((double)sysload.ldavg[1] / sysload.fscale * 1000)); @@ -260,8 +257,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } else next_loadavg_dt -= dt; - // -------------------------------------------------------------------- - if (likely(do_swap)) { if (unlikely(GETSYSCTL_BY_NAME("vm.swapusage", swap_usage))) { do_swap = 0; @@ -288,7 +283,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "free", NULL, 1, 1048576, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1048576, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set(st, "free", swap_usage.xsu_avail); rrddim_set(st, "used", swap_usage.xsu_used); @@ -296,8 +290,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if (likely(do_bandwidth)) { mib[0] = CTL_NET; mib[1] = PF_ROUTE; @@ -349,7 +341,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); } - else rrdset_next(st); rrddim_set(st, "InOctets", iftot.ift_ibytes); rrddim_set(st, "OutOctets", iftot.ift_obytes); @@ -358,8 +349,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - // 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_syscookies || do_ecn)) { if (unlikely(GETSYSCTL_BY_NAME("net.inet.tcp.stats", tcpstat))){ @@ -398,16 +387,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set(st, "InSegs", tcpstat.tcps_rcvtotal); rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_tcp_errors)) { st = rrdset_find_active_localhost("ipv4.tcperrors"); if (unlikely(!st)) { @@ -430,8 +416,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "InErrs", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort); rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum); @@ -439,8 +424,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_tcp_handshake)) { st = rrdset_find_active_localhost("ipv4.tcphandshake"); if (unlikely(!st)) { @@ -464,8 +447,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "EstabResets", tcpstat.tcps_drops); rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt); @@ -474,8 +456,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || @@ -505,7 +485,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "TCPAbortOnData", tcpstat.tcps_rcvpackafterwin); rrddim_set(st, "TCPAbortOnClose", tcpstat.tcps_rcvafterclose); @@ -514,8 +493,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvoopack || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -539,14 +516,11 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "TCPOFOQueue", tcpstat.tcps_rcvoopack); rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || @@ -575,7 +549,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "SyncookiesRecv", tcpstat.tcps_sc_recvcookie); rrddim_set(st, "SyncookiesSent", tcpstat.tcps_sc_sendcookie); @@ -583,9 +556,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - - #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 || @@ -613,7 +583,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_recv_ce); rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported); @@ -624,8 +593,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - // see http://net-snmp.sourceforge.net/docs/mibs/udp.html if (likely(do_udp_packets || do_udp_errors)) { if (unlikely(GETSYSCTL_BY_NAME("net.inet.udp.stats", udpstat))) { @@ -654,16 +621,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set(st, "InDatagrams", udpstat.udps_ipackets); rrddim_set(st, "OutDatagrams", udpstat.udps_opackets); rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_udp_errors)) { st = rrdset_find_active_localhost("ipv4.udperrors"); if (unlikely(!st)) { @@ -690,8 +654,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { #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); @@ -707,8 +670,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if (likely(do_icmp_packets || do_icmpmsg)) { if (unlikely(GETSYSCTL_BY_NAME("net.inet.icmp.stats", icmpstat))) { do_icmp_packets = 0; @@ -745,16 +706,12 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set(st, "InMsgs", icmp_total.msgs_in); rrddim_set(st, "OutMsgs", icmp_total.msgs_out); - rrdset_done(st); - // -------------------------------------------------------------------- - st = rrdset_find_active_localhost("ipv4.icmp_errors"); if (unlikely(!st)) { st = rrdset_create_localhost( @@ -775,18 +732,14 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "InErrors", icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort); rrddim_set(st, "OutErrors", icmpstat.icps_error); rrddim_set(st, "InCsumErrors", icmpstat.icps_checksum); - rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_icmpmsg)) { st = rrdset_find_active_localhost("ipv4.icmpmsg"); if (unlikely(!st)) { @@ -809,21 +762,17 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); - - rrddim_set(st, "InEchoReps", icmpstat.icps_inhist[ICMP_ECHOREPLY]); - rrddim_set(st, "OutEchoReps", icmpstat.icps_outhist[ICMP_ECHOREPLY]); - rrddim_set(st, "InEchos", icmpstat.icps_inhist[ICMP_ECHO]); - rrddim_set(st, "OutEchos", icmpstat.icps_outhist[ICMP_ECHO]); + } + rrddim_set(st, "InEchoReps", icmpstat.icps_inhist[ICMP_ECHOREPLY]); + rrddim_set(st, "OutEchoReps", icmpstat.icps_outhist[ICMP_ECHOREPLY]); + rrddim_set(st, "InEchos", icmpstat.icps_inhist[ICMP_ECHO]); + rrddim_set(st, "OutEchos", icmpstat.icps_outhist[ICMP_ECHO]); rrdset_done(st); } } } - // -------------------------------------------------------------------- - // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html if (likely(do_ip_packets || do_ip_fragsout || do_ip_fragsin || do_ip_errors)) { if (unlikely(GETSYSCTL_BY_NAME("net.inet.ip.stats", ipstat))) { @@ -858,8 +807,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "OutRequests", ipstat.ips_localout); rrddim_set(st, "InReceives", ipstat.ips_total); @@ -868,8 +816,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_ip_fragsout)) { st = rrdset_find_active_localhost("ipv4.fragsout"); if (unlikely(!st)) { @@ -892,8 +838,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "FragOKs", ipstat.ips_fragmented); rrddim_set(st, "FragFails", ipstat.ips_cantfrag); @@ -901,8 +846,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_ip_fragsin)) { st = rrdset_find_active_localhost("ipv4.fragsin"); if (unlikely(!st)) { @@ -925,8 +868,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "ReasmOKs", ipstat.ips_fragments); rrddim_set(st, "ReasmFails", ipstat.ips_fragdropped); @@ -934,8 +876,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (likely(do_ip_errors)) { st = rrdset_find_active_localhost("ipv4.errors"); if (unlikely(!st)) { @@ -963,8 +903,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set(st, "InDiscards", ipstat.ips_badsum + ipstat.ips_tooshort + ipstat.ips_toosmall + ipstat.ips_toolong); rrddim_set(st, "OutDiscards", ipstat.ips_odropped); @@ -977,8 +916,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if (likely(do_ip6_packets || do_ip6_fragsout || do_ip6_fragsin || do_ip6_errors)) { if (unlikely(GETSYSCTL_BY_NAME("net.inet6.ip6.stats", ip6stat))) { do_ip6_packets = 0; @@ -1018,8 +955,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "sent", ip6stat.ip6s_localout); rrddim_set(st, "received", ip6stat.ip6s_total); @@ -1028,8 +964,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag || @@ -1057,8 +991,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "ok", ip6stat.ip6s_fragmented); rrddim_set(st, "failed", ip6stat.ip6s_cantfrag); @@ -1066,8 +999,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped || @@ -1097,8 +1028,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "ok", ip6stat.ip6s_reassembled); rrddim_set(st, "failed", ip6stat.ip6s_fragdropped); @@ -1107,8 +1037,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_toosmall || ip6stat.ip6s_odropped || @@ -1148,8 +1076,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set(st, "InDiscards", ip6stat.ip6s_toosmall); rrddim_set(st, "OutDiscards", ip6stat.ip6s_odropped); @@ -1166,8 +1093,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if (likely(do_icmp6 || do_icmp6_redir || do_icmp6_errors || do_icmp6_echos || do_icmp6_router || do_icmp6_neighbor || do_icmp6_types)) { if (unlikely(GETSYSCTL_BY_NAME("net.inet6.icmp6.stats", icmp6stat))) { do_icmp6 = 0; @@ -1202,16 +1127,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set(st, "sent", icmp6_total.msgs_in); rrddim_set(st, "received", icmp6_total.msgs_out); rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT] || @@ -1236,16 +1158,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - } else - rrdset_next(st); + } rrddim_set(st, "sent", icmp6stat.icp6s_inhist[ND_REDIRECT]); rrddim_set(st, "received", icmp6stat.icp6s_outhist[ND_REDIRECT]); rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_badcode || icmp6stat.icp6s_badlen || @@ -1288,8 +1207,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrddim_add(st, "OutDestUnreachs", 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); - } else - rrdset_next(st); + } rrddim_set(st, "InErrors", icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort); rrddim_set(st, "OutErrors", icmp6stat.icp6s_error); @@ -1304,8 +1222,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] || icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] || @@ -1334,8 +1250,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "InEchos", icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]); rrddim_set(st, "OutEchos", icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]); @@ -1344,8 +1259,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] || icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] || @@ -1374,8 +1287,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]); rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]); @@ -1384,8 +1296,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] || icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] || @@ -1414,18 +1324,14 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]); rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]); rrddim_set(st, "InAdvertisements", icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT]); rrddim_set(st, "OutAdvertisements", icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]); - rrdset_done(st); } - // -------------------------------------------------------------------- - if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[1] || icmp6stat.icp6s_inhist[128] || @@ -1466,8 +1372,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { 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); - } else - rrdset_next(st); + } rrddim_set(st, "InType1", icmp6stat.icp6s_inhist[1]); rrddim_set(st, "InType128", icmp6stat.icp6s_inhist[128]); @@ -1484,8 +1389,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if (likely(do_uptime)) { if (unlikely(GETSYSCTL_BY_NAME("kern.boottime", boot_time))) { do_uptime = 0; @@ -1511,7 +1414,6 @@ int do_macos_sysctl(int update_every, usec_t dt) { ); rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set(st, "uptime", cur_time.tv_sec - boot_time.tv_sec); rrdset_done(st); @@ -1520,4 +1422,3 @@ int do_macos_sysctl(int update_every, usec_t dt) { return 0; } - diff --git a/collectors/macos.plugin/plugin_macos.h b/collectors/macos.plugin/plugin_macos.h index b4c2cf542..2c673a224 100644 --- a/collectors/macos.plugin/plugin_macos.h +++ b/collectors/macos.plugin/plugin_macos.h @@ -5,8 +5,8 @@ #include "daemon/common.h" -extern int do_macos_sysctl(int update_every, usec_t dt); -extern int do_macos_mach_smi(int update_every, usec_t dt); -extern int do_macos_iokit(int update_every, usec_t dt); +int do_macos_sysctl(int update_every, usec_t dt); +int do_macos_mach_smi(int update_every, usec_t dt); +int do_macos_iokit(int update_every, usec_t dt); #endif /* NETDATA_PLUGIN_MACOS_H */ diff --git a/collectors/plugins.d/README.md b/collectors/plugins.d/README.md index 0741636b9..2ecf233f7 100644 --- a/collectors/plugins.d/README.md +++ b/collectors/plugins.d/README.md @@ -116,17 +116,19 @@ For example, if your plugin wants to monitor `squid`, you can search for it on p Any program that can print a few values to its standard output can become a Netdata external plugin. -Netdata parses 9 lines starting with: +Netdata parses lines starting with: - `CHART` - create or update a chart - `DIMENSION` - add or update a dimension to the chart just created +- `VARIABLE` - define a variable (to be used in health calculations) +- `CLABEL` - add a label to a chart +- `CLABEL_COMMIT` - commit added labels to the chart +- `FUNCTION` - define a function that can be called later to execute it - `BEGIN` - initialize data collection for a chart - `SET` - set the value of a dimension for the initialized chart - `END` - complete data collection for the initialized chart - `FLUSH` - ignore the last collected values - `DISABLE` - disable this plugin -- `CLABEL` - add a label to a chart -- `CLABEL_COMMIT` - commit added labels to the chart. a single program can produce any number of charts with any number of dimensions each. @@ -362,6 +364,80 @@ The `source` is an integer field that can have the following values: `CLABEL_COMMIT` indicates that all labels were defined and the chart can be updated. +#### FUNCTION + +> FUNCTION [GLOBAL] "name and parameters of the function" timeout "help string for users" + +A function can be used by users to ask for more information from the collector. Netdata maintains a registry of functions in 2 levels: + +- per node +- per chart + +Both node and chart functions are exactly the same, but chart functions allow Netdata to relate functions with charts and therefore present a context sensitive menu of functions related to the chart the user is using. + +A function is identified by a string. The allowed characters in the function definition are: + +| Character | Symbol | In Functions | +|-------------------|:------:|:------------:| +| UTF-8 character | UTF-8 | keep | +| Lower case letter | [a-z] | keep | +| Upper case letter | [A-Z] | keep | +| Digit | [0-9] | keep | +| Underscore | _ | keep | +| Comma | , | keep | +| Minus | - | keep | +| Period | . | keep | +| Colon | : | keep | +| Slash | / | keep | +| Space | ' ' | keep | +| Semicolon | ; | : | +| Equal | = | : | +| Backslash | \ | / | +| Anything else | | _ | + +Uses can get a list of all the registered functions using the `/api/v1/functions` end point of Netdata. + +Users can call functions using the `/api/v1/function` end point of Netdata. +Once a function is called, the plugin will receive at its standard input a command that looks like this: + +> FUNCTION transaction_id timeout "name and parameters of the function" + +The plugin is expected to parse and validate `name and parameters of the function`. Netdata allows users to edit this string, append more parameters or even change the ones the plugin originally exposed. To minimize the security risk, Netdata guarantees that only the characters shown above are accepted in function definitions, but still the plugin should carefully inspect the `name and parameters of the function` to ensure that it is valid and not harmful. + +If the plugin rejects the request, it should respond with this: + +``` +FUNCTION_RESULT_BEGIN transaction_id 400 application/json +{ + "status": 400, + "error_message": "description of the rejection reasons" +} +FUNCTION_RESULT_END +``` + +If the plugin prepares a response, it should send (via its standard output, together with the collected data, but not interleaved with them): + +> FUNCTION_RESULT_BEGIN transaction_id http_error_code content_type expiration + +Where: + + - `transaction_id` is the transaction id that Netdata sent for this function execution + - `http_error` is the http error code Netdata should respond with, 200 is the "ok" response + - `content_type` is the content type of the response + - `expiration` is the absolute timestamp (number, unix epoch) this response expires + +Immediately after this, all text is assumed to be the response content. +The content is text and line oriented. The maximum line length accepted is 15kb. Longer lines will be truncated. +The type of the context itself depends on the plugin and the UI. + +To terminate the message, Netdata seeks a line with just this: + +> FUNCTION_RESULT_END + +This defines the end of the message. `FUNCTION_RESULT_END` should appear in a line alone, without any other text, so it is wise to add `\n` before and after it. + +After this line, Netdata resumes processing collected metrics from the plugin. + ## Data collection data collection is defined as a series of `BEGIN` -> `SET` -> `END` lines @@ -463,7 +539,7 @@ There are a few rules for writing plugins properly: readConfiguration(); if(!verifyWeCanCollectValues()) { - print "DISABLE"; + print("DISABLE"); exit(1); } @@ -475,7 +551,7 @@ There are a few rules for writing plugins properly: var dt_since_last_run = 0; var now = 0; - FOREVER { + while(true) { /* find the current time in milliseconds */ now = currentTimeStampInMilliseconds(); diff --git a/collectors/plugins.d/plugins_d.c b/collectors/plugins.d/plugins_d.c index 377ec1401..79abc7070 100644 --- a/collectors/plugins.d/plugins_d.c +++ b/collectors/plugins.d/plugins_d.c @@ -6,118 +6,7 @@ char *plugin_directories[PLUGINSD_MAX_DIRECTORIES] = { NULL }; struct plugind *pluginsd_root = NULL; -inline int pluginsd_space(char c) { - switch(c) { - case ' ': - case '\t': - case '\r': - case '\n': - case '=': - return 1; - - default: - return 0; - } -} - -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 quoted_strings_splitter(char *str, char **words, int max_words, int (*custom_isspace)(char), char *recover_input, char **recover_location, int max_recover) -{ - char *s = str, quote = 0; - int i = 0, rec = 0; - char *recover = recover_input; - - // skip all white space - while (unlikely(custom_isspace(*s))) - s++; - - // check for quote - if (unlikely(*s == '\'' || *s == '"')) { - quote = *s; // remember the quote - s++; // skip the quote - } - - // store the first word - words[i++] = s; - - // while we have something - while (likely(*s)) { - // if it is escape - if (unlikely(*s == '\\' && s[1])) { - s += 2; - continue; - } - - // if it is quote - else if (unlikely(*s == quote)) { - quote = 0; - if (recover && rec < max_recover) { - recover_location[rec++] = s; - *recover++ = *s; - } - *s = ' '; - continue; - } - - // if it is a space - else if (unlikely(quote == 0 && custom_isspace(*s))) { - // terminate the word - if (recover && rec < max_recover) { - if (!rec || (rec && recover_location[rec-1] != s)) { - recover_location[rec++] = s; - *recover++ = *s; - } - } - *s++ = '\0'; - - // skip all white space - while (likely(custom_isspace(*s))) - s++; - - // check for quote - if (unlikely(*s == '\'' || *s == '"')) { - quote = *s; // remember the quote - s++; // skip the quote - } - - // if we reached the end, stop - if (unlikely(!*s)) - break; - - // store the next word - if (likely(i < max_words)) - words[i++] = s; - else - break; - } - - // anything else - else - s++; - } - - // terminate the words - memset(&words[i], 0, (max_words - i) * sizeof (char *)); - - return i; -} - -inline int pluginsd_initialize_plugin_directories() +inline size_t pluginsd_initialize_plugin_directories() { char plugins_dirs[(FILENAME_MAX * 2) + 1]; static char *plugins_dir_list = NULL; @@ -132,12 +21,6 @@ inline int pluginsd_initialize_plugin_directories() return quoted_strings_splitter(plugins_dir_list, plugin_directories, PLUGINSD_MAX_DIRECTORIES, config_isspace, NULL, NULL, 0); } -inline int pluginsd_split_words(char *str, char **words, int max_words, char *recover_input, char **recover_location, int max_recover) -{ - return quoted_strings_splitter(str, words, max_words, pluginsd_space, recover_input, recover_location, max_recover); -} - - static void pluginsd_worker_thread_cleanup(void *arg) { struct plugind *cd = (struct plugind *)arg; @@ -238,18 +121,19 @@ void *pluginsd_worker_thread(void *arg) size_t count = 0; while (!netdata_exit) { - FILE *fp = mypopen(cd->cmd, &cd->pid); - if (unlikely(!fp)) { + FILE *fp_child_input = NULL; + FILE *fp_child_output = netdata_popen(cd->cmd, &cd->pid, &fp_child_input); + if (unlikely(!fp_child_input || !fp_child_output)) { error("Cannot popen(\"%s\", \"r\").", cd->cmd); break; } info("connected to '%s' running on pid %d", cd->fullfilename, cd->pid); - count = pluginsd_process(localhost, cd, fp, 0); + count = pluginsd_process(localhost, cd, fp_child_input, fp_child_output, 0); error("'%s' (pid %d) disconnected after %zu successful data collections (ENDs).", cd->fullfilename, cd->pid, count); killpid(cd->pid); - int worker_ret_code = mypclose(fp, cd->pid); + int worker_ret_code = netdata_pclose(fp_child_input, fp_child_output, cd->pid); if (likely(worker_ret_code == 0)) pluginsd_worker_thread_handle_success(cd); diff --git a/collectors/plugins.d/plugins_d.h b/collectors/plugins.d/plugins_d.h index e0b8ac570..a8acf038a 100644 --- a/collectors/plugins.d/plugins_d.h +++ b/collectors/plugins.d/plugins_d.h @@ -10,23 +10,34 @@ #define PLUGINSD_CMD_MAX (FILENAME_MAX*2) #define PLUGINSD_STOCK_PLUGINS_DIRECTORY_PATH 0 -#define PLUGINSD_KEYWORD_CHART "CHART" -#define PLUGINSD_KEYWORD_DIMENSION "DIMENSION" -#define PLUGINSD_KEYWORD_BEGIN "BEGIN" -#define PLUGINSD_KEYWORD_END "END" -#define PLUGINSD_KEYWORD_FLUSH "FLUSH" -#define PLUGINSD_KEYWORD_DISABLE "DISABLE" -#define PLUGINSD_KEYWORD_VARIABLE "VARIABLE" -#define PLUGINSD_KEYWORD_LABEL "LABEL" -#define PLUGINSD_KEYWORD_OVERWRITE "OVERWRITE" -#define PLUGINSD_KEYWORD_GUID "GUID" -#define PLUGINSD_KEYWORD_CONTEXT "CONTEXT" -#define PLUGINSD_KEYWORD_TOMBSTONE "TOMBSTONE" -#define PLUGINSD_KEYWORD_HOST "HOST" - - -#define PLUGINSD_LINE_MAX 1024 +#define PLUGINSD_KEYWORD_CHART "CHART" +#define PLUGINSD_KEYWORD_CHART_DEFINITION_END "CHART_DEFINITION_END" +#define PLUGINSD_KEYWORD_DIMENSION "DIMENSION" +#define PLUGINSD_KEYWORD_BEGIN "BEGIN" +#define PLUGINSD_KEYWORD_SET "SET" +#define PLUGINSD_KEYWORD_END "END" +#define PLUGINSD_KEYWORD_FLUSH "FLUSH" +#define PLUGINSD_KEYWORD_DISABLE "DISABLE" +#define PLUGINSD_KEYWORD_VARIABLE "VARIABLE" +#define PLUGINSD_KEYWORD_LABEL "LABEL" +#define PLUGINSD_KEYWORD_OVERWRITE "OVERWRITE" +#define PLUGINSD_KEYWORD_CLABEL "CLABEL" +#define PLUGINSD_KEYWORD_CLABEL_COMMIT "CLABEL_COMMIT" +#define PLUGINSD_KEYWORD_FUNCTION "FUNCTION" +#define PLUGINSD_KEYWORD_FUNCTION_RESULT_BEGIN "FUNCTION_RESULT_BEGIN" +#define PLUGINSD_KEYWORD_FUNCTION_RESULT_END "FUNCTION_RESULT_END" + +#define PLUGINSD_KEYWORD_REPLAY_CHART "REPLAY_CHART" +#define PLUGINSD_KEYWORD_REPLAY_BEGIN "RBEGIN" +#define PLUGINSD_KEYWORD_REPLAY_SET "RSET" +#define PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE "RDSTATE" +#define PLUGINSD_KEYWORD_REPLAY_RRDSET_STATE "RSSTATE" +#define PLUGINSD_KEYWORD_REPLAY_END "REND" + +#define PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT 10 // seconds + #define PLUGINSD_LINE_MAX_SSL_READ 512 + #define PLUGINSD_MAX_WORDS 20 #define PLUGINSD_MAX_DIRECTORIES 20 @@ -53,19 +64,40 @@ struct plugind { volatile sig_atomic_t enabled; // if this is enabled or not time_t started_t; - uint32_t version; + uint32_t capabilities; // follows the same principles as streaming capabilities struct plugind *next; }; extern struct plugind *pluginsd_root; -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, char *recover_string, char **recover_location, int max_recover); +size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp_plugin_input, FILE *fp_plugin_output, int trust_durations); + +size_t pluginsd_initialize_plugin_directories(); + + + +#define pluginsd_function_result_begin_to_buffer(wb, transaction, code, content_type, expires) \ + buffer_sprintf(wb \ + , PLUGINSD_KEYWORD_FUNCTION_RESULT_BEGIN " \"%s\" %d \"%s\" %ld\n" \ + , (transaction) ? (transaction) : "" \ + , (int)(code) \ + , (content_type) ? (content_type) : "" \ + , (long int)(expires) \ + ) + +#define pluginsd_function_result_end_to_buffer(wb) \ + buffer_strcat(wb, "\n" PLUGINSD_KEYWORD_FUNCTION_RESULT_END "\n") -extern int pluginsd_initialize_plugin_directories(); +#define pluginsd_function_result_begin_to_stdout(transaction, code, content_type, expires) \ + fprintf(stdout \ + , PLUGINSD_KEYWORD_FUNCTION_RESULT_BEGIN " \"%s\" %d \"%s\" %ld\n" \ + , (transaction) ? (transaction) : "" \ + , (int)(code) \ + , (content_type) ? (content_type) : "" \ + , (long int)(expires) \ + ) -extern int config_isspace(char c); -extern int pluginsd_space(char c); -int quoted_strings_splitter(char *str, char **words, int max_words, int (*custom_isspace)(char), char *recover_input, char **recover_location, int max_recover); +#define pluginsd_function_result_end_to_stdout() \ + fprintf(stdout, "\n" PLUGINSD_KEYWORD_FUNCTION_RESULT_END "\n") #endif /* NETDATA_PLUGINS_D_H */ diff --git a/collectors/plugins.d/pluginsd_parser.c b/collectors/plugins.d/pluginsd_parser.c index 88e07fab7..5501c12fa 100644 --- a/collectors/plugins.d/pluginsd_parser.c +++ b/collectors/plugins.d/pluginsd_parser.c @@ -2,336 +2,223 @@ #include "pluginsd_parser.h" -/* - * This is the action defined for the FLUSH command - */ -PARSER_RC pluginsd_set_action(void *user, RRDSET *st, RRDDIM *rd, long long int value) -{ - UNUSED(user); - - rrddim_set_by_pointer(st, rd, value); - return PARSER_RC_OK; -} +#define LOG_FUNCTIONS false -PARSER_RC pluginsd_flush_action(void *user, RRDSET *st) -{ - UNUSED(user); - UNUSED(st); - return PARSER_RC_OK; -} +static int send_to_plugin(const char *txt, void *data) { + PARSER *parser = data; -PARSER_RC pluginsd_begin_action(void *user, RRDSET *st, usec_t microseconds, int trust_durations) -{ - UNUSED(user); - if (likely(st->counter_done)) { - if (likely(microseconds)) { - if (trust_durations) - rrdset_next_usec_unfiltered(st, microseconds); - else - rrdset_next_usec(st, microseconds); - } else - rrdset_next(st); - } - return PARSER_RC_OK; -} - - -PARSER_RC pluginsd_end_action(void *user, RRDSET *st) -{ - UNUSED(user); - - rrdset_done(st); - return PARSER_RC_OK; -} + if(!txt || !*txt) + return 0; -PARSER_RC pluginsd_chart_action(void *user, char *type, char *id, char *name, char *family, char *context, char *title, char *units, char *plugin, - char *module, int priority, int update_every, RRDSET_TYPE chart_type, char *options) -{ - RRDSET *st = NULL; - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; +#ifdef ENABLE_HTTPS + struct netdata_ssl *ssl = parser->ssl_output; + if(ssl) { + if(ssl->conn && ssl->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) + return (int)netdata_ssl_write(ssl->conn, (void *)txt, strlen(txt)); - st = rrdset_create( - host, type, id, name, family, context, title, units, - plugin, module, priority, update_every, - chart_type); + error("PLUGINSD: cannot send command (SSL)"); + return -1; + } +#endif - if (options && *options) { - if (strstr(options, "obsolete")) - rrdset_is_obsolete(st); - else - rrdset_isnot_obsolete(st); + if(parser->fp_output) { + int bytes = fprintf(parser->fp_output, "%s", txt); + if(bytes <= 0) { + error("PLUGINSD: cannot send command (FILE)"); + return -2; + } + fflush(parser->fp_output); + return bytes; + } - if (strstr(options, "detail")) - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - else - rrdset_flag_clear(st, RRDSET_FLAG_DETAIL); + if(parser->fd != -1) { + size_t bytes = 0; + size_t total = strlen(txt); + ssize_t sent; - if (strstr(options, "hidden")) - rrdset_flag_set(st, RRDSET_FLAG_HIDDEN); - else - rrdset_flag_clear(st, RRDSET_FLAG_HIDDEN); + do { + sent = write(parser->fd, &txt[bytes], total - bytes); + if(sent <= 0) { + error("PLUGINSD: cannot send command (fd)"); + return -3; + } + bytes += sent; + } + while(bytes < total); - if (strstr(options, "store_first")) - rrdset_flag_set(st, RRDSET_FLAG_STORE_FIRST); - 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); + return (int)bytes; } - ((PARSER_USER_OBJECT *)user)->st = st; - return PARSER_RC_OK; + error("PLUGINSD: cannot send command (no output socket/pipe/file given to plugins.d parser)"); + return -4; } +static inline RRDHOST *pluginsd_require_host_from_parent(void *user, const char *cmd) { + RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; -PARSER_RC pluginsd_disable_action(void *user) -{ - UNUSED(user); + if(unlikely(!host)) + error("PLUGINSD: command %s requires a host, but is not set.", cmd); - info("called DISABLE. Disabling it."); - ((PARSER_USER_OBJECT *) user)->enabled = 0; - return PARSER_RC_ERROR; + return host; } +static inline RRDSET *pluginsd_require_chart_from_parent(void *user, const char *cmd, const char *parent_cmd) { + RRDSET *st = ((PARSER_USER_OBJECT *) user)->st; -PARSER_RC pluginsd_variable_action(void *user, RRDHOST *host, RRDSET *st, char *name, int global, NETDATA_DOUBLE value) -{ - UNUSED(user); + if(unlikely(!st)) + error("PLUGINSD: command %s requires a chart defined via command %s, but is not set.", cmd, parent_cmd); - if (global) { - RRDVAR *rv = rrdvar_custom_host_variable_create(host, name); - if (rv) - rrdvar_custom_host_variable_set(host, rv, value); - else - error("cannot find/create HOST VARIABLE '%s' on host '%s'", name, host->hostname); - } else { - RRDSETVAR *rs = rrdsetvar_custom_chart_variable_create(st, name); - if (rs) - rrdsetvar_custom_chart_variable_set(rs, value); - else - error("cannot find/create CHART VARIABLE '%s' on host '%s', chart '%s'", name, host->hostname, st->id); - } - return PARSER_RC_OK; + return st; } - - -PARSER_RC pluginsd_dimension_action(void *user, RRDSET *st, char *id, char *name, char *algorithm, long multiplier, long divisor, char *options, - RRD_ALGORITHM algorithm_type) -{ - UNUSED(user); - UNUSED(algorithm); - - RRDDIM *rd = rrddim_add(st, id, name, multiplier, divisor, algorithm_type); - int unhide_dimension = 1; - - rrddim_flag_clear(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); - if (options && *options) { - if (strstr(options, "obsolete") != NULL) - rrddim_is_obsolete(st, rd); - else - rrddim_isnot_obsolete(st, rd); - - unhide_dimension = !strstr(options, "hidden"); - - if (strstr(options, "noreset") != NULL) - rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); - if (strstr(options, "nooverflow") != NULL) - rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); - } else - rrddim_isnot_obsolete(st, rd); - - if (likely(unhide_dimension)) { - rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN); - if (rrddim_flag_check(rd, RRDDIM_FLAG_META_HIDDEN)) { - (void)sql_set_dimension_option(&rd->metric_uuid, NULL); - rrddim_flag_clear(rd, RRDDIM_FLAG_META_HIDDEN); - } - } else { - rrddim_flag_set(rd, RRDDIM_FLAG_HIDDEN); - if (!rrddim_flag_check(rd, RRDDIM_FLAG_META_HIDDEN)) { - (void)sql_set_dimension_option(&rd->metric_uuid, "hidden"); - rrddim_flag_set(rd, RRDDIM_FLAG_META_HIDDEN); - } +static inline RRDDIM_ACQUIRED *pluginsd_acquire_dimension(RRDHOST *host, RRDSET *st, const char *dimension, const char *cmd) { + if (unlikely(!dimension || !*dimension)) { + error("PLUGINSD: 'host:%s/chart:%s' got a %s, without a dimension.", + rrdhost_hostname(host), rrdset_id(st), cmd); + return NULL; } - return PARSER_RC_OK; -} - -PARSER_RC pluginsd_label_action(void *user, char *key, char *value, RRDLABEL_SRC source) -{ - - if(unlikely(!((PARSER_USER_OBJECT *) user)->new_host_labels)) - ((PARSER_USER_OBJECT *) user)->new_host_labels = rrdlabels_create(); - rrdlabels_add(((PARSER_USER_OBJECT *)user)->new_host_labels, key, value, source); + RRDDIM_ACQUIRED *rda = rrddim_find_and_acquire(st, dimension); - return PARSER_RC_OK; -} + if (unlikely(!rda)) + error("PLUGINSD: 'host:%s/chart:%s/dim:%s' got a %s but dimension does not exist.", + rrdhost_hostname(host), rrdset_id(st), dimension, cmd); -PARSER_RC pluginsd_clabel_action(void *user, char *key, char *value, RRDLABEL_SRC source) -{ - if(unlikely(!((PARSER_USER_OBJECT *) user)->new_chart_labels)) - ((PARSER_USER_OBJECT *) user)->new_chart_labels = rrdlabels_create(); - - rrdlabels_add(((PARSER_USER_OBJECT *)user)->new_chart_labels, key, value, source); - - return PARSER_RC_OK; + return rda; } -PARSER_RC pluginsd_clabel_commit_action(void *user, RRDHOST *host, DICTIONARY *new_chart_labels) -{ - RRDSET *st = ((PARSER_USER_OBJECT *)user)->st; - if (unlikely(!st)) { - error("requested CLABEL_COMMIT on host '%s', without a BEGIN, ignoring it.", host->hostname); - return PARSER_RC_OK; +static inline RRDSET *pluginsd_find_chart(RRDHOST *host, const char *chart, const char *cmd) { + if (unlikely(!chart || !*chart)) { + error("PLUGINSD: 'host:%s' got a %s without a chart id.", + rrdhost_hostname(host), cmd); + return NULL; } - rrdset_update_rrdlabels(st, new_chart_labels); + RRDSET *st = rrdset_find(host, chart); + if (unlikely(!st)) + error("PLUGINSD: 'host:%s/chart:%s' got a %s but chart does not exist.", + rrdhost_hostname(host), chart, cmd); - return PARSER_RC_OK; + return st; } -PARSER_RC pluginsd_overwrite_action(void *user, RRDHOST *host, DICTIONARY *new_host_labels) -{ - UNUSED(user); - - if(!host->host_labels) - host->host_labels = rrdlabels_create(); - - rrdlabels_migrate_to_these(host->host_labels, new_host_labels); - sql_store_host_labels(host); - - return PARSER_RC_OK; +static inline PARSER_RC PLUGINSD_DISABLE_PLUGIN(void *user) { + ((PARSER_USER_OBJECT *) user)->enabled = 0; + return PARSER_RC_ERROR; } -PARSER_RC pluginsd_set(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_set(char **words, size_t num_words, void *user) { - char *dimension = words[1]; - char *value = words[2]; + char *dimension = get_word(words, num_words, 1); + char *value = get_word(words, num_words, 2); - RRDSET *st = ((PARSER_USER_OBJECT *) user)->st; - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_SET); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); - if (unlikely(!dimension || !*dimension)) { - error("requested a SET on chart '%s' of host '%s', without a dimension. Disabling it.", st->id, host->hostname); - goto disable; - } + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_SET, PLUGINSD_KEYWORD_CHART); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); - if (unlikely(!value || !*value)) - value = NULL; + RRDDIM_ACQUIRED *rda = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_SET); + if(!rda) return PLUGINSD_DISABLE_PLUGIN(user); - if (unlikely(!st)) { - error( - "requested a SET on dimension %s with value %s on host '%s', without a BEGIN. Disabling it.", dimension, - value ? value : "<nothing>", host->hostname); - goto disable; - } + RRDDIM *rd = rrddim_acquired_to_rrddim(rda); if (unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) - debug(D_PLUGINSD, "is setting dimension %s/%s to %s", st->id, dimension, value ? value : "<nothing>"); - - if (value) { - RRDDIM *rd = rrddim_find(st, dimension); - if (unlikely(!rd)) { - error( - "requested a SET to dimension with id '%s' on stats '%s' (%s) on host '%s', which does not exist. Disabling it.", - dimension, st->name, st->id, st->rrdhost->hostname); - goto disable; - } else { - if (plugins_action->set_action) { - return plugins_action->set_action( - user, st, rd, strtoll(value, NULL, 0)); - } - } - } - return PARSER_RC_OK; + debug(D_PLUGINSD, "PLUGINSD: 'host:%s/chart:%s/dim:%s' SET is setting value to '%s'", + rrdhost_hostname(host), rrdset_id(st), dimension, value && *value ? value : "UNSET"); -disable: - ((PARSER_USER_OBJECT *) user)->enabled = 0; - return PARSER_RC_ERROR; + if (value && *value) + rrddim_set_by_pointer(st, rd, strtoll(value, NULL, 0)); + + rrddim_acquired_release(rda); + return PARSER_RC_OK; } -PARSER_RC pluginsd_begin(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_begin(char **words, size_t num_words, void *user) { - char *id = words[1]; - char *microseconds_txt = words[2]; + char *id = get_word(words, num_words, 1); + char *microseconds_txt = get_word(words, num_words, 2); - RRDSET *st = NULL; - RRDHOST *host = ((PARSER_USER_OBJECT *)user)->host; + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_BEGIN); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); - if (unlikely(!id)) { - error("requested a BEGIN without a chart id for host '%s'. Disabling it.", host->hostname); - goto disable; - } + RRDSET *st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); - st = rrdset_find(host, id); - if (unlikely(!st)) { - error("requested a BEGIN on chart '%s', which does not exist on host '%s'. Disabling it.", id, host->hostname); - goto disable; - } ((PARSER_USER_OBJECT *)user)->st = st; usec_t microseconds = 0; if (microseconds_txt && *microseconds_txt) microseconds = str2ull(microseconds_txt); - if (plugins_action->begin_action) { - return plugins_action->begin_action(user, st, microseconds, - ((PARSER_USER_OBJECT *)user)->trust_durations); +#ifdef NETDATA_LOG_REPLICATION_REQUESTS + if(st->replay.log_next_data_collection) { + st->replay.log_next_data_collection = false; + + internal_error(true, + "REPLAY: 'host:%s/chart:%s' first BEGIN after replication, last collected %llu, last updated %llu, microseconds %llu", + rrdhost_hostname(host), rrdset_id(st), + st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec, + st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec, + microseconds + ); + } +#endif + + if (likely(st->counter_done)) { + if (likely(microseconds)) { + if (((PARSER_USER_OBJECT *)user)->trust_durations) + rrdset_next_usec_unfiltered(st, microseconds); + else + rrdset_next_usec(st, microseconds); + } + else + rrdset_next(st); } return PARSER_RC_OK; -disable: - ((PARSER_USER_OBJECT *)user)->enabled = 0; - return PARSER_RC_ERROR; } -PARSER_RC pluginsd_end(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_end(char **words, size_t num_words, void *user) { UNUSED(words); - RRDSET *st = ((PARSER_USER_OBJECT *) user)->st; - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; + UNUSED(num_words); - if (unlikely(!st)) { - error("requested an END, without a BEGIN on host '%s'. Disabling it.", host->hostname); - ((PARSER_USER_OBJECT *) user)->enabled = 0; - return PARSER_RC_ERROR; - } + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_END); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_END, PLUGINSD_KEYWORD_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); if (unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) - debug(D_PLUGINSD, "requested an END on chart %s", st->id); + debug(D_PLUGINSD, "requested an END on chart '%s'", rrdset_id(st)); ((PARSER_USER_OBJECT *) user)->st = NULL; ((PARSER_USER_OBJECT *) user)->count++; - if (plugins_action->end_action) { - return plugins_action->end_action(user, st); - } + + struct timeval now; + now_realtime_timeval(&now); + rrdset_timed_done(st, now, /* pending_rrdset_next = */ false); + return PARSER_RC_OK; } -PARSER_RC pluginsd_chart(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_chart(char **words, size_t num_words, void *user) { - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; - if (unlikely(!host && !((PARSER_USER_OBJECT *) user)->host_exists)) { - debug(D_PLUGINSD, "Ignoring chart belonging to missing or ignored host."); - return PARSER_RC_OK; - } - - char *type = words[1]; - char *name = words[2]; - char *title = words[3]; - char *units = words[4]; - char *family = words[5]; - char *context = words[6]; - char *chart = words[7]; - char *priority_s = words[8]; - char *update_every_s = words[9]; - char *options = words[10]; - char *plugin = words[11]; - char *module = words[12]; - - int have_action = ((plugins_action->chart_action) != NULL); + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CHART); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + char *type = get_word(words, num_words, 1); + char *name = get_word(words, num_words, 2); + char *title = get_word(words, num_words, 3); + char *units = get_word(words, num_words, 4); + char *family = get_word(words, num_words, 5); + char *context = get_word(words, num_words, 6); + char *chart = get_word(words, num_words, 7); + char *priority_s = get_word(words, num_words, 8); + char *update_every_s = get_word(words, num_words, 9); + char *options = get_word(words, num_words, 10); + char *plugin = get_word(words, num_words, 11); + char *module = get_word(words, num_words, 12); // parse the id from type char *id = NULL; @@ -342,10 +229,9 @@ PARSER_RC pluginsd_chart(char **words, void *user, PLUGINSD_ACTION *plugins_act // make sure we have the required variables if (unlikely((!type || !*type || !id || !*id))) { - if (likely(host)) - error("requested a CHART, without a type.id, on host '%s'. Disabling it.", host->hostname); - else - error("requested a CHART, without a type.id. Disabling it."); + error("PLUGINSD: 'host:%s' requested a CHART, without a type.id. Disabling it.", + rrdhost_hostname(host)); + ((PARSER_USER_OBJECT *) user)->enabled = 0; return PARSER_RC_ERROR; } @@ -396,42 +282,120 @@ PARSER_RC pluginsd_chart(char **words, void *user, PLUGINSD_ACTION *plugins_act type, id, name ? name : "", family ? family : "", context ? context : "", rrdset_type_name(chart_type), priority, update_every); - if (have_action) { - return plugins_action->chart_action( - user, type, id, name, family, context, title, units, - (plugin && *plugin) ? plugin : ((PARSER_USER_OBJECT *)user)->cd->filename, module, priority, update_every, - chart_type, options); + RRDSET *st = NULL; + + st = rrdset_create( + host, type, id, name, family, context, title, units, + (plugin && *plugin) ? plugin : ((PARSER_USER_OBJECT *)user)->cd->filename, + module, priority, update_every, + chart_type); + + if (likely(st)) { + if (options && *options) { + if (strstr(options, "obsolete")) + rrdset_is_obsolete(st); + else + rrdset_isnot_obsolete(st); + + if (strstr(options, "detail")) + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + else + rrdset_flag_clear(st, RRDSET_FLAG_DETAIL); + + if (strstr(options, "hidden")) + rrdset_flag_set(st, RRDSET_FLAG_HIDDEN); + else + rrdset_flag_clear(st, RRDSET_FLAG_HIDDEN); + + if (strstr(options, "store_first")) + rrdset_flag_set(st, RRDSET_FLAG_STORE_FIRST); + 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); + } } + ((PARSER_USER_OBJECT *)user)->st = st; return PARSER_RC_OK; } -PARSER_RC pluginsd_dimension(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_chart_definition_end(char **words, size_t num_words, void *user) { - char *id = words[1]; - char *name = words[2]; - char *algorithm = words[3]; - char *multiplier_s = words[4]; - char *divisor_s = words[5]; - char *options = words[6]; - - RRDSET *st = ((PARSER_USER_OBJECT *) user)->st; - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; - if (unlikely(!host && !((PARSER_USER_OBJECT *) user)->host_exists)) { - debug(D_PLUGINSD, "Ignoring dimension belonging to missing or ignored host."); - return PARSER_RC_OK; + const char *first_entry_txt = get_word(words, num_words, 1); + const char *last_entry_txt = get_word(words, num_words, 2); + const char *world_time_txt = get_word(words, num_words, 3); + + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CHART_DEFINITION_END); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_CHART_DEFINITION_END, PLUGINSD_KEYWORD_CHART); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); + + time_t first_entry_child = (first_entry_txt && *first_entry_txt) ? (time_t)str2ul(first_entry_txt) : 0; + time_t last_entry_child = (last_entry_txt && *last_entry_txt) ? (time_t)str2ul(last_entry_txt) : 0; + time_t child_world_time = (world_time_txt && *world_time_txt) ? (time_t)str2ul(world_time_txt) : now_realtime_sec(); + + if((first_entry_child != 0 || last_entry_child != 0) && (first_entry_child == 0 || last_entry_child == 0)) + error("PLUGINSD REPLAY ERROR: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_CHART_DEFINITION_END " with malformed timings (first time %ld, last time %ld, world time %ld).", + rrdhost_hostname(host), rrdset_id(st), + first_entry_child, last_entry_child, child_world_time); + + bool ok = true; + if(!rrdset_flag_check(st, RRDSET_FLAG_RECEIVER_REPLICATION_IN_PROGRESS)) { + +#ifdef NETDATA_LOG_REPLICATION_REQUESTS + st->replay.start_streaming = false; + st->replay.after = 0; + st->replay.before = 0; +#endif + + rrdset_flag_set(st, RRDSET_FLAG_RECEIVER_REPLICATION_IN_PROGRESS); + rrdset_flag_clear(st, RRDSET_FLAG_RECEIVER_REPLICATION_FINISHED); + rrdhost_receiver_replicating_charts_plus_one(st->rrdhost); + + PARSER *parser = ((PARSER_USER_OBJECT *)user)->parser; + ok = replicate_chart_request(send_to_plugin, parser, host, st, + first_entry_child, last_entry_child, child_world_time, + 0, 0); + } +#ifdef NETDATA_LOG_REPLICATION_REQUESTS + else { + internal_error(true, "REPLAY: 'host:%s/chart:%s' not sending duplicate replication request", + rrdhost_hostname(st->rrdhost), rrdset_id(st)); } +#endif + + return ok ? PARSER_RC_OK : PARSER_RC_ERROR; +} + +PARSER_RC pluginsd_dimension(char **words, size_t num_words, void *user) +{ + char *id = get_word(words, num_words, 1); + char *name = get_word(words, num_words, 2); + char *algorithm = get_word(words, num_words, 3); + char *multiplier_s = get_word(words, num_words, 4); + char *divisor_s = get_word(words, num_words, 5); + char *options = get_word(words, num_words, 6); + + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_DIMENSION); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_DIMENSION, PLUGINSD_KEYWORD_CHART); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); if (unlikely(!id)) { - error( - "requested a DIMENSION, without an id, host '%s' and chart '%s'. Disabling it.", host->hostname, - st ? st->id : "UNSET"); - goto disable; + error("PLUGINSD: 'host:%s/chart:%s' got a DIMENSION, without an id. Disabling it.", + rrdhost_hostname(host), st ? rrdset_id(st) : "UNSET"); + return PLUGINSD_DISABLE_PLUGIN(user); } if (unlikely(!st && !((PARSER_USER_OBJECT *) user)->st_exists)) { - error("requested a DIMENSION, without a CHART, on host '%s'. Disabling it.", host->hostname); - goto disable; + error("PLUGINSD: 'host:%s' got a DIMENSION, without a CHART. Disabling it.", + rrdhost_hostname(host)); + return PLUGINSD_DISABLE_PLUGIN(user); } long multiplier = 1; @@ -455,316 +419,906 @@ PARSER_RC pluginsd_dimension(char **words, void *user, PLUGINSD_ACTION *plugins debug( D_PLUGINSD, "creating dimension in chart %s, id='%s', name='%s', algorithm='%s', multiplier=%ld, divisor=%ld, hidden='%s'", - st->id, id, name ? name : "", rrd_algorithm_name(rrd_algorithm_id(algorithm)), multiplier, divisor, + rrdset_id(st), id, name ? name : "", rrd_algorithm_name(rrd_algorithm_id(algorithm)), multiplier, divisor, options ? options : ""); - if (plugins_action->dimension_action) { - return plugins_action->dimension_action( - user, st, id, name, algorithm, - multiplier, divisor, (options && *options)?options:NULL, rrd_algorithm_id(algorithm)); + RRDDIM *rd = rrddim_add(st, id, name, multiplier, divisor, rrd_algorithm_id(algorithm)); + int unhide_dimension = 1; + + rrddim_option_clear(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS); + if (options && *options) { + if (strstr(options, "obsolete") != NULL) + rrddim_is_obsolete(st, rd); + else + rrddim_isnot_obsolete(st, rd); + + unhide_dimension = !strstr(options, "hidden"); + + if (strstr(options, "noreset") != NULL) + rrddim_option_set(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS); + if (strstr(options, "nooverflow") != NULL) + rrddim_option_set(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS); + } else + rrddim_isnot_obsolete(st, rd); + + if (likely(unhide_dimension)) { + rrddim_option_clear(rd, RRDDIM_OPTION_HIDDEN); + if (rrddim_flag_check(rd, RRDDIM_FLAG_META_HIDDEN)) { + rrddim_flag_clear(rd, RRDDIM_FLAG_META_HIDDEN); + metaqueue_dimension_update_flags(rd); + } + } + else { + rrddim_option_set(rd, RRDDIM_OPTION_HIDDEN); + if (!rrddim_flag_check(rd, RRDDIM_FLAG_META_HIDDEN)) { + rrddim_flag_set(rd, RRDDIM_FLAG_META_HIDDEN); + metaqueue_dimension_update_flags(rd); + } + } + + return PARSER_RC_OK; +} + +// ---------------------------------------------------------------------------- +// execution of functions + +struct inflight_function { + int code; + int timeout; + BUFFER *destination_wb; + STRING *function; + void (*callback)(BUFFER *wb, int code, void *callback_data); + void *callback_data; + usec_t timeout_ut; + usec_t started_ut; + usec_t sent_ut; +}; + +static void inflight_functions_insert_callback(const DICTIONARY_ITEM *item, void *func, void *parser_ptr) { + struct inflight_function *pf = func; + + PARSER *parser = parser_ptr; + + // leave this code as default, so that when the dictionary is destroyed this will be sent back to the caller + pf->code = HTTP_RESP_GATEWAY_TIMEOUT; + + char buffer[2048 + 1]; + snprintfz(buffer, 2048, "FUNCTION %s %d \"%s\"\n", + dictionary_acquired_item_name(item), + pf->timeout, + string2str(pf->function)); + + // send the command to the plugin + int ret = send_to_plugin(buffer, parser); + + pf->sent_ut = now_realtime_usec(); + + if(ret < 0) { + error("FUNCTION: failed to send function to plugin, error %d", ret); + rrd_call_function_error(pf->destination_wb, "Failed to communicate with collector", HTTP_RESP_BACKEND_FETCH_FAILED); + } + else { + internal_error(LOG_FUNCTIONS, + "FUNCTION '%s' with transaction '%s' sent to collector (%d bytes, in %llu usec)", + string2str(pf->function), dictionary_acquired_item_name(item), ret, + pf->sent_ut - pf->started_ut); + } +} + +static bool inflight_functions_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *func __maybe_unused, void *new_func, void *parser_ptr __maybe_unused) { + struct inflight_function *pf = new_func; + + error("PLUGINSD_PARSER: duplicate UUID on pending function '%s' detected. Ignoring the second one.", string2str(pf->function)); + pf->code = rrd_call_function_error(pf->destination_wb, "This request is already in progress", HTTP_RESP_BAD_REQUEST); + pf->callback(pf->destination_wb, pf->code, pf->callback_data); + string_freez(pf->function); + + return false; +} + +static void inflight_functions_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *func, void *parser_ptr __maybe_unused) { + struct inflight_function *pf = func; + + internal_error(LOG_FUNCTIONS, + "FUNCTION '%s' result of transaction '%s' received from collector (%zu bytes, request %llu usec, response %llu usec)", + string2str(pf->function), dictionary_acquired_item_name(item), + buffer_strlen(pf->destination_wb), pf->sent_ut - pf->started_ut, now_realtime_usec() - pf->sent_ut); + + pf->callback(pf->destination_wb, pf->code, pf->callback_data); + string_freez(pf->function); +} + +void inflight_functions_init(PARSER *parser) { + parser->inflight.functions = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE); + dictionary_register_insert_callback(parser->inflight.functions, inflight_functions_insert_callback, parser); + dictionary_register_delete_callback(parser->inflight.functions, inflight_functions_delete_callback, parser); + dictionary_register_conflict_callback(parser->inflight.functions, inflight_functions_conflict_callback, parser); +} + +static void inflight_functions_garbage_collect(PARSER *parser, usec_t now) { + parser->inflight.smaller_timeout = 0; + struct inflight_function *pf; + dfe_start_write(parser->inflight.functions, pf) { + if (pf->timeout_ut < now) { + internal_error(true, + "FUNCTION '%s' removing expired transaction '%s', after %llu usec.", + string2str(pf->function), pf_dfe.name, now - pf->started_ut); + + if(!buffer_strlen(pf->destination_wb) || pf->code == HTTP_RESP_OK) + pf->code = rrd_call_function_error(pf->destination_wb, + "Timeout waiting for collector response.", + HTTP_RESP_GATEWAY_TIMEOUT); + + dictionary_del(parser->inflight.functions, pf_dfe.name); + } + + else if(!parser->inflight.smaller_timeout || pf->timeout_ut < parser->inflight.smaller_timeout) + parser->inflight.smaller_timeout = pf->timeout_ut; + } + dfe_done(pf); +} + +// this is the function that is called from +// rrd_call_function_and_wait() and rrd_call_function_async() +static int pluginsd_execute_function_callback(BUFFER *destination_wb, int timeout, const char *function, void *collector_data, void (*callback)(BUFFER *wb, int code, void *callback_data), void *callback_data) { + PARSER *parser = collector_data; + + usec_t now = now_realtime_usec(); + + struct inflight_function tmp = { + .started_ut = now, + .timeout_ut = now + timeout * USEC_PER_SEC, + .destination_wb = destination_wb, + .timeout = timeout, + .function = string_strdupz(function), + .callback = callback, + .callback_data = callback_data, + }; + + uuid_t uuid; + uuid_generate_time(uuid); + + char key[UUID_STR_LEN]; + uuid_unparse_lower(uuid, key); + + dictionary_write_lock(parser->inflight.functions); + + // if there is any error, our dictionary callbacks will call the caller callback to notify + // the caller about the error - no need for error handling here. + dictionary_set(parser->inflight.functions, key, &tmp, sizeof(struct inflight_function)); + + if(!parser->inflight.smaller_timeout || tmp.timeout_ut < parser->inflight.smaller_timeout) + parser->inflight.smaller_timeout = tmp.timeout_ut; + + // garbage collect stale inflight functions + if(parser->inflight.smaller_timeout < now) + inflight_functions_garbage_collect(parser, now); + + dictionary_write_unlock(parser->inflight.functions); + + return HTTP_RESP_OK; +} + +PARSER_RC pluginsd_function(char **words, size_t num_words, void *user) +{ + bool global = false; + size_t i = 1; + if(num_words >= 2 && strcmp(get_word(words, num_words, 1), "GLOBAL") == 0) { + i++; + global = true; + } + + char *name = get_word(words, num_words, i++); + char *timeout_s = get_word(words, num_words, i++); + char *help = get_word(words, num_words, i++); + + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_FUNCTION); + if(!host) return PARSER_RC_ERROR; + + RRDSET *st = (global)?NULL:pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_FUNCTION, PLUGINSD_KEYWORD_CHART); + if(!st) global = true; + + if (unlikely(!timeout_s || !name || !help || (!global && !st))) { + error("PLUGINSD: 'host:%s/chart:%s' got a FUNCTION, without providing the required data (global = '%s', name = '%s', timeout = '%s', help = '%s'). Ignoring it.", + rrdhost_hostname(host), + st?rrdset_id(st):"(unset)", + global?"yes":"no", + name?name:"(unset)", + timeout_s?timeout_s:"(unset)", + help?help:"(unset)" + ); + return PARSER_RC_ERROR; + } + + int timeout = PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT; + if (timeout_s && *timeout_s) { + timeout = str2i(timeout_s); + if (unlikely(timeout <= 0)) + timeout = PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT; } + PARSER *parser = ((PARSER_USER_OBJECT *) user)->parser; + rrd_collector_add_function(host, st, name, timeout, help, false, pluginsd_execute_function_callback, parser); + + return PARSER_RC_OK; +} + +static void pluginsd_function_result_end(struct parser *parser, void *action_data) { + STRING *key = action_data; + if(key) + dictionary_del(parser->inflight.functions, string2str(key)); + string_freez(key); +} + +PARSER_RC pluginsd_function_result_begin(char **words, size_t num_words, void *user) +{ + char *key = get_word(words, num_words, 1); + char *status = get_word(words, num_words, 2); + char *format = get_word(words, num_words, 3); + char *expires = get_word(words, num_words, 4); + + if (unlikely(!key || !*key || !status || !*status || !format || !*format || !expires || !*expires)) { + error("got a " PLUGINSD_KEYWORD_FUNCTION_RESULT_BEGIN " without providing the required data (key = '%s', status = '%s', format = '%s', expires = '%s')." + , key ? key : "(unset)" + , status ? status : "(unset)" + , format ? format : "(unset)" + , expires ? expires : "(unset)" + ); + } + + int code = (status && *status) ? str2i(status) : 0; + if (code <= 0) + code = HTTP_RESP_BACKEND_RESPONSE_INVALID; + + time_t expiration = (expires && *expires) ? str2l(expires) : 0; + + PARSER *parser = ((PARSER_USER_OBJECT *) user)->parser; + + struct inflight_function *pf = NULL; + + if(key && *key) + pf = (struct inflight_function *)dictionary_get(parser->inflight.functions, key); + + if(!pf) { + error("got a " PLUGINSD_KEYWORD_FUNCTION_RESULT_BEGIN " for transaction '%s', but the transaction is not found.", key?key:"(unset)"); + } + else { + if(format && *format) + pf->destination_wb->contenttype = functions_format_to_content_type(format); + + pf->code = code; + + pf->destination_wb->expires = expiration; + if(expiration <= now_realtime_sec()) + buffer_no_cacheable(pf->destination_wb); + else + buffer_cacheable(pf->destination_wb); + } + + parser->defer.response = (pf) ? pf->destination_wb : NULL; + parser->defer.end_keyword = PLUGINSD_KEYWORD_FUNCTION_RESULT_END; + parser->defer.action = pluginsd_function_result_end; + parser->defer.action_data = string_strdupz(key); // it is ok is key is NULL + parser->flags |= PARSER_DEFER_UNTIL_KEYWORD; + return PARSER_RC_OK; -disable: - ((PARSER_USER_OBJECT *)user)->enabled = 0; - return PARSER_RC_ERROR; } -PARSER_RC pluginsd_variable(char **words, void *user, PLUGINSD_ACTION *plugins_action) +// ---------------------------------------------------------------------------- + +PARSER_RC pluginsd_variable(char **words, size_t num_words, void *user) { - char *name = words[1]; - char *value = words[2]; + char *name = get_word(words, num_words, 1); + char *value = get_word(words, num_words, 2); NETDATA_DOUBLE v; + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_VARIABLE); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + RRDSET *st = ((PARSER_USER_OBJECT *) user)->st; - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; 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]; + name = get_word(words, num_words, 2); + value = get_word(words, num_words, 3); } else if ((strcmp(name, "LOCAL") == 0 || strcmp(name, "CHART") == 0)) { global = 0; - name = words[2]; - value = words[3]; + name = get_word(words, num_words, 2); + value = get_word(words, num_words, 3); } } if (unlikely(!name || !*name)) { - error("requested a VARIABLE on host '%s', without a variable name. Disabling it.", host->hostname); + error("PLUGINSD: 'host:%s/chart:%s' got a VARIABLE without a variable name. Disabling it.", + rrdhost_hostname(host), st ? rrdset_id(st):"UNSET"); + ((PARSER_USER_OBJECT *)user)->enabled = 0; - return PARSER_RC_ERROR; + return PLUGINSD_DISABLE_PLUGIN(user); } if (unlikely(!value || !*value)) value = NULL; if (unlikely(!value)) { - error("cannot set %s VARIABLE '%s' on host '%s' to an empty value", (global) ? "HOST" : "CHART", name, - host->hostname); + error("PLUGINSD: 'host:%s/chart:%s' cannot set %s VARIABLE '%s' to an empty value", + rrdhost_hostname(host), + st ? rrdset_id(st):"UNSET", + (global) ? "HOST" : "CHART", + name); return PARSER_RC_OK; } if (!global && !st) { - error("cannot find/create CHART VARIABLE '%s' on host '%s' without a chart", name, host->hostname); - return PARSER_RC_OK; + error("PLUGINSD: 'host:%s/chart:%s' cannot update CHART VARIABLE '%s' without a chart", + rrdhost_hostname(host), + st ? rrdset_id(st):"UNSET", + name + ); + return PLUGINSD_DISABLE_PLUGIN(user); } char *endptr = NULL; v = (NETDATA_DOUBLE)str2ndd(value, &endptr); if (unlikely(endptr && *endptr)) { if (endptr == value) - error( - "the value '%s' of VARIABLE '%s' on host '%s' cannot be parsed as a number", value, name, - host->hostname); + error("PLUGINSD: 'host:%s/chart:%s' the value '%s' of VARIABLE '%s' cannot be parsed as a number", + rrdhost_hostname(host), + st ? rrdset_id(st):"UNSET", + value, + name); else - error( - "the value '%s' of VARIABLE '%s' on host '%s' has leftovers: '%s'", value, name, host->hostname, - endptr); + error("PLUGINSD: 'host:%s/chart:%s' the value '%s' of VARIABLE '%s' has leftovers: '%s'", + rrdhost_hostname(host), + st ? rrdset_id(st):"UNSET", + value, + name, + endptr); } - if (plugins_action->variable_action) { - return plugins_action->variable_action(user, host, st, name, global, v); + if (global) { + const RRDVAR_ACQUIRED *rva = rrdvar_custom_host_variable_add_and_acquire(host, name); + if (rva) { + rrdvar_custom_host_variable_set(host, rva, v); + rrdvar_custom_host_variable_release(host, rva); + } + else + error("PLUGINSD: 'host:%s' cannot find/create HOST VARIABLE '%s'", + rrdhost_hostname(host), + name); + } else { + const RRDSETVAR_ACQUIRED *rsa = rrdsetvar_custom_chart_variable_add_and_acquire(st, name); + if (rsa) { + rrdsetvar_custom_chart_variable_set(st, rsa, v); + rrdsetvar_custom_chart_variable_release(st, rsa); + } + else + error("PLUGINSD: 'host:%s/chart:%s' cannot find/create CHART VARIABLE '%s'", + rrdhost_hostname(host), rrdset_id(st), name); } return PARSER_RC_OK; } -PARSER_RC pluginsd_flush(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_flush(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) { - UNUSED(words); debug(D_PLUGINSD, "requested a FLUSH"); - RRDSET *st = ((PARSER_USER_OBJECT *) user)->st; ((PARSER_USER_OBJECT *) user)->st = NULL; - if (plugins_action->flush_action) { - return plugins_action->flush_action(user, st); - } + ((PARSER_USER_OBJECT *) user)->replay.start_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.end_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.start_time_ut = 0; + ((PARSER_USER_OBJECT *) user)->replay.end_time_ut = 0; return PARSER_RC_OK; } -PARSER_RC pluginsd_disable(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_disable(char **words __maybe_unused, size_t num_words __maybe_unused, void *user __maybe_unused) { - UNUSED(user); - UNUSED(words); - - if (plugins_action->disable_action) { - return plugins_action->disable_action(user); - } + info("PLUGINSD: plugin called DISABLE. Disabling it."); + ((PARSER_USER_OBJECT *) user)->enabled = 0; return PARSER_RC_ERROR; } -PARSER_RC pluginsd_label(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_label(char **words, size_t num_words, void *user) { - char *store; + const char *name = get_word(words, num_words, 1); + const char *label_source = get_word(words, num_words, 2); + const char *value = get_word(words, num_words, 3); - if (!words[1] || !words[2] || !words[3]) { - error("Ignoring malformed or empty LABEL command."); - return PARSER_RC_OK; + if (!name || !label_source || !value) { + error("PLUGINSD: ignoring malformed or empty LABEL command."); + return PLUGINSD_DISABLE_PLUGIN(user); } - if (!words[4]) - store = words[3]; - else { - store = callocz(PLUGINSD_LINE_MAX + 1, sizeof(char)); + + char *store = (char *)value; + bool allocated_store = false; + + if(unlikely(num_words > 4)) { + allocated_store = true; + store = mallocz(PLUGINSD_LINE_MAX + 1); size_t remaining = PLUGINSD_LINE_MAX; char *move = store; - int i = 3; - while (i < PLUGINSD_MAX_WORDS) { - size_t length = strlen(words[i]); - if ((length + 1) >= remaining) - break; - - remaining -= (length + 1); - memcpy(move, words[i], length); - move += length; - *move++ = ' '; + char *word; + for(size_t i = 3; i < num_words && remaining > 2 && (word = get_word(words, num_words, i)) ;i++) { + if(i > 3) { + *move++ = ' '; + *move = '\0'; + remaining--; + } + + size_t length = strlen(word); + if (length > remaining) + length = remaining; - i++; - if (!words[i]) - break; + remaining -= length; + memcpy(move, word, length); + move += length; + *move = '\0'; } } - if (plugins_action->label_action) { - PARSER_RC rc = plugins_action->label_action(user, words[1], store, strtol(words[2], NULL, 10)); - if (store != words[3]) - freez(store); - return rc; - } + if(unlikely(!((PARSER_USER_OBJECT *) user)->new_host_labels)) + ((PARSER_USER_OBJECT *) user)->new_host_labels = rrdlabels_create(); + + rrdlabels_add(((PARSER_USER_OBJECT *)user)->new_host_labels, + name, + store, + str2l(label_source)); - if (store != words[3]) + if (allocated_store) freez(store); + + return PARSER_RC_OK; +} + +PARSER_RC pluginsd_overwrite(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) +{ + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_OVERWRITE); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + debug(D_PLUGINSD, "requested to OVERWRITE host labels"); + + if(unlikely(!host->rrdlabels)) + host->rrdlabels = rrdlabels_create(); + + rrdlabels_migrate_to_these(host->rrdlabels, (DICTIONARY *) (((PARSER_USER_OBJECT *)user)->new_host_labels)); + metaqueue_store_host_labels(host->machine_guid); + + rrdlabels_destroy(((PARSER_USER_OBJECT *)user)->new_host_labels); + ((PARSER_USER_OBJECT *)user)->new_host_labels = NULL; return PARSER_RC_OK; } -PARSER_RC pluginsd_clabel(char **words, void *user, PLUGINSD_ACTION *plugins_action) + +PARSER_RC pluginsd_clabel(char **words, size_t num_words, void *user) { - if (!words[1] || !words[2] || !words[3]) { + const char *name = get_word(words, num_words, 1); + const char *value = get_word(words, num_words, 2); + const char *label_source = get_word(words, num_words, 3); + + if (!name || !value || !*label_source) { error("Ignoring malformed or empty CHART LABEL command."); - return PARSER_RC_OK; + return PLUGINSD_DISABLE_PLUGIN(user); } - if (plugins_action->clabel_action) { - PARSER_RC rc = plugins_action->clabel_action(user, words[1], words[2], strtol(words[3], NULL, 10)); - return rc; + if(unlikely(!((PARSER_USER_OBJECT *) user)->chart_rrdlabels_linked_temporarily)) { + ((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily = ((PARSER_USER_OBJECT *)user)->st->rrdlabels; + rrdlabels_unmark_all(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily); } + rrdlabels_add(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily, + name, value, str2l(label_source)); + return PARSER_RC_OK; } -PARSER_RC pluginsd_clabel_commit(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_clabel_commit(char **words __maybe_unused, size_t num_words __maybe_unused, void *user) { - UNUSED(words); + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_CLABEL_COMMIT); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_CLABEL_COMMIT, PLUGINSD_KEYWORD_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; debug(D_PLUGINSD, "requested to commit chart labels"); - PARSER_RC rc = PARSER_RC_OK; + if(!((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily) { + error("PLUGINSD: 'host:%s' got CLABEL_COMMIT, without a CHART or BEGIN. Ignoring it.", + rrdhost_hostname(host)); + return PLUGINSD_DISABLE_PLUGIN(user); + } - if (plugins_action->clabel_commit_action) - rc = plugins_action->clabel_commit_action(user, host, ((PARSER_USER_OBJECT *)user)->new_chart_labels); + rrdlabels_remove_all_unmarked(((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily); - rrdlabels_destroy(((PARSER_USER_OBJECT *)user)->new_chart_labels); - ((PARSER_USER_OBJECT *)user)->new_chart_labels = NULL; + rrdset_flag_set(st, RRDSET_FLAG_METADATA_UPDATE); + rrdhost_flag_set(st->rrdhost, RRDHOST_FLAG_METADATA_UPDATE); - return rc; + ((PARSER_USER_OBJECT *)user)->chart_rrdlabels_linked_temporarily = NULL; + return PARSER_RC_OK; } -PARSER_RC pluginsd_overwrite(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_replay_rrdset_begin(char **words, size_t num_words, void *user) { - UNUSED(words); + char *id = get_word(words, num_words, 1); + char *start_time_str = get_word(words, num_words, 2); + char *end_time_str = get_word(words, num_words, 3); + char *child_now_str = get_word(words, num_words, 4); - RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host; - debug(D_PLUGINSD, "requested to OVERWRITE host labels"); + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); - PARSER_RC rc = PARSER_RC_OK; + RRDSET *st; + if (likely(!id || !*id)) + st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_BEGIN, PLUGINSD_KEYWORD_REPLAY_BEGIN); + else + st = pluginsd_find_chart(host, id, PLUGINSD_KEYWORD_REPLAY_BEGIN); - if (plugins_action->overwrite_action) - rc = plugins_action->overwrite_action(user, host, ((PARSER_USER_OBJECT *)user)->new_host_labels); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); + ((PARSER_USER_OBJECT *) user)->st = st; - rrdlabels_destroy(((PARSER_USER_OBJECT *)user)->new_host_labels); - ((PARSER_USER_OBJECT *)user)->new_host_labels = NULL; + if(start_time_str && end_time_str) { + time_t start_time = (time_t)str2ul(start_time_str); + time_t end_time = (time_t)str2ul(end_time_str); - return rc; -} + time_t wall_clock_time = 0, tolerance; + bool wall_clock_comes_from_child; (void)wall_clock_comes_from_child; + if(child_now_str) { + wall_clock_time = (time_t)str2ul(child_now_str); + tolerance = st->update_every + 1; + wall_clock_comes_from_child = true; + } -PARSER_RC pluginsd_guid(char **words, void *user, PLUGINSD_ACTION *plugins_action) -{ - char *uuid_str = words[1]; - uuid_t uuid; + if(wall_clock_time <= 0) { + wall_clock_time = now_realtime_sec(); + tolerance = st->update_every + 5; + wall_clock_comes_from_child = false; + } - if (unlikely(!uuid_str)) { - error("requested a GUID, without a uuid."); - return PARSER_RC_ERROR; - } - if (unlikely(strlen(uuid_str) != GUID_LEN || uuid_parse(uuid_str, uuid) == -1)) { - error("requested a GUID, without a valid uuid string."); - return PARSER_RC_ERROR; - } +#ifdef NETDATA_LOG_REPLICATION_REQUESTS + internal_error( + (!st->replay.start_streaming && (end_time < st->replay.after || start_time > st->replay.before)), + "REPLAY ERROR: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_BEGIN " from %ld to %ld, which does not match our request (%ld to %ld).", + rrdhost_hostname(st->rrdhost), rrdset_id(st), start_time, end_time, st->replay.after, st->replay.before); + + internal_error( + true, + "REPLAY: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_BEGIN " from %ld to %ld, child wall clock is %ld (%s), had requested %ld to %ld", + rrdhost_hostname(st->rrdhost), rrdset_id(st), + start_time, end_time, wall_clock_time, wall_clock_comes_from_child ? "from child" : "parent time", + st->replay.after, st->replay.before); +#endif + + if(start_time && end_time && start_time < wall_clock_time + tolerance && end_time < wall_clock_time + tolerance && start_time < end_time) { + if (unlikely(end_time - start_time != st->update_every)) + rrdset_set_update_every(st, end_time - start_time); + + st->last_collected_time.tv_sec = end_time; + st->last_collected_time.tv_usec = 0; + + st->last_updated.tv_sec = end_time; + st->last_updated.tv_usec = 0; + + st->counter++; + st->counter_done++; + + // these are only needed for db mode RAM, SAVE, MAP, ALLOC + st->current_entry++; + if(st->current_entry >= st->entries) + st->current_entry -= st->entries; + + ((PARSER_USER_OBJECT *) user)->replay.start_time = start_time; + ((PARSER_USER_OBJECT *) user)->replay.end_time = end_time; + ((PARSER_USER_OBJECT *) user)->replay.start_time_ut = (usec_t) start_time * USEC_PER_SEC; + ((PARSER_USER_OBJECT *) user)->replay.end_time_ut = (usec_t) end_time * USEC_PER_SEC; + ((PARSER_USER_OBJECT *) user)->replay.wall_clock_time = wall_clock_time; + ((PARSER_USER_OBJECT *) user)->replay.rset_enabled = true; + + return PARSER_RC_OK; + } - debug(D_PLUGINSD, "Parsed uuid=%s", uuid_str); - if (plugins_action->guid_action) { - return plugins_action->guid_action(user, &uuid); + error("PLUGINSD REPLAY ERROR: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_BEGIN " from %ld to %ld, but timestamps are invalid (now is %ld [%s], tolerance %ld). Ignoring " PLUGINSD_KEYWORD_REPLAY_SET, + rrdhost_hostname(st->rrdhost), rrdset_id(st), start_time, end_time, + wall_clock_time, wall_clock_comes_from_child ? "child wall clock" : "parent wall clock", tolerance); } + // the child sends an RBEGIN without any parameters initially + // setting rset_enabled to false, means the RSET should not store any metrics + // to store metrics, the RBEGIN needs to have timestamps + ((PARSER_USER_OBJECT *) user)->replay.start_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.end_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.start_time_ut = 0; + ((PARSER_USER_OBJECT *) user)->replay.end_time_ut = 0; + ((PARSER_USER_OBJECT *) user)->replay.wall_clock_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.rset_enabled = false; return PARSER_RC_OK; } -PARSER_RC pluginsd_context(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_replay_set(char **words, size_t num_words, void *user) { - char *uuid_str = words[1]; - uuid_t uuid; + char *dimension = get_word(words, num_words, 1); + char *value_str = get_word(words, num_words, 2); + char *flags_str = get_word(words, num_words, 3); - if (unlikely(!uuid_str)) { - error("requested a CONTEXT, without a uuid."); - return PARSER_RC_ERROR; + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_SET); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_SET, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); + + if(!((PARSER_USER_OBJECT *) user)->replay.rset_enabled) { + error_limit_static_thread_var(erl, 1, 0); + error_limit(&erl, "PLUGINSD: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_SET " but it is disabled by " PLUGINSD_KEYWORD_REPLAY_BEGIN " errors", + rrdhost_hostname(host), rrdset_id(st)); + + // we have to return OK here + return PARSER_RC_OK; } - if (unlikely(strlen(uuid_str) != GUID_LEN || uuid_parse(uuid_str, uuid) == -1)) { - error("requested a CONTEXT, without a valid uuid string."); - return PARSER_RC_ERROR; + + RRDDIM_ACQUIRED *rda = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_SET); + if(!rda) return PLUGINSD_DISABLE_PLUGIN(user); + + if (unlikely(!((PARSER_USER_OBJECT *) user)->replay.start_time || !((PARSER_USER_OBJECT *) user)->replay.end_time)) { + error("PLUGINSD: 'host:%s/chart:%s/dim:%s' got a " PLUGINSD_KEYWORD_REPLAY_SET " with invalid timestamps %ld to %ld from a " PLUGINSD_KEYWORD_REPLAY_BEGIN ". Disabling it.", + rrdhost_hostname(host), + rrdset_id(st), + dimension, + ((PARSER_USER_OBJECT *) user)->replay.start_time, + ((PARSER_USER_OBJECT *) user)->replay.end_time); + return PLUGINSD_DISABLE_PLUGIN(user); + } + + if (unlikely(!value_str || !*value_str)) + value_str = "NAN"; + + if(unlikely(!flags_str)) + flags_str = ""; + + if (likely(value_str)) { + RRDDIM *rd = rrddim_acquired_to_rrddim(rda); + + RRDDIM_FLAGS rd_flags = rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE | RRDDIM_FLAG_ARCHIVED); + + if(!(rd_flags & RRDDIM_FLAG_ARCHIVED)) { + NETDATA_DOUBLE value = strtondd(value_str, NULL); + SN_FLAGS flags = SN_FLAG_NONE; + + char c; + while ((c = *flags_str++)) { + switch (c) { + case 'R': + flags |= SN_FLAG_RESET; + break; + + case 'E': + flags |= SN_EMPTY_SLOT; + value = NAN; + break; + + default: + error("unknown flag '%c'", c); + break; + } + } + + if (!netdata_double_isnumber(value)) { + value = NAN; + flags = SN_EMPTY_SLOT; + } + + rrddim_store_metric(rd, ((PARSER_USER_OBJECT *) user)->replay.end_time_ut, value, flags); + rd->last_collected_time.tv_sec = ((PARSER_USER_OBJECT *) user)->replay.end_time; + rd->last_collected_time.tv_usec = 0; + rd->collections_counter++; + } + else { + error_limit_static_global_var(erl, 1, 0); + error_limit(&erl, "PLUGINSD: 'host:%s/chart:%s/dim:%s' has the ARCHIVED flag set, but it is replicated. Ignoring data.", + rrdhost_hostname(st->rrdhost), rrdset_id(st), rrddim_name(rd)); + } } - debug(D_PLUGINSD, "Parsed uuid=%s", uuid_str); - if (plugins_action->context_action) { - return plugins_action->context_action(user, &uuid); + rrddim_acquired_release(rda); + return PARSER_RC_OK; +} + +PARSER_RC pluginsd_replay_rrddim_collection_state(char **words, size_t num_words, void *user) +{ + char *dimension = get_word(words, num_words, 1); + char *last_collected_ut_str = get_word(words, num_words, 2); + char *last_collected_value_str = get_word(words, num_words, 3); + char *last_calculated_value_str = get_word(words, num_words, 4); + char *last_stored_value_str = get_word(words, num_words, 5); + + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDDIM_ACQUIRED *rda = pluginsd_acquire_dimension(host, st, dimension, PLUGINSD_KEYWORD_REPLAY_RRDDIM_STATE); + if(!rda) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDDIM *rd = rrddim_acquired_to_rrddim(rda); + usec_t dim_last_collected_ut = (usec_t)rd->last_collected_time.tv_sec * USEC_PER_SEC + (usec_t)rd->last_collected_time.tv_usec; + usec_t last_collected_ut = last_collected_ut_str ? str2ull(last_collected_ut_str) : 0; + if(last_collected_ut > dim_last_collected_ut) { + rd->last_collected_time.tv_sec = last_collected_ut / USEC_PER_SEC; + rd->last_collected_time.tv_usec = last_collected_ut % USEC_PER_SEC; } + rd->last_collected_value = last_collected_value_str ? str2ll(last_collected_value_str, NULL) : 0; + rd->last_calculated_value = last_calculated_value_str ? str2ndd(last_calculated_value_str, NULL) : 0; + rd->last_stored_value = last_stored_value_str ? str2ndd(last_stored_value_str, NULL) : 0.0; + rrddim_acquired_release(rda); return PARSER_RC_OK; } -PARSER_RC pluginsd_tombstone(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_replay_rrdset_collection_state(char **words, size_t num_words, void *user) { - char *uuid_str = words[1]; - uuid_t uuid; + char *last_collected_ut_str = get_word(words, num_words, 1); + char *last_updated_ut_str = get_word(words, num_words, 2); - if (unlikely(!uuid_str)) { - error("requested a TOMBSTONE, without a uuid."); - return PARSER_RC_ERROR; - } - if (unlikely(strlen(uuid_str) != GUID_LEN || uuid_parse(uuid_str, uuid) == -1)) { - error("requested a TOMBSTONE, without a valid uuid string."); - return PARSER_RC_ERROR; + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDSET_STATE); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_RRDSET_STATE, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); + + usec_t chart_last_collected_ut = (usec_t)st->last_collected_time.tv_sec * USEC_PER_SEC + (usec_t)st->last_collected_time.tv_usec; + usec_t last_collected_ut = last_collected_ut_str ? str2ull(last_collected_ut_str) : 0; + if(last_collected_ut > chart_last_collected_ut) { + st->last_collected_time.tv_sec = last_collected_ut / USEC_PER_SEC; + st->last_collected_time.tv_usec = last_collected_ut % USEC_PER_SEC; } - debug(D_PLUGINSD, "Parsed uuid=%s", uuid_str); - if (plugins_action->tombstone_action) { - return plugins_action->tombstone_action(user, &uuid); + usec_t chart_last_updated_ut = (usec_t)st->last_updated.tv_sec * USEC_PER_SEC + (usec_t)st->last_updated.tv_usec; + usec_t last_updated_ut = last_updated_ut_str ? str2ull(last_updated_ut_str) : 0; + if(last_updated_ut > chart_last_updated_ut) { + st->last_updated.tv_sec = last_updated_ut / USEC_PER_SEC; + st->last_updated.tv_usec = last_updated_ut % USEC_PER_SEC; } + st->counter++; + st->counter_done++; + return PARSER_RC_OK; } -PARSER_RC metalog_pluginsd_host(char **words, void *user, PLUGINSD_ACTION *plugins_action) +PARSER_RC pluginsd_replay_end(char **words, size_t num_words, void *user) { - char *machine_guid = words[1]; - char *hostname = words[2]; - char *registry_hostname = words[3]; - char *update_every_s = words[4]; - char *os = words[5]; - char *timezone = words[6]; - char *tags = words[7]; - - int update_every = 1; - if (likely(update_every_s && *update_every_s)) - update_every = str2i(update_every_s); - if (unlikely(!update_every)) - update_every = 1; + if (num_words < 7) { // accepts 7, but the 7th is optional + error("REPLAY: malformed " PLUGINSD_KEYWORD_REPLAY_END " command"); + return PARSER_RC_ERROR; + } - debug(D_PLUGINSD, "HOST PARSED: guid=%s, hostname=%s, reg_host=%s, update=%d, os=%s, timezone=%s, tags=%s", - machine_guid, hostname, registry_hostname, update_every, os, timezone, tags); + const char *update_every_child_txt = get_word(words, num_words, 1); + const char *first_entry_child_txt = get_word(words, num_words, 2); + const char *last_entry_child_txt = get_word(words, num_words, 3); + const char *start_streaming_txt = get_word(words, num_words, 4); + const char *first_entry_requested_txt = get_word(words, num_words, 5); + const char *last_entry_requested_txt = get_word(words, num_words, 6); + const char *child_world_time_txt = get_word(words, num_words, 7); // optional - if (plugins_action->host_action) { - return plugins_action->host_action( - user, machine_guid, hostname, registry_hostname, update_every, os, timezone, tags); + time_t update_every_child = (time_t)str2ul(update_every_child_txt); + time_t first_entry_child = (time_t)str2ul(first_entry_child_txt); + time_t last_entry_child = (time_t)str2ul(last_entry_child_txt); + + bool start_streaming = (strcmp(start_streaming_txt, "true") == 0); + time_t first_entry_requested = (time_t)str2ul(first_entry_requested_txt); + time_t last_entry_requested = (time_t)str2ul(last_entry_requested_txt); + + // the optional child world time + time_t child_world_time = (child_world_time_txt && *child_world_time_txt) ? (time_t)str2ul(child_world_time_txt) : now_realtime_sec(); + + PARSER_USER_OBJECT *user_object = user; + + RRDHOST *host = pluginsd_require_host_from_parent(user, PLUGINSD_KEYWORD_REPLAY_END); + if(!host) return PLUGINSD_DISABLE_PLUGIN(user); + + RRDSET *st = pluginsd_require_chart_from_parent(user, PLUGINSD_KEYWORD_REPLAY_END, PLUGINSD_KEYWORD_REPLAY_BEGIN); + if(!st) return PLUGINSD_DISABLE_PLUGIN(user); + +#ifdef NETDATA_LOG_REPLICATION_REQUESTS + internal_error(true, + "PLUGINSD REPLAY: 'host:%s/chart:%s': got a " PLUGINSD_KEYWORD_REPLAY_END " child db from %llu to %llu, start_streaming %s, had requested from %llu to %llu, wall clock %llu", + rrdhost_hostname(host), rrdset_id(st), + (unsigned long long)first_entry_child, (unsigned long long)last_entry_child, + start_streaming?"true":"false", + (unsigned long long)first_entry_requested, (unsigned long long)last_entry_requested, + (unsigned long long)child_world_time + ); +#endif + + ((PARSER_USER_OBJECT *) user)->st = NULL; + ((PARSER_USER_OBJECT *) user)->count++; + + if(((PARSER_USER_OBJECT *) user)->replay.rset_enabled && st->rrdhost->receiver) { + time_t now = now_realtime_sec(); + time_t started = st->rrdhost->receiver->replication_first_time_t; + time_t current = ((PARSER_USER_OBJECT *) user)->replay.end_time; + + worker_set_metric(WORKER_RECEIVER_JOB_REPLICATION_COMPLETION, + (NETDATA_DOUBLE)(current - started) * 100.0 / (NETDATA_DOUBLE)(now - started)); } - return PARSER_RC_OK; + ((PARSER_USER_OBJECT *) user)->replay.start_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.end_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.start_time_ut = 0; + ((PARSER_USER_OBJECT *) user)->replay.end_time_ut = 0; + ((PARSER_USER_OBJECT *) user)->replay.wall_clock_time = 0; + ((PARSER_USER_OBJECT *) user)->replay.rset_enabled = false; + + st->counter++; + st->counter_done++; + +#ifdef NETDATA_LOG_REPLICATION_REQUESTS + st->replay.start_streaming = false; + st->replay.after = 0; + st->replay.before = 0; + if(start_streaming) + st->replay.log_next_data_collection = true; +#endif + + if (start_streaming) { + if (st->update_every != update_every_child) + rrdset_set_update_every(st, update_every_child); + + if(rrdset_flag_check(st, RRDSET_FLAG_RECEIVER_REPLICATION_IN_PROGRESS)) { + rrdset_flag_set(st, RRDSET_FLAG_RECEIVER_REPLICATION_FINISHED); + rrdset_flag_clear(st, RRDSET_FLAG_RECEIVER_REPLICATION_IN_PROGRESS); + rrdset_flag_clear(st, RRDSET_FLAG_SYNC_CLOCK); + rrdhost_receiver_replicating_charts_minus_one(st->rrdhost); + } +#ifdef NETDATA_LOG_REPLICATION_REQUESTS + else + internal_error(true, "REPLAY ERROR: 'host:%s/chart:%s' got a " PLUGINSD_KEYWORD_REPLAY_END " with enable_streaming = true, but there is no replication in progress for this chart.", + rrdhost_hostname(host), rrdset_id(st)); +#endif + worker_set_metric(WORKER_RECEIVER_JOB_REPLICATION_COMPLETION, 100.0); + + return PARSER_RC_OK; + } + + rrdcontext_updated_retention_rrdset(st); + + bool ok = replicate_chart_request(send_to_plugin, user_object->parser, host, st, + first_entry_child, last_entry_child, child_world_time, + first_entry_requested, last_entry_requested); + return ok ? PARSER_RC_OK : PARSER_RC_ERROR; } static void pluginsd_process_thread_cleanup(void *ptr) { PARSER *parser = (PARSER *)ptr; + rrd_collector_finished(); parser_destroy(parser); } // New plugins.d parser -inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations) +inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp_plugin_input, FILE *fp_plugin_output, int trust_durations) { int enabled = cd->enabled; - if (!fp || !enabled) { + if (!fp_plugin_input || !fp_plugin_output || !enabled) { cd->enabled = 0; return 0; } - if (unlikely(fileno(fp) == -1)) { - error("file descriptor given is not a valid stream"); + if (unlikely(fileno(fp_plugin_input) == -1)) { + error("input file descriptor given is not a valid stream"); cd->serial_failures++; return 0; } - clearerr(fp); + + if (unlikely(fileno(fp_plugin_output) == -1)) { + error("output file descriptor given is not a valid stream"); + cd->serial_failures++; + return 0; + } + + clearerr(fp_plugin_input); + clearerr(fp_plugin_output); PARSER_USER_OBJECT user = { .enabled = cd->enabled, @@ -773,25 +1327,15 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int .trust_durations = trust_durations }; - PARSER *parser = parser_init(host, &user, fp, PARSER_INPUT_SPLIT); + // fp_plugin_output = our input; fp_plugin_input = our output + PARSER *parser = parser_init(host, &user, fp_plugin_output, fp_plugin_input, -1, PARSER_INPUT_SPLIT, NULL); + + rrd_collector_started(); // this keeps the parser with its current value // so, parser needs to be allocated before pushing it netdata_thread_cleanup_push(pluginsd_process_thread_cleanup, parser); - parser->plugins_action->begin_action = &pluginsd_begin_action; - parser->plugins_action->flush_action = &pluginsd_flush_action; - parser->plugins_action->end_action = &pluginsd_end_action; - parser->plugins_action->disable_action = &pluginsd_disable_action; - parser->plugins_action->variable_action = &pluginsd_variable_action; - parser->plugins_action->dimension_action = &pluginsd_dimension_action; - parser->plugins_action->label_action = &pluginsd_label_action; - parser->plugins_action->overwrite_action = &pluginsd_overwrite_action; - parser->plugins_action->chart_action = &pluginsd_chart_action; - parser->plugins_action->set_action = &pluginsd_set_action; - parser->plugins_action->clabel_commit_action = &pluginsd_clabel_commit_action; - parser->plugins_action->clabel_action = &pluginsd_clabel_action; - user.parser = parser; while (likely(!parser_next(parser))) { diff --git a/collectors/plugins.d/pluginsd_parser.h b/collectors/plugins.d/pluginsd_parser.h index 924d48b7b..e18b43e58 100644 --- a/collectors/plugins.d/pluginsd_parser.h +++ b/collectors/plugins.d/pluginsd_parser.h @@ -5,7 +5,6 @@ #include "parser/parser.h" - typedef struct parser_user_object { PARSER *parser; RRDSET *st; @@ -14,29 +13,27 @@ typedef struct parser_user_object { struct plugind *cd; int trust_durations; DICTIONARY *new_host_labels; - DICTIONARY *new_chart_labels; + DICTIONARY *chart_rrdlabels_linked_temporarily; size_t count; int enabled; uint8_t st_exists; uint8_t host_exists; void *private; // the user can set this for private use -} PARSER_USER_OBJECT; -extern PARSER_RC pluginsd_set_action(void *user, RRDSET *st, RRDDIM *rd, long long int value); -extern PARSER_RC pluginsd_flush_action(void *user, RRDSET *st); -extern PARSER_RC pluginsd_begin_action(void *user, RRDSET *st, usec_t microseconds, int trust_durations); -extern PARSER_RC pluginsd_end_action(void *user, RRDSET *st); -extern PARSER_RC pluginsd_chart_action(void *user, char *type, char *id, char *name, char *family, char *context, - char *title, char *units, char *plugin, char *module, int priority, - int update_every, RRDSET_TYPE chart_type, char *options); -extern PARSER_RC pluginsd_disable_action(void *user); -extern PARSER_RC pluginsd_variable_action(void *user, RRDHOST *host, RRDSET *st, char *name, int global, NETDATA_DOUBLE value); -extern PARSER_RC pluginsd_dimension_action(void *user, RRDSET *st, char *id, char *name, char *algorithm, - long multiplier, long divisor, char *options, RRD_ALGORITHM algorithm_type); -extern PARSER_RC pluginsd_label_action(void *user, char *key, char *value, RRDLABEL_SRC source); -extern PARSER_RC pluginsd_overwrite_action(void *user, RRDHOST *host, DICTIONARY *new_host_labels); -extern PARSER_RC pluginsd_clabel_commit_action(void *user, RRDHOST *host, DICTIONARY *new_chart_labels); -extern PARSER_RC pluginsd_clabel_action(void *user, char *key, char *value, RRDLABEL_SRC source); + struct { + time_t start_time; + time_t end_time; + + usec_t start_time_ut; + usec_t end_time_ut; + time_t wall_clock_time; + + bool rset_enabled; + } replay; +} PARSER_USER_OBJECT; +PARSER_RC pluginsd_function(char **words, size_t num_words, void *user); +PARSER_RC pluginsd_function_result_begin(char **words, size_t num_words, void *user); +void inflight_functions_init(PARSER *parser); #endif //NETDATA_PLUGINSD_PARSER_H diff --git a/collectors/proc.plugin/ipc.c b/collectors/proc.plugin/ipc.c index b5c9ae5e1..9185894eb 100644 --- a/collectors/proc.plugin/ipc.c +++ b/collectors/proc.plugin/ipc.c @@ -281,7 +281,7 @@ int do_ipc(int update_every, usec_t dt) { static int read_limits_next = -1; static struct ipc_limits limits; static struct ipc_status status; - static RRDVAR *arrays_max = NULL, *semaphores_max = NULL; + static const RRDVAR_ACQUIRED *arrays_max = NULL, *semaphores_max = NULL; static RRDSET *st_semaphores = NULL, *st_arrays = NULL; static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL; static char *msg_filename = NULL; @@ -352,8 +352,8 @@ int do_ipc(int update_every, usec_t dt) { } // variables - semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_max"); - arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_arrays_max"); + semaphores_max = rrdvar_custom_host_variable_add_and_acquire(localhost, "ipc_semaphores_max"); + arrays_max = rrdvar_custom_host_variable_add_and_acquire(localhost, "ipc_semaphores_arrays_max"); } struct stat stbuf; @@ -390,17 +390,13 @@ int do_ipc(int update_every, usec_t dt) { return 0; } - if(st_semaphores->counter_done) rrdset_next(st_semaphores); rrddim_set_by_pointer(st_semaphores, rd_semaphores, status.semaem); rrdset_done(st_semaphores); - if(st_arrays->counter_done) rrdset_next(st_arrays); rrddim_set_by_pointer(st_arrays, rd_arrays, status.semusz); rrdset_done(st_arrays); } - // -------------------------------------------------------------------- - if(likely(do_msg != CONFIG_BOOLEAN_NO)) { static RRDSET *st_msq_messages = NULL, *st_msq_bytes = NULL; @@ -422,8 +418,6 @@ int do_ipc(int update_every, usec_t dt) { , update_every , RRDSET_TYPE_STACKED ); - else - rrdset_next(st_msq_messages); if(unlikely(!st_msq_bytes)) st_msq_bytes = rrdset_create_localhost( @@ -440,8 +434,6 @@ int do_ipc(int update_every, usec_t dt) { , update_every , RRDSET_TYPE_STACKED ); - else - rrdset_next(st_msq_bytes); struct message_queue *msq = message_queue_root, *msq_prev = NULL; while(likely(msq)){ @@ -483,11 +475,7 @@ int do_ipc(int update_every, usec_t dt) { rrdset_done(st_msq_messages); rrdset_done(st_msq_bytes); - long long dimensions_num = 0; - RRDDIM *rd; - rrdset_rdlock(st_msq_messages); - rrddim_foreach_read(rd, st_msq_messages) dimensions_num++; - rrdset_unlock(st_msq_messages); + long long dimensions_num = rrdset_number_of_dimensions(st_msq_messages); if(unlikely(dimensions_num > dimensions_limit)) { info("Message queue statistics has been disabled"); @@ -499,19 +487,17 @@ int do_ipc(int update_every, usec_t dt) { do_msg = CONFIG_BOOLEAN_NO; } else if(unlikely(!message_queue_root)) { - info("Making chart %s (%s) obsolete since it does not have any dimensions", st_msq_messages->name, st_msq_messages->id); + info("Making chart %s (%s) obsolete since it does not have any dimensions", rrdset_name(st_msq_messages), rrdset_id(st_msq_messages)); rrdset_is_obsolete(st_msq_messages); st_msq_messages = NULL; - info("Making chart %s (%s) obsolete since it does not have any dimensions", st_msq_bytes->name, st_msq_bytes->id); + info("Making chart %s (%s) obsolete since it does not have any dimensions", rrdset_name(st_msq_bytes), rrdset_id(st_msq_bytes)); rrdset_is_obsolete(st_msq_bytes); st_msq_bytes = NULL; } } } - // -------------------------------------------------------------------- - if(likely(do_shm != CONFIG_BOOLEAN_NO)) { static RRDSET *st_shm_segments = NULL, *st_shm_bytes = NULL; static RRDDIM *rd_shm_segments = NULL, *rd_shm_bytes = NULL; @@ -536,15 +522,10 @@ int do_ipc(int update_every, usec_t dt) { rd_shm_segments = rrddim_add(st_shm_segments, "segments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_shm_segments); rrddim_set_by_pointer(st_shm_segments, rd_shm_segments, shm.segments); - rrdset_done(st_shm_segments); - // -------------------------------------------------------------------- - if(unlikely(!st_shm_bytes)) { st_shm_bytes = rrdset_create_localhost( "system" @@ -563,11 +544,8 @@ int do_ipc(int update_every, usec_t dt) { rd_shm_bytes = rrddim_add(st_shm_bytes, "bytes", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_shm_bytes); rrddim_set_by_pointer(st_shm_bytes, rd_shm_bytes, shm.bytes); - rrdset_done(st_shm_bytes); } } diff --git a/collectors/proc.plugin/plugin_proc.c b/collectors/proc.plugin/plugin_proc.c index 5033aa5e2..1b24df45f 100644 --- a/collectors/proc.plugin/plugin_proc.c +++ b/collectors/proc.plugin/plugin_proc.c @@ -40,11 +40,7 @@ static struct proc_module { {.name = "/proc/net/wireless", .dim = "netwireless", .func = do_proc_net_wireless}, {.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}, + {.name = "/proc/net/netstat", .dim = "netstat", .func = do_proc_net_netstat}, {.name = "/proc/net/sctp/snmp", .dim = "sctp", .func = do_proc_net_sctp_snmp}, {.name = "/proc/net/softnet_stat", .dim = "softnet", .func = do_proc_net_softnet_stat}, {.name = "/proc/net/ip_vs/stats", .dim = "ipvs", .func = do_proc_net_ip_vs_stats}, diff --git a/collectors/proc.plugin/plugin_proc.h b/collectors/proc.plugin/plugin_proc.h index 8cb5431e5..d67ccd6e5 100644 --- a/collectors/proc.plugin/plugin_proc.h +++ b/collectors/proc.plugin/plugin_proc.h @@ -9,58 +9,55 @@ #define PLUGIN_PROC_NAME PLUGIN_PROC_CONFIG_NAME ".plugin" #define THREAD_NETDEV_NAME "PLUGIN[proc netdev]" -extern void *netdev_main(void *ptr); +void *netdev_main(void *ptr); -extern int do_proc_net_wireless(int update_every, usec_t dt); -extern int do_proc_diskstats(int update_every, usec_t dt); -extern int do_proc_mdstat(int update_every, usec_t dt); -extern int do_proc_net_snmp(int update_every, usec_t dt); -extern int do_proc_net_snmp6(int update_every, usec_t dt); -extern int do_proc_net_netstat(int update_every, usec_t dt); -extern int do_proc_net_stat_conntrack(int update_every, usec_t dt); -extern int do_proc_net_ip_vs_stats(int update_every, usec_t dt); -extern int do_proc_stat(int update_every, usec_t dt); -extern int do_proc_meminfo(int update_every, usec_t dt); -extern int do_proc_vmstat(int update_every, usec_t dt); -extern int do_proc_net_rpc_nfs(int update_every, usec_t dt); -extern int do_proc_net_rpc_nfsd(int update_every, usec_t dt); -extern int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt); -extern int do_proc_interrupts(int update_every, usec_t dt); -extern int do_proc_softirqs(int update_every, usec_t dt); -extern int do_proc_pressure(int update_every, usec_t dt); -extern int do_sys_kernel_mm_ksm(int update_every, usec_t dt); -extern int do_sys_block_zram(int update_every, usec_t dt); -extern int do_proc_loadavg(int update_every, usec_t dt); -extern int do_proc_net_stat_synproxy(int update_every, usec_t dt); -extern int do_proc_net_softnet_stat(int update_every, usec_t dt); -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_spl_kstat_zfs_pool_state(int update_every, usec_t dt); -extern int do_sys_fs_btrfs(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 do_proc_net_sctp_snmp(int update_every, usec_t dt); -extern int do_ipc(int update_every, usec_t dt); -extern int do_sys_class_power_supply(int update_every, usec_t dt); -extern int do_proc_pagetypeinfo(int update_every, usec_t dt); -extern int do_sys_class_infiniband(int update_every, usec_t dt); -extern int get_numa_node_count(void); +int do_proc_net_wireless(int update_every, usec_t dt); +int do_proc_diskstats(int update_every, usec_t dt); +int do_proc_mdstat(int update_every, usec_t dt); +int do_proc_net_netstat(int update_every, usec_t dt); +int do_proc_net_stat_conntrack(int update_every, usec_t dt); +int do_proc_net_ip_vs_stats(int update_every, usec_t dt); +int do_proc_stat(int update_every, usec_t dt); +int do_proc_meminfo(int update_every, usec_t dt); +int do_proc_vmstat(int update_every, usec_t dt); +int do_proc_net_rpc_nfs(int update_every, usec_t dt); +int do_proc_net_rpc_nfsd(int update_every, usec_t dt); +int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt); +int do_proc_interrupts(int update_every, usec_t dt); +int do_proc_softirqs(int update_every, usec_t dt); +int do_proc_pressure(int update_every, usec_t dt); +int do_sys_kernel_mm_ksm(int update_every, usec_t dt); +int do_sys_block_zram(int update_every, usec_t dt); +int do_proc_loadavg(int update_every, usec_t dt); +int do_proc_net_stat_synproxy(int update_every, usec_t dt); +int do_proc_net_softnet_stat(int update_every, usec_t dt); +int do_proc_uptime(int update_every, usec_t dt); +int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt); +int do_proc_sys_devices_system_node(int update_every, usec_t dt); +int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt); +int do_proc_spl_kstat_zfs_pool_state(int update_every, usec_t dt); +int do_sys_fs_btrfs(int update_every, usec_t dt); +int do_proc_net_sockstat(int update_every, usec_t dt); +int do_proc_net_sockstat6(int update_every, usec_t dt); +int do_proc_net_sctp_snmp(int update_every, usec_t dt); +int do_ipc(int update_every, usec_t dt); +int do_sys_class_power_supply(int update_every, usec_t dt); +int do_proc_pagetypeinfo(int update_every, usec_t dt); +int do_sys_class_infiniband(int update_every, usec_t dt); +int get_numa_node_count(void); // metrics that need to be shared among data collectors -extern unsigned long long tcpext_TCPSynRetrans; extern unsigned long long zfs_arcstats_shrinkable_cache_size_bytes; // netdev renames -extern void netdev_rename_device_add( +void netdev_rename_device_add( const char *host_device, const char *container_device, const char *container_name, DICTIONARY *labels, const char *ctx_prefix); -extern void netdev_rename_device_del(const char *host_device); +void netdev_rename_device_del(const char *host_device); #include "proc_self_mountinfo.h" #include "proc_pressure.h" diff --git a/collectors/proc.plugin/proc_diskstats.c b/collectors/proc.plugin/proc_diskstats.c index be4a481cd..28d0e7584 100644 --- a/collectors/proc.plugin/proc_diskstats.c +++ b/collectors/proc.plugin/proc_diskstats.c @@ -25,6 +25,8 @@ static struct disk { char *mount_point; + char *chart_id; + // disk options caching int do_io; int do_ops; @@ -283,7 +285,7 @@ void bcache_read_priority_stats(struct disk *d, const char *family, int update_e if(unlikely(!d->st_bcache_cache_allocations)) { d->st_bcache_cache_allocations = rrdset_create_localhost( "disk_bcache_cache_alloc" - , d->device + , d->chart_id , d->disk , family , "disk.bcache_cache_alloc" @@ -304,7 +306,6 @@ void bcache_read_priority_stats(struct disk *d, const char *family, int update_e d->bcache_priority_stats_update_every_usec = update_every * USEC_PER_SEC; } - else rrdset_next(d->st_bcache_cache_allocations); rrddim_set_by_pointer(d->st_bcache_cache_allocations, d->rd_bcache_cache_allocations_unused, unused); rrddim_set_by_pointer(d->st_bcache_cache_allocations, d->rd_bcache_cache_allocations_dirty, dirty); @@ -609,6 +610,26 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis last->next = d; } + d->chart_id = strdupz(d->device); + + // read device uuid if it is an LVM volume + if (!strncmp(d->device, "dm-", 3)) { + char uuid_filename[FILENAME_MAX + 1]; + snprintfz(uuid_filename, FILENAME_MAX, path_to_sys_devices_virtual_block_device, disk); + strncat(uuid_filename, "/dm/uuid", FILENAME_MAX); + + char device_uuid[RRD_ID_LENGTH_MAX + 1]; + if (!read_file(uuid_filename, device_uuid, RRD_ID_LENGTH_MAX) && !strncmp(device_uuid, "LVM-", 4)) { + trim(device_uuid); + + char chart_id[RRD_ID_LENGTH_MAX + 1]; + snprintf(chart_id, RRD_ID_LENGTH_MAX, "%s-%s", d->device, device_uuid + 4); + + freez(d->chart_id); + d->chart_id = strdupz(chart_id); + } + } + char buffer[FILENAME_MAX + 1]; // find if it is a physical disk @@ -831,25 +852,25 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis } static void add_labels_to_disk(struct disk *d, RRDSET *st) { - rrdlabels_add(st->state->chart_labels, "device", d->disk, RRDLABEL_SRC_AUTO); - rrdlabels_add(st->state->chart_labels, "mount_point", d->mount_point, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device", d->disk, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "mount_point", d->mount_point, RRDLABEL_SRC_AUTO); switch (d->type) { default: case DISK_TYPE_UNKNOWN: - rrdlabels_add(st->state->chart_labels, "device_type", "unknown", RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device_type", "unknown", RRDLABEL_SRC_AUTO); break; case DISK_TYPE_PHYSICAL: - rrdlabels_add(st->state->chart_labels, "device_type", "physical", RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device_type", "physical", RRDLABEL_SRC_AUTO); break; case DISK_TYPE_PARTITION: - rrdlabels_add(st->state->chart_labels, "device_type", "partition", RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device_type", "partition", RRDLABEL_SRC_AUTO); break; case DISK_TYPE_VIRTUAL: - rrdlabels_add(st->state->chart_labels, "device_type", "virtual", RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device_type", "virtual", RRDLABEL_SRC_AUTO); break; } } @@ -1076,7 +1097,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_io)) { d->st_io = rrdset_create_localhost( RRD_TYPE_DISK - , d->device + , d->chart_id , d->disk , family , "disk.io" @@ -1094,20 +1115,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_io); } - else rrdset_next(d->st_io); 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); } - // -------------------------------------------------------------------- - if (do_dc_stats && d->do_io == CONFIG_BOOLEAN_YES && d->do_ext != CONFIG_BOOLEAN_NO) { if (unlikely(!d->st_ext_io)) { d->st_ext_io = rrdset_create_localhost( "disk_ext" - , d->device + , d->chart_id , d->disk , family , "disk_ext.io" @@ -1123,15 +1141,12 @@ int do_proc_diskstats(int update_every, usec_t dt) { d->rd_io_discards = rrddim_add(d->st_ext_io, "discards", NULL, d->sector_size, 1024, RRD_ALGORITHM_INCREMENTAL); add_labels_to_disk(d, d->st_ext_io); - } else - rrdset_next(d->st_ext_io); + } last_discardsectors = rrddim_set_by_pointer(d->st_ext_io, d->rd_io_discards, discardsectors); rrdset_done(d->st_ext_io); } - // -------------------------------------------------------------------- - if(d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes || discards || flushes || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -1140,7 +1155,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_ops)) { d->st_ops = rrdset_create_localhost( "disk_ops" - , d->device + , d->chart_id , d->disk , family , "disk.ops" @@ -1160,20 +1175,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_ops); } - else rrdset_next(d->st_ops); 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); } - // -------------------------------------------------------------------- - if (do_dc_stats && d->do_ops == CONFIG_BOOLEAN_YES && d->do_ext != CONFIG_BOOLEAN_NO) { if (unlikely(!d->st_ext_ops)) { d->st_ext_ops = rrdset_create_localhost( "disk_ext_ops" - , d->device + , d->chart_id , d->disk , family , "disk_ext.ops" @@ -1194,8 +1206,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_ext_ops); } - else - rrdset_next(d->st_ext_ops); last_discards = rrddim_set_by_pointer(d->st_ext_ops, d->rd_ops_discards, discards); if (do_fl_stats) @@ -1203,8 +1213,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_done(d->st_ext_ops); } - // -------------------------------------------------------------------- - if(d->do_qops == CONFIG_BOOLEAN_YES || (d->do_qops == CONFIG_BOOLEAN_AUTO && (queued_ios || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { d->do_qops = CONFIG_BOOLEAN_YES; @@ -1212,7 +1220,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_qops)) { d->st_qops = rrdset_create_localhost( "disk_qops" - , d->device + , d->chart_id , d->disk , family , "disk.qops" @@ -1231,14 +1239,11 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_qops); } - else rrdset_next(d->st_qops); rrddim_set_by_pointer(d->st_qops, d->rd_qops_operations, queued_ios); rrdset_done(d->st_qops); } - // -------------------------------------------------------------------- - if(d->do_backlog == CONFIG_BOOLEAN_YES || (d->do_backlog == CONFIG_BOOLEAN_AUTO && (backlog_ms || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { d->do_backlog = CONFIG_BOOLEAN_YES; @@ -1246,7 +1251,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_backlog)) { d->st_backlog = rrdset_create_localhost( "disk_backlog" - , d->device + , d->chart_id , d->disk , family , "disk.backlog" @@ -1265,14 +1270,11 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_backlog); } - else rrdset_next(d->st_backlog); rrddim_set_by_pointer(d->st_backlog, d->rd_backlog_backlog, backlog_ms); rrdset_done(d->st_backlog); } - // -------------------------------------------------------------------- - if(d->do_util == CONFIG_BOOLEAN_YES || (d->do_util == CONFIG_BOOLEAN_AUTO && (busy_ms || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { d->do_util = CONFIG_BOOLEAN_YES; @@ -1280,7 +1282,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_busy)) { d->st_busy = rrdset_create_localhost( "disk_busy" - , d->device + , d->chart_id , d->disk , family , "disk.busy" @@ -1299,17 +1301,14 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_busy); } - else rrdset_next(d->st_busy); last_busy_ms = rrddim_set_by_pointer(d->st_busy, d->rd_busy_busy, busy_ms); rrdset_done(d->st_busy); - // -------------------------------------------------------------------- - if(unlikely(!d->st_util)) { d->st_util = rrdset_create_localhost( "disk_util" - , d->device + , d->chart_id , d->disk , family , "disk.util" @@ -1328,7 +1327,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_util); } - else rrdset_next(d->st_util); collected_number disk_utilization = (busy_ms - last_busy_ms) / (10 * update_every); if (disk_utilization > 100) @@ -1338,8 +1336,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_done(d->st_util); } - // -------------------------------------------------------------------- - if(d->do_mops == CONFIG_BOOLEAN_YES || (d->do_mops == CONFIG_BOOLEAN_AUTO && (mreads || mwrites || mdiscards || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -1348,7 +1344,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_mops)) { d->st_mops = rrdset_create_localhost( "disk_mops" - , d->device + , d->chart_id , d->disk , family , "disk.mops" @@ -1368,22 +1364,19 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_mops); } - else rrdset_next(d->st_mops); 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); } - // -------------------------------------------------------------------- - if(do_dc_stats && d->do_mops == CONFIG_BOOLEAN_YES && d->do_ext != CONFIG_BOOLEAN_NO) { d->do_mops = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_ext_mops)) { d->st_ext_mops = rrdset_create_localhost( "disk_ext_mops" - , d->device + , d->chart_id , d->disk , family , "disk_ext.mops" @@ -1402,15 +1395,11 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_ext_mops); } - else - rrdset_next(d->st_ext_mops); rrddim_set_by_pointer(d->st_ext_mops, d->rd_mops_discards, mdiscards); rrdset_done(d->st_ext_mops); } - // -------------------------------------------------------------------- - if(d->do_iotime == CONFIG_BOOLEAN_YES || (d->do_iotime == CONFIG_BOOLEAN_AUTO && (readms || writems || discardms || flushms || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { d->do_iotime = CONFIG_BOOLEAN_YES; @@ -1418,7 +1407,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_iotime)) { d->st_iotime = rrdset_create_localhost( "disk_iotime" - , d->device + , d->chart_id , d->disk , family , "disk.iotime" @@ -1438,20 +1427,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_iotime); } - else rrdset_next(d->st_iotime); 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); } - // -------------------------------------------------------------------- - if(do_dc_stats && d->do_iotime == CONFIG_BOOLEAN_YES && d->do_ext != CONFIG_BOOLEAN_NO) { if(unlikely(!d->st_ext_iotime)) { d->st_ext_iotime = rrdset_create_localhost( "disk_ext_iotime" - , d->device + , d->chart_id , d->disk , family , "disk_ext.iotime" @@ -1472,8 +1458,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_ext_iotime); } - else - rrdset_next(d->st_ext_iotime); last_discardms = rrddim_set_by_pointer(d->st_ext_iotime, d->rd_iotime_discards, discardms); if (do_fl_stats) @@ -1481,7 +1465,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_done(d->st_ext_iotime); } - // -------------------------------------------------------------------- // calculate differential charts // only if this is not the first time we run @@ -1496,7 +1479,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_await)) { d->st_await = rrdset_create_localhost( "disk_await" - , d->device + , d->chart_id , d->disk , family , "disk.await" @@ -1516,7 +1499,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_await); } - else rrdset_next(d->st_await); 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); @@ -1527,7 +1509,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_ext_await)) { d->st_ext_await = rrdset_create_localhost( "disk_ext_await" - , d->device + , d->chart_id , d->disk , family , "disk_ext.await" @@ -1548,8 +1530,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_ext_await); } - else - rrdset_next(d->st_ext_await); rrddim_set_by_pointer( d->st_ext_await, d->rd_await_discards, @@ -1571,7 +1551,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_avgsz)) { d->st_avgsz = rrdset_create_localhost( "disk_avgsz" - , d->device + , d->chart_id , d->disk , family , "disk.avgsz" @@ -1591,7 +1571,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_avgsz); } - else rrdset_next(d->st_avgsz); 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); @@ -1602,7 +1581,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_ext_avgsz)) { d->st_ext_avgsz = rrdset_create_localhost( "disk_ext_avgsz" - , d->device + , d->chart_id , d->disk , family , "disk_ext.avgsz" @@ -1621,8 +1600,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_ext_avgsz); } - else - rrdset_next(d->st_ext_avgsz); rrddim_set_by_pointer( d->st_ext_avgsz, d->rd_avgsz_discards, @@ -1641,7 +1618,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_svctm)) { d->st_svctm = rrdset_create_localhost( "disk_svctm" - , d->device + , d->chart_id , d->disk , family , "disk.svctm" @@ -1660,15 +1637,12 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_svctm); } - else - rrdset_next(d->st_svctm); 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); } } - // -------------------------------------------------------------------------- // read bcache metrics and generate the bcache charts if(d->device_is_bcache && d->do_bcache != CONFIG_BOOLEAN_NO) { @@ -1749,7 +1723,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_bcache_hit_ratio)) { d->st_bcache_hit_ratio = rrdset_create_localhost( "disk_bcache_hit_ratio" - , d->device + , d->chart_id , d->disk , family , "disk.bcache_hit_ratio" @@ -1769,8 +1743,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_bcache_hit_ratio); } - else - rrdset_next(d->st_bcache_hit_ratio); rrddim_set_by_pointer(d->st_bcache_hit_ratio, d->rd_bcache_hit_ratio_5min, stats_five_minute_cache_hit_ratio); rrddim_set_by_pointer(d->st_bcache_hit_ratio, d->rd_bcache_hit_ratio_1hour, stats_hour_cache_hit_ratio); @@ -1784,7 +1756,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_bcache_rates)) { d->st_bcache_rates = rrdset_create_localhost( "disk_bcache_rates" - , d->device + , d->chart_id , d->disk , family , "disk.bcache_rates" @@ -1802,8 +1774,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_bcache_rates); } - else - rrdset_next(d->st_bcache_rates); rrddim_set_by_pointer(d->st_bcache_rates, d->rd_bcache_rate_writeback, writeback_rate); rrddim_set_by_pointer(d->st_bcache_rates, d->rd_bcache_rate_congested, cache_congested); @@ -1814,7 +1784,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_bcache_size)) { d->st_bcache_size = rrdset_create_localhost( "disk_bcache_size" - , d->device + , d->chart_id , d->disk , family , "disk.bcache_size" @@ -1831,8 +1801,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_bcache_size); } - else - rrdset_next(d->st_bcache_size); rrddim_set_by_pointer(d->st_bcache_size, d->rd_bcache_dirty_size, dirty_data); rrdset_done(d->st_bcache_size); @@ -1842,7 +1810,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_bcache_usage)) { d->st_bcache_usage = rrdset_create_localhost( "disk_bcache_usage" - , d->device + , d->chart_id , d->disk , family , "disk.bcache_usage" @@ -1859,8 +1827,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_bcache_usage); } - else - rrdset_next(d->st_bcache_usage); rrddim_set_by_pointer(d->st_bcache_usage, d->rd_bcache_available_percent, cache_available_percent); rrdset_done(d->st_bcache_usage); @@ -1871,7 +1837,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_bcache_cache_read_races)) { d->st_bcache_cache_read_races = rrdset_create_localhost( "disk_bcache_cache_read_races" - , d->device + , d->chart_id , d->disk , family , "disk.bcache_cache_read_races" @@ -1889,8 +1855,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_bcache_cache_read_races); } - else - rrdset_next(d->st_bcache_cache_read_races); rrddim_set_by_pointer(d->st_bcache_cache_read_races, d->rd_bcache_cache_read_races, cache_read_races); rrddim_set_by_pointer(d->st_bcache_cache_read_races, d->rd_bcache_cache_io_errors, cache_io_errors); @@ -1906,7 +1870,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_bcache)) { d->st_bcache = rrdset_create_localhost( "disk_bcache" - , d->device + , d->chart_id , d->disk , family , "disk.bcache" @@ -1928,8 +1892,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_bcache); } - else - rrdset_next(d->st_bcache); rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_hits, stats_total_cache_hits); rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_misses, stats_total_cache_misses); @@ -1946,7 +1908,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!d->st_bcache_bypass)) { d->st_bcache_bypass = rrdset_create_localhost( "disk_bcache_bypass" - , d->device + , d->chart_id , d->disk , family , "disk.bcache_bypass" @@ -1966,7 +1928,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { add_labels_to_disk(d, d->st_bcache_bypass); } - else rrdset_next(d->st_bcache_bypass); rrddim_set_by_pointer(d->st_bcache_bypass, d->rd_bcache_bypass_hits, stats_total_cache_bypass_hits); rrddim_set_by_pointer(d->st_bcache_bypass, d->rd_bcache_bypass_misses, stats_total_cache_bypass_misses); @@ -1975,8 +1936,6 @@ int do_proc_diskstats(int update_every, usec_t dt) { } } - - // ------------------------------------------------------------------------ // update the system total I/O if(global_do_io == CONFIG_BOOLEAN_YES || (global_do_io == CONFIG_BOOLEAN_AUTO && @@ -2004,15 +1963,12 @@ int do_proc_diskstats(int update_every, usec_t dt) { 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; @@ -2021,12 +1977,19 @@ int do_proc_diskstats(int update_every, usec_t dt) { struct disk *t = d; rrdset_obsolete_and_pointer_null(d->st_avgsz); + rrdset_obsolete_and_pointer_null(d->st_ext_avgsz); rrdset_obsolete_and_pointer_null(d->st_await); + rrdset_obsolete_and_pointer_null(d->st_ext_await); rrdset_obsolete_and_pointer_null(d->st_backlog); + rrdset_obsolete_and_pointer_null(d->st_busy); rrdset_obsolete_and_pointer_null(d->st_io); + rrdset_obsolete_and_pointer_null(d->st_ext_io); rrdset_obsolete_and_pointer_null(d->st_iotime); + rrdset_obsolete_and_pointer_null(d->st_ext_iotime); rrdset_obsolete_and_pointer_null(d->st_mops); + rrdset_obsolete_and_pointer_null(d->st_ext_mops); rrdset_obsolete_and_pointer_null(d->st_ops); + rrdset_obsolete_and_pointer_null(d->st_ext_ops); rrdset_obsolete_and_pointer_null(d->st_qops); rrdset_obsolete_and_pointer_null(d->st_svctm); rrdset_obsolete_and_pointer_null(d->st_util); @@ -2036,6 +1999,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_obsolete_and_pointer_null(d->st_bcache_size); rrdset_obsolete_and_pointer_null(d->st_bcache_usage); rrdset_obsolete_and_pointer_null(d->st_bcache_hit_ratio); + rrdset_obsolete_and_pointer_null(d->st_bcache_cache_allocations); + rrdset_obsolete_and_pointer_null(d->st_bcache_cache_read_races); if(d == disk_root) { disk_root = d = d->next; @@ -2066,6 +2031,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { freez(t->disk); freez(t->device); freez(t->mount_point); + freez(t->chart_id); freez(t); } else { diff --git a/collectors/proc.plugin/proc_interrupts.c b/collectors/proc.plugin/proc_interrupts.c index 46290554b..f87684758 100644 --- a/collectors/proc.plugin/proc_interrupts.c +++ b/collectors/proc.plugin/proc_interrupts.c @@ -146,8 +146,6 @@ int do_proc_interrupts(int update_every, usec_t dt) { irr->used = 1; } - // -------------------------------------------------------------------- - static RRDSET *st_system_interrupts = NULL; if(unlikely(!st_system_interrupts)) st_system_interrupts = rrdset_create_localhost( @@ -164,8 +162,6 @@ int do_proc_interrupts(int update_every, usec_t dt) { , update_every , RRDSET_TYPE_STACKED ); - else - rrdset_next(st_system_interrupts); for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); @@ -173,9 +169,9 @@ int do_proc_interrupts(int update_every, usec_t dt) { // some interrupt may have changed without changing the total number of lines // if the same number of interrupts have been added and removed between two // calls of this function. - if(unlikely(!irr->rd || strncmp(irr->rd->name, irr->name, MAX_INTERRUPT_NAME) != 0)) { + if(unlikely(!irr->rd || strncmp(rrddim_name(irr->rd), irr->name, MAX_INTERRUPT_NAME) != 0)) { irr->rd = rrddim_add(st_system_interrupts, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(st_system_interrupts, irr->rd, irr->name); + rrddim_reset_name(st_system_interrupts, irr->rd, irr->name); // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { @@ -190,8 +186,6 @@ int do_proc_interrupts(int update_every, usec_t dt) { rrdset_done(st_system_interrupts); - // -------------------------------------------------------------------- - if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { static RRDSET **core_st = NULL; static int old_cpus = 0; @@ -228,16 +222,15 @@ int do_proc_interrupts(int update_every, usec_t dt) { char core[50+1]; snprintfz(core, 50, "cpu%d", c); - rrdlabels_add(core_st[c]->state->chart_labels, "cpu", core, RRDLABEL_SRC_AUTO); + rrdlabels_add(core_st[c]->rrdlabels, "cpu", core, RRDLABEL_SRC_AUTO); } - else rrdset_next(core_st[c]); for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); if(irr->used && (do_per_core == CONFIG_BOOLEAN_YES || irr->cpu[c].value)) { if(unlikely(!irr->cpu[c].rd)) { irr->cpu[c].rd = rrddim_add(core_st[c], irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(core_st[c], irr->cpu[c].rd, irr->name); + rrddim_reset_name(core_st[c], irr->cpu[c].rd, irr->name); } rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value); diff --git a/collectors/proc.plugin/proc_loadavg.c b/collectors/proc.plugin/proc_loadavg.c index 8b78ecc9e..d928c8617 100644 --- a/collectors/proc.plugin/proc_loadavg.c +++ b/collectors/proc.plugin/proc_loadavg.c @@ -52,9 +52,6 @@ int do_proc_loadavg(int update_every, usec_t dt) { // //unsigned long long next_pid = str2ull(procfile_lineword(ff, 0, 5)); - - // -------------------------------------------------------------------- - if(next_loadavg_dt <= dt) { if(likely(do_loadavg)) { static RRDSET *load_chart = NULL; @@ -80,8 +77,6 @@ int do_proc_loadavg(int update_every, usec_t dt) { rd_load5 = rrddim_add(load_chart, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rd_load15 = rrddim_add(load_chart, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(load_chart); rrddim_set_by_pointer(load_chart, rd_load1, (collected_number) (load1 * 1000)); rrddim_set_by_pointer(load_chart, rd_load5, (collected_number) (load5 * 1000)); @@ -90,16 +85,17 @@ int do_proc_loadavg(int update_every, usec_t dt) { next_loadavg_dt = load_chart->update_every * USEC_PER_SEC; } - else next_loadavg_dt = MIN_LOADAVG_UPDATE_EVERY * USEC_PER_SEC; + else + next_loadavg_dt = MIN_LOADAVG_UPDATE_EVERY * USEC_PER_SEC; } - else next_loadavg_dt -= dt; + else + next_loadavg_dt -= dt; - // -------------------------------------------------------------------- if(likely(do_all_processes)) { static RRDSET *processes_chart = NULL; static RRDDIM *rd_active = NULL; - static RRDSETVAR *rd_pidmax; + static const RRDSETVAR_ACQUIRED *rd_pidmax; if(unlikely(!processes_chart)) { processes_chart = rrdset_create_localhost( @@ -118,12 +114,11 @@ int do_proc_loadavg(int update_every, usec_t dt) { ); rd_active = rrddim_add(processes_chart, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - rd_pidmax = rrdsetvar_custom_chart_variable_create(processes_chart, "pidmax"); + rd_pidmax = rrdsetvar_custom_chart_variable_add_and_acquire(processes_chart, "pidmax"); } - else rrdset_next(processes_chart); rrddim_set_by_pointer(processes_chart, rd_active, active_processes); - rrdsetvar_custom_chart_variable_set(rd_pidmax, max_processes); + rrdsetvar_custom_chart_variable_set(processes_chart, rd_pidmax, max_processes); rrdset_done(processes_chart); } diff --git a/collectors/proc.plugin/proc_mdstat.c b/collectors/proc.plugin/proc_mdstat.c index c8015827e..63e0c68eb 100644 --- a/collectors/proc.plugin/proc_mdstat.c +++ b/collectors/proc.plugin/proc_mdstat.c @@ -78,8 +78,8 @@ static inline void make_chart_obsolete(char *name, const char *id_modifier) } static void add_labels_to_mdstat(struct raid *raid, RRDSET *st) { - rrdlabels_add(st->state->chart_labels, "device", raid->name, RRDLABEL_SRC_AUTO); - rrdlabels_add(st->state->chart_labels, "raid_level", raid->level, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device", raid->name, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "raid_level", raid->level, RRDLABEL_SRC_AUTO); } int do_proc_mdstat(int update_every, usec_t dt) @@ -392,8 +392,6 @@ int do_proc_mdstat(int update_every, usec_t dt) } } - // -------------------------------------------------------------------- - if (likely(do_health && redundant_num)) { static RRDSET *st_mdstat_health = NULL; if (unlikely(!st_mdstat_health)) { @@ -413,8 +411,6 @@ int do_proc_mdstat(int update_every, usec_t dt) rrdset_isnot_obsolete(st_mdstat_health); } - else - rrdset_next(st_mdstat_health); if (!redundant_num) { if (likely(make_charts_obsolete)) @@ -435,8 +431,6 @@ int do_proc_mdstat(int update_every, usec_t dt) } } - // -------------------------------------------------------------------- - for (raid_idx = 0; raid_idx < raids_num; raid_idx++) { struct raid *raid = &raids[raid_idx]; char id[50 + 1]; @@ -467,8 +461,6 @@ int do_proc_mdstat(int update_every, usec_t dt) add_labels_to_mdstat(raid, raid->st_disks); } - else - rrdset_next(raid->st_disks); if (unlikely(!raid->rd_inuse && !(raid->rd_inuse = rrddim_find_active(raid->st_disks, "inuse")))) raid->rd_inuse = rrddim_add(raid->st_disks, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -477,12 +469,9 @@ int do_proc_mdstat(int update_every, usec_t dt) rrddim_set_by_pointer(raid->st_disks, raid->rd_inuse, raid->inuse_disks); rrddim_set_by_pointer(raid->st_disks, raid->rd_down, raid->failed_disks); - rrdset_done(raid->st_disks); } - // -------------------------------------------------------------------- - if (likely(do_mismatch)) { snprintfz(id, 50, "%s_mismatch", raid->name); @@ -507,19 +496,14 @@ int do_proc_mdstat(int update_every, usec_t dt) add_labels_to_mdstat(raid, raid->st_mismatch_cnt); } - else - rrdset_next(raid->st_mismatch_cnt); if (unlikely(!raid->rd_mismatch_cnt && !(raid->rd_mismatch_cnt = rrddim_find_active(raid->st_mismatch_cnt, "count")))) raid->rd_mismatch_cnt = rrddim_add(raid->st_mismatch_cnt, "count", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(raid->st_mismatch_cnt, raid->rd_mismatch_cnt, raid->mismatch_cnt); - rrdset_done(raid->st_mismatch_cnt); } - // -------------------------------------------------------------------- - if (likely(do_operations)) { snprintfz(id, 50, "%s_operation", raid->name); @@ -544,8 +528,6 @@ int do_proc_mdstat(int update_every, usec_t dt) add_labels_to_mdstat(raid, raid->st_operation); } - else - rrdset_next(raid->st_operation); if(unlikely(!raid->rd_check && !(raid->rd_check = rrddim_find_active(raid->st_operation, "check")))) raid->rd_check = rrddim_add(raid->st_operation, "check", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); @@ -560,13 +542,9 @@ int do_proc_mdstat(int update_every, usec_t dt) rrddim_set_by_pointer(raid->st_operation, raid->rd_resync, raid->resync); rrddim_set_by_pointer(raid->st_operation, raid->rd_recovery, raid->recovery); rrddim_set_by_pointer(raid->st_operation, raid->rd_reshape, raid->reshape); - rrdset_done(raid->st_operation); - // -------------------------------------------------------------------- - snprintfz(id, 50, "%s_finish", raid->name); - if (unlikely(!raid->st_finish && !(raid->st_finish = rrdset_find_active_byname_localhost(id)))) { snprintfz(family, 50, "%s (%s)", raid->name, raid->level); @@ -587,20 +565,14 @@ int do_proc_mdstat(int update_every, usec_t dt) add_labels_to_mdstat(raid, raid->st_finish); } - else - rrdset_next(raid->st_finish); if(unlikely(!raid->rd_finish_in && !(raid->rd_finish_in = rrddim_find_active(raid->st_finish, "finish_in")))) raid->rd_finish_in = rrddim_add(raid->st_finish, "finish_in", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(raid->st_finish, raid->rd_finish_in, raid->finish_in); - rrdset_done(raid->st_finish); - // -------------------------------------------------------------------- - snprintfz(id, 50, "%s_speed", raid->name); - if (unlikely(!raid->st_speed && !(raid->st_speed = rrdset_find_active_byname_localhost(id)))) { snprintfz(family, 50, "%s (%s)", raid->name, raid->level); @@ -622,19 +594,14 @@ int do_proc_mdstat(int update_every, usec_t dt) add_labels_to_mdstat(raid, raid->st_speed); } - else - rrdset_next(raid->st_speed); if (unlikely(!raid->rd_speed && !(raid->rd_speed = rrddim_find_active(raid->st_speed, "speed")))) raid->rd_speed = rrddim_add(raid->st_speed, "speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(raid->st_speed, raid->rd_speed, raid->speed); - rrdset_done(raid->st_speed); } } else { - // -------------------------------------------------------------------- - if (likely(do_nonredundant)) { snprintfz(id, 50, "%s_availability", raid->name); @@ -659,14 +626,11 @@ int do_proc_mdstat(int update_every, usec_t dt) add_labels_to_mdstat(raid, raid->st_nonredundant); } - else - rrdset_next(raid->st_nonredundant); if (unlikely(!raid->rd_nonredundant && !(raid->rd_nonredundant = rrddim_find_active(raid->st_nonredundant, "available")))) raid->rd_nonredundant = rrddim_add(raid->st_nonredundant, "available", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(raid->st_nonredundant, raid->rd_nonredundant, 1); - rrdset_done(raid->st_nonredundant); } } diff --git a/collectors/proc.plugin/proc_meminfo.c b/collectors/proc.plugin/proc_meminfo.c index f89ddd8d4..2f390c653 100644 --- a/collectors/proc.plugin/proc_meminfo.c +++ b/collectors/proc.plugin/proc_meminfo.c @@ -154,8 +154,6 @@ int do_proc_meminfo(int update_every, usec_t dt) { if (first_ff_read) first_ff_read = 0; - // -------------------------------------------------------------------- - // http://calimeroteknik.free.fr/blag/?article20/really-used-memory-on-gnu-linux unsigned long long MemCached = Cached + SReclaimable - Shmem; unsigned long long MemUsed = MemTotal - MemFree - MemCached - Buffers; @@ -190,13 +188,11 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_cached = rrddim_add(st_system_ram, "cached", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rd_buffers = rrddim_add(st_system_ram, "buffers", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_system_ram); rrddim_set_by_pointer(st_system_ram, rd_free, MemFree); rrddim_set_by_pointer(st_system_ram, rd_used, MemUsed); rrddim_set_by_pointer(st_system_ram, rd_cached, MemCached); rrddim_set_by_pointer(st_system_ram, rd_buffers, Buffers); - rrdset_done(st_system_ram); } @@ -222,16 +218,12 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_avail = rrddim_add(st_mem_available, "MemAvailable", "avail", 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_available); rrddim_set_by_pointer(st_mem_available, rd_avail, MemAvailable); - rrdset_done(st_mem_available); } } - // -------------------------------------------------------------------- - unsigned long long SwapUsed = SwapTotal - SwapFree; if(do_swap == CONFIG_BOOLEAN_YES || (do_swap == CONFIG_BOOLEAN_AUTO && @@ -263,16 +255,12 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_free = rrddim_add(st_system_swap, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rd_used = rrddim_add(st_system_swap, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_system_swap); rrddim_set_by_pointer(st_system_swap, rd_used, SwapUsed); rrddim_set_by_pointer(st_system_swap, rd_free, SwapFree); - rrdset_done(st_system_swap); } - // -------------------------------------------------------------------- - if(arl_hwcorrupted->flags & ARL_ENTRY_FLAG_FOUND && (do_hwcorrupt == CONFIG_BOOLEAN_YES || (do_hwcorrupt == CONFIG_BOOLEAN_AUTO && (HardwareCorrupted > 0 || @@ -302,15 +290,11 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_corrupted = rrddim_add(st_mem_hwcorrupt, "HardwareCorrupted", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_hwcorrupt); rrddim_set_by_pointer(st_mem_hwcorrupt, rd_corrupted, HardwareCorrupted); - rrdset_done(st_mem_hwcorrupt); } - // -------------------------------------------------------------------- - if(do_committed) { static RRDSET *st_mem_committed = NULL; static RRDDIM *rd_committed = NULL; @@ -335,15 +319,11 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_committed = rrddim_add(st_mem_committed, "Committed_AS", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_committed); rrddim_set_by_pointer(st_mem_committed, rd_committed, Committed_AS); - rrdset_done(st_mem_committed); } - // -------------------------------------------------------------------- - if(do_writeback) { static RRDSET *st_mem_writeback = NULL; static RRDDIM *rd_dirty = NULL, *rd_writeback = NULL, *rd_fusewriteback = NULL, *rd_nfs_writeback = NULL, *rd_bounce = NULL; @@ -371,14 +351,12 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_nfs_writeback = rrddim_add(st_mem_writeback, "NfsWriteback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rd_bounce = rrddim_add(st_mem_writeback, "Bounce", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_writeback); rrddim_set_by_pointer(st_mem_writeback, rd_dirty, Dirty); rrddim_set_by_pointer(st_mem_writeback, rd_writeback, Writeback); rrddim_set_by_pointer(st_mem_writeback, rd_fusewriteback, WritebackTmp); rrddim_set_by_pointer(st_mem_writeback, rd_nfs_writeback, NFS_Unstable); rrddim_set_by_pointer(st_mem_writeback, rd_bounce, Bounce); - rrdset_done(st_mem_writeback); } @@ -414,7 +392,6 @@ int do_proc_meminfo(int update_every, usec_t dt) { if (do_percpu) rd_percpu = rrddim_add(st_mem_kernel, "Percpu", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_kernel); rrddim_set_by_pointer(st_mem_kernel, rd_slab, Slab); rrddim_set_by_pointer(st_mem_kernel, rd_kernelstack, KernelStack); @@ -426,8 +403,6 @@ int do_proc_meminfo(int update_every, usec_t dt) { rrdset_done(st_mem_kernel); } - // -------------------------------------------------------------------- - if(do_slab) { static RRDSET *st_mem_slab = NULL; static RRDDIM *rd_reclaimable = NULL, *rd_unreclaimable = NULL; @@ -453,16 +428,12 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_reclaimable = rrddim_add(st_mem_slab, "reclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rd_unreclaimable = rrddim_add(st_mem_slab, "unreclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_slab); rrddim_set_by_pointer(st_mem_slab, rd_reclaimable, SReclaimable); rrddim_set_by_pointer(st_mem_slab, rd_unreclaimable, SUnreclaim); - rrdset_done(st_mem_slab); } - // -------------------------------------------------------------------- - if(do_hugepages == CONFIG_BOOLEAN_YES || (do_hugepages == CONFIG_BOOLEAN_AUTO && ((Hugepagesize && HugePages_Total) || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { @@ -494,18 +465,14 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_surp = rrddim_add(st_mem_hugepages, "surplus", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE); rd_rsvd = rrddim_add(st_mem_hugepages, "reserved", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_hugepages); rrddim_set_by_pointer(st_mem_hugepages, rd_used, HugePages_Total - HugePages_Free - HugePages_Rsvd); rrddim_set_by_pointer(st_mem_hugepages, rd_free, HugePages_Free); rrddim_set_by_pointer(st_mem_hugepages, rd_rsvd, HugePages_Rsvd); rrddim_set_by_pointer(st_mem_hugepages, rd_surp, HugePages_Surp); - rrdset_done(st_mem_hugepages); } - // -------------------------------------------------------------------- - if(do_transparent_hugepages == CONFIG_BOOLEAN_YES || (do_transparent_hugepages == CONFIG_BOOLEAN_AUTO && (AnonHugePages || ShmemHugePages || @@ -536,11 +503,9 @@ int do_proc_meminfo(int update_every, usec_t dt) { rd_anonymous = rrddim_add(st_mem_transparent_hugepages, "anonymous", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rd_shared = rrddim_add(st_mem_transparent_hugepages, "shmem", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_mem_transparent_hugepages); rrddim_set_by_pointer(st_mem_transparent_hugepages, rd_anonymous, AnonHugePages); rrddim_set_by_pointer(st_mem_transparent_hugepages, rd_shared, ShmemHugePages); - rrdset_done(st_mem_transparent_hugepages); } diff --git a/collectors/proc.plugin/proc_net_dev.c b/collectors/proc.plugin/proc_net_dev.c index 79572f442..e124f631f 100644 --- a/collectors/proc.plugin/proc_net_dev.c +++ b/collectors/proc.plugin/proc_net_dev.c @@ -7,6 +7,8 @@ #define STATE_LENGTH_MAX 32 +#define READ_RETRY_PERIOD 60 // seconds + enum { NETDEV_DUPLEX_UNKNOWN, NETDEV_DUPLEX_HALF, @@ -55,6 +57,15 @@ static struct netdev { int configured; int enabled; int updated; + + int carrier_file_exists; + time_t carrier_file_lost_time; + + int duplex_file_exists; + time_t duplex_file_lost_time; + + int speed_file_exists; + time_t speed_file_lost_time; int do_bandwidth; int do_packets; @@ -188,7 +199,7 @@ static struct netdev { RRDDIM *rd_mtu; char *filename_speed; - RRDSETVAR *chart_var_speed; + const RRDSETVAR_ACQUIRED *chart_var_speed; char *filename_duplex; char *filename_operstate; @@ -859,21 +870,37 @@ int do_proc_net_dev(int update_every, usec_t dt) { if ((d->do_carrier != CONFIG_BOOLEAN_NO || d->do_duplex != CONFIG_BOOLEAN_NO || d->do_speed != CONFIG_BOOLEAN_NO) && - d->filename_carrier) { + d->filename_carrier && + (d->carrier_file_exists || + now_monotonic_sec() - d->carrier_file_lost_time > READ_RETRY_PERIOD)) { if (read_single_number_file(d->filename_carrier, &d->carrier)) { - error("Cannot refresh interface %s carrier state by reading '%s'. Stop updating it.", d->name, d->filename_carrier); - freez(d->filename_carrier); - d->filename_carrier = NULL; + if (d->carrier_file_exists) + error( + "Cannot refresh interface %s carrier state by reading '%s'. Next update is in %d seconds.", + d->name, + d->filename_carrier, + READ_RETRY_PERIOD); + d->carrier_file_exists = 0; + d->carrier_file_lost_time = now_monotonic_sec(); + } else { + d->carrier_file_exists = 1; + d->carrier_file_lost_time = 0; } } - if (d->do_duplex != CONFIG_BOOLEAN_NO && d->filename_duplex && (d->carrier || !d->filename_carrier)) { + if (d->do_duplex != CONFIG_BOOLEAN_NO && + d->filename_duplex && + (d->carrier || d->carrier_file_exists) && + (d->duplex_file_exists || + now_monotonic_sec() - d->duplex_file_lost_time > READ_RETRY_PERIOD)) { char buffer[STATE_LENGTH_MAX + 1]; if (read_file(d->filename_duplex, buffer, STATE_LENGTH_MAX)) { - error("Cannot refresh interface %s duplex state by reading '%s'. I will stop updating it.", d->name, d->filename_duplex); - freez(d->filename_duplex); - d->filename_duplex = NULL; + if (d->duplex_file_exists) + error("Cannot refresh interface %s duplex state by reading '%s'.", d->name, d->filename_duplex); + d->duplex_file_exists = 0; + d->duplex_file_lost_time = now_monotonic_sec(); + d->duplex = NETDEV_DUPLEX_UNKNOWN; } else { // values can be unknown, half or full -- just check the first letter for speed if (buffer[0] == 'f') @@ -882,9 +909,11 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->duplex = NETDEV_DUPLEX_HALF; else d->duplex = NETDEV_DUPLEX_UNKNOWN; + d->duplex_file_exists = 1; + d->duplex_file_lost_time = 0; } } else { - d->duplex = 0; + d->duplex = NETDEV_DUPLEX_UNKNOWN; } if(d->do_operstate != CONFIG_BOOLEAN_NO && d->filename_operstate) { @@ -904,7 +933,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { if (d->do_mtu != CONFIG_BOOLEAN_NO && d->filename_mtu) { if (read_single_number_file(d->filename_mtu, &d->mtu)) { - error("Cannot refresh mtu for interface %s by reading '%s'. Stop updating it.", d->name, d->filename_mtu); + error( + "Cannot refresh mtu for interface %s by reading '%s'. Stop updating it.", d->name, d->filename_mtu); freez(d->filename_mtu); d->filename_mtu = NULL; } @@ -921,8 +951,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { // , d->rframe, d->tcollisions, d->tcarrier // ); - // -------------------------------------------------------------------- - if(unlikely(d->do_bandwidth == CONFIG_BOOLEAN_AUTO && (d->rbytes || d->tbytes || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) d->do_bandwidth = CONFIG_BOOLEAN_YES; @@ -958,7 +986,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_tbytes = td; } } - else rrdset_next(d->st_bandwidth); rrddim_set_by_pointer(d->st_bandwidth, d->rd_rbytes, (collected_number)d->rbytes); rrddim_set_by_pointer(d->st_bandwidth, d->rd_tbytes, (collected_number)d->tbytes); @@ -967,31 +994,34 @@ int do_proc_net_dev(int update_every, usec_t dt) { // update the interface speed if(d->filename_speed) { if(unlikely(!d->chart_var_speed)) { - d->chart_var_speed = rrdsetvar_custom_chart_variable_create(d->st_bandwidth, "nic_speed_max"); + d->chart_var_speed = + rrdsetvar_custom_chart_variable_add_and_acquire(d->st_bandwidth, "nic_speed_max"); if(!d->chart_var_speed) { - error("Cannot create interface %s chart variable 'nic_speed_max'. Will not update its speed anymore.", d->name); + error( + "Cannot create interface %s chart variable 'nic_speed_max'. Will not update its speed anymore.", + d->name); freez(d->filename_speed); d->filename_speed = NULL; } } - if(d->filename_speed && d->chart_var_speed) { + if (d->filename_speed && d->chart_var_speed) { int ret = 0; - if (d->carrier || !d->filename_carrier) { + if ((d->carrier || d->carrier_file_exists) && + (d->speed_file_exists || now_monotonic_sec() - d->speed_file_lost_time > READ_RETRY_PERIOD)) { ret = read_single_number_file(d->filename_speed, (unsigned long long *) &d->speed); } else { - d->speed = 0; + d->speed = 0; // TODO: this is wrong, shouldn't use 0 value, but NULL. } if(ret) { - error("Cannot refresh interface %s speed by reading '%s'. Will not update its speed anymore.", d->name, d->filename_speed); - freez(d->filename_speed); - d->filename_speed = NULL; + if (d->speed_file_exists) + error("Cannot refresh interface %s speed by reading '%s'.", d->name, d->filename_speed); + d->speed_file_exists = 0; + d->speed_file_lost_time = now_monotonic_sec(); } else { - rrdsetvar_custom_chart_variable_set(d->chart_var_speed, (NETDATA_DOUBLE) d->speed * KILOBITS_IN_A_MEGABIT); - if(d->do_speed != CONFIG_BOOLEAN_NO) { if(unlikely(!d->st_speed)) { d->st_speed = rrdset_create_localhost( @@ -1015,18 +1045,23 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_speed = rrddim_add(d->st_speed, "speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(d->st_speed); rrddim_set_by_pointer(d->st_speed, d->rd_speed, (collected_number)d->speed * KILOBITS_IN_A_MEGABIT); rrdset_done(d->st_speed); } + + rrdsetvar_custom_chart_variable_set( + d->st_bandwidth, d->chart_var_speed, (NETDATA_DOUBLE)d->speed * KILOBITS_IN_A_MEGABIT); + + if (d->speed) { + d->speed_file_exists = 1; + d->speed_file_lost_time = 0; + } } } } } - // -------------------------------------------------------------------- - if(d->do_duplex != CONFIG_BOOLEAN_NO && d->filename_duplex) { if(unlikely(!d->st_duplex)) { d->st_duplex = rrdset_create_localhost( @@ -1052,7 +1087,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_duplex_half = rrddim_add(d->st_duplex, "half", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); d->rd_duplex_unknown = rrddim_add(d->st_duplex, "unknown", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(d->st_duplex); rrddim_set_by_pointer(d->st_duplex, d->rd_duplex_full, (collected_number)(d->duplex == NETDEV_DUPLEX_FULL)); rrddim_set_by_pointer(d->st_duplex, d->rd_duplex_half, (collected_number)(d->duplex == NETDEV_DUPLEX_HALF)); @@ -1060,8 +1094,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { rrdset_done(d->st_duplex); } - // -------------------------------------------------------------------- - if(d->do_operstate != CONFIG_BOOLEAN_NO && d->filename_operstate) { if(unlikely(!d->st_operstate)) { d->st_operstate = rrdset_create_localhost( @@ -1091,7 +1123,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_operstate_dormant = rrddim_add(d->st_operstate, "dormant", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); d->rd_operstate_unknown = rrddim_add(d->st_operstate, "unknown", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(d->st_operstate); rrddim_set_by_pointer(d->st_operstate, d->rd_operstate_up, (collected_number)(d->operstate == NETDEV_OPERSTATE_UP)); rrddim_set_by_pointer(d->st_operstate, d->rd_operstate_down, (collected_number)(d->operstate == NETDEV_OPERSTATE_DOWN)); @@ -1103,9 +1134,7 @@ int do_proc_net_dev(int update_every, usec_t dt) { rrdset_done(d->st_operstate); } - // -------------------------------------------------------------------- - - if(d->do_carrier != CONFIG_BOOLEAN_NO && d->filename_carrier) { + if(d->do_carrier != CONFIG_BOOLEAN_NO && d->carrier_file_exists) { if(unlikely(!d->st_carrier)) { d->st_carrier = rrdset_create_localhost( d->chart_type_net_carrier @@ -1129,15 +1158,12 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_carrier_up = rrddim_add(d->st_carrier, "up", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); d->rd_carrier_down = rrddim_add(d->st_carrier, "down", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(d->st_carrier); rrddim_set_by_pointer(d->st_carrier, d->rd_carrier_up, (collected_number)(d->carrier == 1)); rrddim_set_by_pointer(d->st_carrier, d->rd_carrier_down, (collected_number)(d->carrier != 1)); rrdset_done(d->st_carrier); } - // -------------------------------------------------------------------- - if(d->do_mtu != CONFIG_BOOLEAN_NO && d->filename_mtu) { if(unlikely(!d->st_mtu)) { d->st_mtu = rrdset_create_localhost( @@ -1161,14 +1187,11 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_mtu = rrddim_add(d->st_mtu, "mtu", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(d->st_mtu); rrddim_set_by_pointer(d->st_mtu, d->rd_mtu, (collected_number)d->mtu); rrdset_done(d->st_mtu); } - // -------------------------------------------------------------------- - if(unlikely(d->do_packets == CONFIG_BOOLEAN_AUTO && (d->rpackets || d->tpackets || d->rmulticast || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) d->do_packets = CONFIG_BOOLEAN_YES; @@ -1207,7 +1230,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_tpackets = td; } } - else rrdset_next(d->st_packets); rrddim_set_by_pointer(d->st_packets, d->rd_rpackets, (collected_number)d->rpackets); rrddim_set_by_pointer(d->st_packets, d->rd_tpackets, (collected_number)d->tpackets); @@ -1215,8 +1237,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { rrdset_done(d->st_packets); } - // -------------------------------------------------------------------- - if(unlikely(d->do_errors == CONFIG_BOOLEAN_AUTO && (d->rerrors || d->terrors || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) d->do_errors = CONFIG_BOOLEAN_YES; @@ -1254,15 +1274,12 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_terrors = td; } } - else rrdset_next(d->st_errors); rrddim_set_by_pointer(d->st_errors, d->rd_rerrors, (collected_number)d->rerrors); rrddim_set_by_pointer(d->st_errors, d->rd_terrors, (collected_number)d->terrors); rrdset_done(d->st_errors); } - // -------------------------------------------------------------------- - if(unlikely(d->do_drops == CONFIG_BOOLEAN_AUTO && (d->rdrops || d->tdrops || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) d->do_drops = CONFIG_BOOLEAN_YES; @@ -1300,15 +1317,12 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_tdrops = td; } } - else rrdset_next(d->st_drops); rrddim_set_by_pointer(d->st_drops, d->rd_rdrops, (collected_number)d->rdrops); rrddim_set_by_pointer(d->st_drops, d->rd_tdrops, (collected_number)d->tdrops); rrdset_done(d->st_drops); } - // -------------------------------------------------------------------- - if(unlikely(d->do_fifo == CONFIG_BOOLEAN_AUTO && (d->rfifo || d->tfifo || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) d->do_fifo = CONFIG_BOOLEAN_YES; @@ -1346,15 +1360,12 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_tfifo = td; } } - else rrdset_next(d->st_fifo); rrddim_set_by_pointer(d->st_fifo, d->rd_rfifo, (collected_number)d->rfifo); rrddim_set_by_pointer(d->st_fifo, d->rd_tfifo, (collected_number)d->tfifo); rrdset_done(d->st_fifo); } - // -------------------------------------------------------------------- - if(unlikely(d->do_compressed == CONFIG_BOOLEAN_AUTO && (d->rcompressed || d->tcompressed || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) d->do_compressed = CONFIG_BOOLEAN_YES; @@ -1392,15 +1403,12 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_tcompressed = td; } } - else rrdset_next(d->st_compressed); rrddim_set_by_pointer(d->st_compressed, d->rd_rcompressed, (collected_number)d->rcompressed); rrddim_set_by_pointer(d->st_compressed, d->rd_tcompressed, (collected_number)d->tcompressed); rrdset_done(d->st_compressed); } - // -------------------------------------------------------------------- - if(unlikely(d->do_events == CONFIG_BOOLEAN_AUTO && (d->rframe || d->tcollisions || d->tcarrier || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) d->do_events = CONFIG_BOOLEAN_YES; @@ -1431,7 +1439,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->rd_tcollisions = rrddim_add(d->st_events, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); d->rd_tcarrier = rrddim_add(d->st_events, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(d->st_events); rrddim_set_by_pointer(d->st_events, d->rd_rframe, (collected_number)d->rframe); rrddim_set_by_pointer(d->st_events, d->rd_tcollisions, (collected_number)d->tcollisions); @@ -1466,8 +1473,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { 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); diff --git a/collectors/proc.plugin/proc_net_ip_vs_stats.c b/collectors/proc.plugin/proc_net_ip_vs_stats.c index 43dcf2a88..2b9c9332e 100644 --- a/collectors/proc.plugin/proc_net_ip_vs_stats.c +++ b/collectors/proc.plugin/proc_net_ip_vs_stats.c @@ -39,9 +39,6 @@ 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); - - // -------------------------------------------------------------------- - if(do_sockets) { static RRDSET *st = NULL; @@ -63,14 +60,11 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "connections", entries); rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_packets) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -92,15 +86,12 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "received", InPackets); rrddim_set(st, "sent", OutPackets); rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_bandwidth) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -122,7 +113,6 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { 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); } - else rrdset_next(st); rrddim_set(st, "received", InBytes); rrddim_set(st, "sent", OutBytes); diff --git a/collectors/proc.plugin/proc_net_netstat.c b/collectors/proc.plugin/proc_net_netstat.c index ab8206be3..f7635e3d0 100644 --- a/collectors/proc.plugin/proc_net_netstat.c +++ b/collectors/proc.plugin/proc_net_netstat.c @@ -3,14 +3,97 @@ #include "plugin_proc.h" #define RRD_TYPE_NET_NETSTAT "ip" +#define RRD_TYPE_NET_SNMP "ipv4" +#define RRD_TYPE_NET_SNMP6 "ipv6" #define PLUGIN_PROC_MODULE_NETSTAT_NAME "/proc/net/netstat" #define CONFIG_SECTION_PLUGIN_PROC_NETSTAT "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NETSTAT_NAME -unsigned long long tcpext_TCPSynRetrans = 0; - -static void parse_line_pair(procfile *ff, ARL_BASE *base, size_t header_line, size_t values_line) { - size_t hwords = procfile_linewords(ff, header_line); - size_t vwords = procfile_linewords(ff, values_line); +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 }; + +static void parse_line_pair(procfile *ff_netstat, ARL_BASE *base, size_t header_line, size_t values_line) { + size_t hwords = procfile_linewords(ff_netstat, header_line); + size_t vwords = procfile_linewords(ff_netstat, values_line); size_t w; if(unlikely(vwords > hwords)) { @@ -19,7 +102,7 @@ static void parse_line_pair(procfile *ff, ARL_BASE *base, size_t header_line, si } for(w = 1; w < vwords ;w++) { - if(unlikely(arl_check(base, procfile_lineword(ff, header_line, w), procfile_lineword(ff, values_line, w)))) + if(unlikely(arl_check(base, procfile_lineword(ff_netstat, header_line, w), procfile_lineword(ff_netstat, values_line, w)))) break; } } @@ -31,12 +114,38 @@ int do_proc_net_netstat(int update_every, usec_t dt) { do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1, do_tcpext_syn_queue = -1, do_tcpext_accept_queue = -1; + static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1, + do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_tcp_opens = -1, + do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1, do_udplite_packets = -1; + + static int do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1, + do_ip6_udplite_packets = -1, do_ip6_udplite_errors = -1, do_ip6_udp_packets = -1, do_ip6_udp_errors = -1, + do_ip6_bandwidth = -1, do_ip6_mcast = -1, do_ip6_bcast = -1, do_ip6_mcast_p = -1, do_ip6_icmp = -1, + do_ip6_icmp_redir = -1, do_ip6_icmp_errors = -1, do_ip6_icmp_echos = -1, do_ip6_icmp_groupmemb = -1, + do_ip6_icmp_router = -1, do_ip6_icmp_neighbor = -1, do_ip6_icmp_mldv2 = -1, do_ip6_icmp_types = -1, + do_ip6_ect = -1; + static uint32_t hash_ipext = 0, hash_tcpext = 0; - static procfile *ff = NULL; + static uint32_t hash_ip = 0, hash_icmp = 0, hash_tcp = 0, hash_udp = 0, hash_icmpmsg = 0, hash_udplite = 0; + + static procfile *ff_netstat = NULL; + static procfile *ff_snmp = NULL; + static procfile *ff_snmp6 = NULL; static ARL_BASE *arl_tcpext = NULL; static ARL_BASE *arl_ipext = NULL; + static ARL_BASE *arl_ip = NULL; + static ARL_BASE *arl_icmp = NULL; + static ARL_BASE *arl_icmpmsg = NULL; + static ARL_BASE *arl_tcp = NULL; + static ARL_BASE *arl_udp = NULL; + static ARL_BASE *arl_udplite = NULL; + + static ARL_BASE *arl_ipv6 = NULL; + + static const RRDVAR_ACQUIRED *tcp_max_connections_var = NULL; + // -------------------------------------------------------------------- // IP @@ -111,8 +220,103 @@ int do_proc_net_netstat(int update_every, usec_t dt) { static unsigned long long tcpext_TCPReqQFullDrop = 0; static unsigned long long tcpext_TCPReqQFullDoCookies = 0; - // shared: tcpext_TCPSynRetrans - + static unsigned long long tcpext_TCPSynRetrans = 0; + + // IPv6 + static unsigned long long Ip6InReceives = 0ULL; + static unsigned long long Ip6InHdrErrors = 0ULL; + static unsigned long long Ip6InTooBigErrors = 0ULL; + static unsigned long long Ip6InNoRoutes = 0ULL; + static unsigned long long Ip6InAddrErrors = 0ULL; + static unsigned long long Ip6InUnknownProtos = 0ULL; + static unsigned long long Ip6InTruncatedPkts = 0ULL; + static unsigned long long Ip6InDiscards = 0ULL; + static unsigned long long Ip6InDelivers = 0ULL; + static unsigned long long Ip6OutForwDatagrams = 0ULL; + static unsigned long long Ip6OutRequests = 0ULL; + static unsigned long long Ip6OutDiscards = 0ULL; + static unsigned long long Ip6OutNoRoutes = 0ULL; + static unsigned long long Ip6ReasmTimeout = 0ULL; + static unsigned long long Ip6ReasmReqds = 0ULL; + static unsigned long long Ip6ReasmOKs = 0ULL; + static unsigned long long Ip6ReasmFails = 0ULL; + static unsigned long long Ip6FragOKs = 0ULL; + static unsigned long long Ip6FragFails = 0ULL; + static unsigned long long Ip6FragCreates = 0ULL; + static unsigned long long Ip6InMcastPkts = 0ULL; + static unsigned long long Ip6OutMcastPkts = 0ULL; + static unsigned long long Ip6InOctets = 0ULL; + static unsigned long long Ip6OutOctets = 0ULL; + static unsigned long long Ip6InMcastOctets = 0ULL; + static unsigned long long Ip6OutMcastOctets = 0ULL; + static unsigned long long Ip6InBcastOctets = 0ULL; + static unsigned long long Ip6OutBcastOctets = 0ULL; + static unsigned long long Ip6InNoECTPkts = 0ULL; + static unsigned long long Ip6InECT1Pkts = 0ULL; + static unsigned long long Ip6InECT0Pkts = 0ULL; + static unsigned long long Ip6InCEPkts = 0ULL; + static unsigned long long Icmp6InMsgs = 0ULL; + static unsigned long long Icmp6InErrors = 0ULL; + static unsigned long long Icmp6OutMsgs = 0ULL; + static unsigned long long Icmp6OutErrors = 0ULL; + static unsigned long long Icmp6InCsumErrors = 0ULL; + static unsigned long long Icmp6InDestUnreachs = 0ULL; + static unsigned long long Icmp6InPktTooBigs = 0ULL; + static unsigned long long Icmp6InTimeExcds = 0ULL; + static unsigned long long Icmp6InParmProblems = 0ULL; + static unsigned long long Icmp6InEchos = 0ULL; + static unsigned long long Icmp6InEchoReplies = 0ULL; + static unsigned long long Icmp6InGroupMembQueries = 0ULL; + static unsigned long long Icmp6InGroupMembResponses = 0ULL; + static unsigned long long Icmp6InGroupMembReductions = 0ULL; + static unsigned long long Icmp6InRouterSolicits = 0ULL; + static unsigned long long Icmp6InRouterAdvertisements = 0ULL; + static unsigned long long Icmp6InNeighborSolicits = 0ULL; + static unsigned long long Icmp6InNeighborAdvertisements = 0ULL; + static unsigned long long Icmp6InRedirects = 0ULL; + static unsigned long long Icmp6InMLDv2Reports = 0ULL; + static unsigned long long Icmp6OutDestUnreachs = 0ULL; + static unsigned long long Icmp6OutPktTooBigs = 0ULL; + static unsigned long long Icmp6OutTimeExcds = 0ULL; + static unsigned long long Icmp6OutParmProblems = 0ULL; + static unsigned long long Icmp6OutEchos = 0ULL; + static unsigned long long Icmp6OutEchoReplies = 0ULL; + static unsigned long long Icmp6OutGroupMembQueries = 0ULL; + static unsigned long long Icmp6OutGroupMembResponses = 0ULL; + static unsigned long long Icmp6OutGroupMembReductions = 0ULL; + static unsigned long long Icmp6OutRouterSolicits = 0ULL; + static unsigned long long Icmp6OutRouterAdvertisements = 0ULL; + static unsigned long long Icmp6OutNeighborSolicits = 0ULL; + static unsigned long long Icmp6OutNeighborAdvertisements = 0ULL; + static unsigned long long Icmp6OutRedirects = 0ULL; + static unsigned long long Icmp6OutMLDv2Reports = 0ULL; + static unsigned long long Icmp6InType1 = 0ULL; + static unsigned long long Icmp6InType128 = 0ULL; + static unsigned long long Icmp6InType129 = 0ULL; + static unsigned long long Icmp6InType136 = 0ULL; + static unsigned long long Icmp6OutType1 = 0ULL; + static unsigned long long Icmp6OutType128 = 0ULL; + static unsigned long long Icmp6OutType129 = 0ULL; + static unsigned long long Icmp6OutType133 = 0ULL; + static unsigned long long Icmp6OutType135 = 0ULL; + static unsigned long long Icmp6OutType143 = 0ULL; + static unsigned long long Udp6InDatagrams = 0ULL; + static unsigned long long Udp6NoPorts = 0ULL; + static unsigned long long Udp6InErrors = 0ULL; + static unsigned long long Udp6OutDatagrams = 0ULL; + static unsigned long long Udp6RcvbufErrors = 0ULL; + static unsigned long long Udp6SndbufErrors = 0ULL; + static unsigned long long Udp6InCsumErrors = 0ULL; + static unsigned long long Udp6IgnoredMulti = 0ULL; + static unsigned long long UdpLite6InDatagrams = 0ULL; + static unsigned long long UdpLite6NoPorts = 0ULL; + static unsigned long long UdpLite6InErrors = 0ULL; + static unsigned long long UdpLite6OutDatagrams = 0ULL; + static unsigned long long UdpLite6RcvbufErrors = 0ULL; + static unsigned long long UdpLite6SndbufErrors = 0ULL; + static unsigned long long UdpLite6InCsumErrors = 0ULL; + + // prepare for /proc/net/netstat parsing if(unlikely(!arl_ipext)) { hash_ipext = simple_hash("IpExt"); @@ -225,645 +429,2682 @@ int do_proc_net_netstat(int update_every, usec_t dt) { arl_expect(arl_tcpext, "TCPReqQFullDoCookies", &tcpext_TCPReqQFullDoCookies); } - // shared metrics arl_expect(arl_tcpext, "TCPSynRetrans", &tcpext_TCPSynRetrans); } - if(unlikely(!ff)) { + // prepare for /proc/net/snmp parsing + + if(unlikely(!arl_ip)) { + do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 packets", CONFIG_BOOLEAN_AUTO); + do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", CONFIG_BOOLEAN_AUTO); + do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", CONFIG_BOOLEAN_AUTO); + do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 errors", CONFIG_BOOLEAN_AUTO); + do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", CONFIG_BOOLEAN_AUTO); + do_tcp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", CONFIG_BOOLEAN_AUTO); + do_tcp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", CONFIG_BOOLEAN_AUTO); + do_tcp_opens = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP opens", CONFIG_BOOLEAN_AUTO); + do_tcp_handshake = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", CONFIG_BOOLEAN_AUTO); + do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", CONFIG_BOOLEAN_AUTO); + do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", CONFIG_BOOLEAN_AUTO); + do_icmp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 ICMP packets", CONFIG_BOOLEAN_AUTO); + do_icmpmsg = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 ICMP messages", CONFIG_BOOLEAN_AUTO); + do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 UDPLite packets", CONFIG_BOOLEAN_AUTO); + + hash_ip = simple_hash("Ip"); + hash_tcp = simple_hash("Tcp"); + hash_udp = simple_hash("Udp"); + hash_icmp = simple_hash("Icmp"); + hash_icmpmsg = simple_hash("IcmpMsg"); + hash_udplite = simple_hash("UdpLite"); + + 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_custom(arl_tcp, "MaxConn", arl_callback_ssize_t, &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_add_and_acquire(localhost, "tcp_max_connections"); + } + + // prepare for /proc/net/snmp6 parsing + + if(unlikely(!arl_ipv6)) { + do_ip6_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_BOOLEAN_AUTO); + do_ip6_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO); + do_ip6_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_BOOLEAN_AUTO); + do_ip6_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_BOOLEAN_AUTO); + do_ip6_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_BOOLEAN_AUTO); + do_ip6_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_BOOLEAN_AUTO); + do_ip6_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_BOOLEAN_AUTO); + do_ip6_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_BOOLEAN_AUTO); + do_ip6_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_BOOLEAN_AUTO); + do_ip6_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_BOOLEAN_AUTO); + do_ip6_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO); + do_ip6_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_BOOLEAN_AUTO); + do_ip6_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_BOOLEAN_AUTO); + do_ip6_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_BOOLEAN_AUTO); + + arl_ipv6 = arl_create("snmp6", NULL, 60); + arl_expect(arl_ipv6, "Ip6InReceives", &Ip6InReceives); + arl_expect(arl_ipv6, "Ip6InHdrErrors", &Ip6InHdrErrors); + arl_expect(arl_ipv6, "Ip6InTooBigErrors", &Ip6InTooBigErrors); + arl_expect(arl_ipv6, "Ip6InNoRoutes", &Ip6InNoRoutes); + arl_expect(arl_ipv6, "Ip6InAddrErrors", &Ip6InAddrErrors); + arl_expect(arl_ipv6, "Ip6InUnknownProtos", &Ip6InUnknownProtos); + arl_expect(arl_ipv6, "Ip6InTruncatedPkts", &Ip6InTruncatedPkts); + arl_expect(arl_ipv6, "Ip6InDiscards", &Ip6InDiscards); + arl_expect(arl_ipv6, "Ip6InDelivers", &Ip6InDelivers); + arl_expect(arl_ipv6, "Ip6OutForwDatagrams", &Ip6OutForwDatagrams); + arl_expect(arl_ipv6, "Ip6OutRequests", &Ip6OutRequests); + arl_expect(arl_ipv6, "Ip6OutDiscards", &Ip6OutDiscards); + arl_expect(arl_ipv6, "Ip6OutNoRoutes", &Ip6OutNoRoutes); + arl_expect(arl_ipv6, "Ip6ReasmTimeout", &Ip6ReasmTimeout); + arl_expect(arl_ipv6, "Ip6ReasmReqds", &Ip6ReasmReqds); + arl_expect(arl_ipv6, "Ip6ReasmOKs", &Ip6ReasmOKs); + arl_expect(arl_ipv6, "Ip6ReasmFails", &Ip6ReasmFails); + arl_expect(arl_ipv6, "Ip6FragOKs", &Ip6FragOKs); + arl_expect(arl_ipv6, "Ip6FragFails", &Ip6FragFails); + arl_expect(arl_ipv6, "Ip6FragCreates", &Ip6FragCreates); + arl_expect(arl_ipv6, "Ip6InMcastPkts", &Ip6InMcastPkts); + arl_expect(arl_ipv6, "Ip6OutMcastPkts", &Ip6OutMcastPkts); + arl_expect(arl_ipv6, "Ip6InOctets", &Ip6InOctets); + arl_expect(arl_ipv6, "Ip6OutOctets", &Ip6OutOctets); + arl_expect(arl_ipv6, "Ip6InMcastOctets", &Ip6InMcastOctets); + arl_expect(arl_ipv6, "Ip6OutMcastOctets", &Ip6OutMcastOctets); + arl_expect(arl_ipv6, "Ip6InBcastOctets", &Ip6InBcastOctets); + arl_expect(arl_ipv6, "Ip6OutBcastOctets", &Ip6OutBcastOctets); + arl_expect(arl_ipv6, "Ip6InNoECTPkts", &Ip6InNoECTPkts); + arl_expect(arl_ipv6, "Ip6InECT1Pkts", &Ip6InECT1Pkts); + arl_expect(arl_ipv6, "Ip6InECT0Pkts", &Ip6InECT0Pkts); + arl_expect(arl_ipv6, "Ip6InCEPkts", &Ip6InCEPkts); + arl_expect(arl_ipv6, "Icmp6InMsgs", &Icmp6InMsgs); + arl_expect(arl_ipv6, "Icmp6InErrors", &Icmp6InErrors); + arl_expect(arl_ipv6, "Icmp6OutMsgs", &Icmp6OutMsgs); + arl_expect(arl_ipv6, "Icmp6OutErrors", &Icmp6OutErrors); + arl_expect(arl_ipv6, "Icmp6InCsumErrors", &Icmp6InCsumErrors); + arl_expect(arl_ipv6, "Icmp6InDestUnreachs", &Icmp6InDestUnreachs); + arl_expect(arl_ipv6, "Icmp6InPktTooBigs", &Icmp6InPktTooBigs); + arl_expect(arl_ipv6, "Icmp6InTimeExcds", &Icmp6InTimeExcds); + arl_expect(arl_ipv6, "Icmp6InParmProblems", &Icmp6InParmProblems); + arl_expect(arl_ipv6, "Icmp6InEchos", &Icmp6InEchos); + arl_expect(arl_ipv6, "Icmp6InEchoReplies", &Icmp6InEchoReplies); + arl_expect(arl_ipv6, "Icmp6InGroupMembQueries", &Icmp6InGroupMembQueries); + arl_expect(arl_ipv6, "Icmp6InGroupMembResponses", &Icmp6InGroupMembResponses); + arl_expect(arl_ipv6, "Icmp6InGroupMembReductions", &Icmp6InGroupMembReductions); + arl_expect(arl_ipv6, "Icmp6InRouterSolicits", &Icmp6InRouterSolicits); + arl_expect(arl_ipv6, "Icmp6InRouterAdvertisements", &Icmp6InRouterAdvertisements); + arl_expect(arl_ipv6, "Icmp6InNeighborSolicits", &Icmp6InNeighborSolicits); + arl_expect(arl_ipv6, "Icmp6InNeighborAdvertisements", &Icmp6InNeighborAdvertisements); + arl_expect(arl_ipv6, "Icmp6InRedirects", &Icmp6InRedirects); + arl_expect(arl_ipv6, "Icmp6InMLDv2Reports", &Icmp6InMLDv2Reports); + arl_expect(arl_ipv6, "Icmp6OutDestUnreachs", &Icmp6OutDestUnreachs); + arl_expect(arl_ipv6, "Icmp6OutPktTooBigs", &Icmp6OutPktTooBigs); + arl_expect(arl_ipv6, "Icmp6OutTimeExcds", &Icmp6OutTimeExcds); + arl_expect(arl_ipv6, "Icmp6OutParmProblems", &Icmp6OutParmProblems); + arl_expect(arl_ipv6, "Icmp6OutEchos", &Icmp6OutEchos); + arl_expect(arl_ipv6, "Icmp6OutEchoReplies", &Icmp6OutEchoReplies); + arl_expect(arl_ipv6, "Icmp6OutGroupMembQueries", &Icmp6OutGroupMembQueries); + arl_expect(arl_ipv6, "Icmp6OutGroupMembResponses", &Icmp6OutGroupMembResponses); + arl_expect(arl_ipv6, "Icmp6OutGroupMembReductions", &Icmp6OutGroupMembReductions); + arl_expect(arl_ipv6, "Icmp6OutRouterSolicits", &Icmp6OutRouterSolicits); + arl_expect(arl_ipv6, "Icmp6OutRouterAdvertisements", &Icmp6OutRouterAdvertisements); + arl_expect(arl_ipv6, "Icmp6OutNeighborSolicits", &Icmp6OutNeighborSolicits); + arl_expect(arl_ipv6, "Icmp6OutNeighborAdvertisements", &Icmp6OutNeighborAdvertisements); + arl_expect(arl_ipv6, "Icmp6OutRedirects", &Icmp6OutRedirects); + arl_expect(arl_ipv6, "Icmp6OutMLDv2Reports", &Icmp6OutMLDv2Reports); + arl_expect(arl_ipv6, "Icmp6InType1", &Icmp6InType1); + arl_expect(arl_ipv6, "Icmp6InType128", &Icmp6InType128); + arl_expect(arl_ipv6, "Icmp6InType129", &Icmp6InType129); + arl_expect(arl_ipv6, "Icmp6InType136", &Icmp6InType136); + arl_expect(arl_ipv6, "Icmp6OutType1", &Icmp6OutType1); + arl_expect(arl_ipv6, "Icmp6OutType128", &Icmp6OutType128); + arl_expect(arl_ipv6, "Icmp6OutType129", &Icmp6OutType129); + arl_expect(arl_ipv6, "Icmp6OutType133", &Icmp6OutType133); + arl_expect(arl_ipv6, "Icmp6OutType135", &Icmp6OutType135); + arl_expect(arl_ipv6, "Icmp6OutType143", &Icmp6OutType143); + arl_expect(arl_ipv6, "Udp6InDatagrams", &Udp6InDatagrams); + arl_expect(arl_ipv6, "Udp6NoPorts", &Udp6NoPorts); + arl_expect(arl_ipv6, "Udp6InErrors", &Udp6InErrors); + arl_expect(arl_ipv6, "Udp6OutDatagrams", &Udp6OutDatagrams); + arl_expect(arl_ipv6, "Udp6RcvbufErrors", &Udp6RcvbufErrors); + arl_expect(arl_ipv6, "Udp6SndbufErrors", &Udp6SndbufErrors); + arl_expect(arl_ipv6, "Udp6InCsumErrors", &Udp6InCsumErrors); + arl_expect(arl_ipv6, "Udp6IgnoredMulti", &Udp6IgnoredMulti); + arl_expect(arl_ipv6, "UdpLite6InDatagrams", &UdpLite6InDatagrams); + arl_expect(arl_ipv6, "UdpLite6NoPorts", &UdpLite6NoPorts); + arl_expect(arl_ipv6, "UdpLite6InErrors", &UdpLite6InErrors); + arl_expect(arl_ipv6, "UdpLite6OutDatagrams", &UdpLite6OutDatagrams); + arl_expect(arl_ipv6, "UdpLite6RcvbufErrors", &UdpLite6RcvbufErrors); + arl_expect(arl_ipv6, "UdpLite6SndbufErrors", &UdpLite6SndbufErrors); + arl_expect(arl_ipv6, "UdpLite6InCsumErrors", &UdpLite6InCsumErrors); + } + + size_t lines, l, words; + + // parse /proc/net/netstat + + if(unlikely(!ff_netstat)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/netstat"); - ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); - if(unlikely(!ff)) return 1; + ff_netstat = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff_netstat)) return 1; } - ff = procfile_readall(ff); - if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time + ff_netstat = procfile_readall(ff_netstat); + if(unlikely(!ff_netstat)) 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; + lines = procfile_lines(ff_netstat); arl_begin(arl_ipext); arl_begin(arl_tcpext); for(l = 0; l < lines ;l++) { - char *key = procfile_lineword(ff, l, 0); + char *key = procfile_lineword(ff_netstat, l, 0); uint32_t hash = simple_hash(key); if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) { size_t h = l++; - words = procfile_linewords(ff, l); + words = procfile_linewords(ff_netstat, l); if(unlikely(words < 2)) { error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %zu.", words); continue; } - parse_line_pair(ff, arl_ipext, h, l); - - // -------------------------------------------------------------------- - - if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && - (ipext_InOctets || - ipext_OutOctets || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_bandwidth = CONFIG_BOOLEAN_YES; - static RRDSET *st_system_ip = NULL; - static RRDDIM *rd_in = NULL, *rd_out = NULL; - - if(unlikely(!st_system_ip)) { - st_system_ip = rrdset_create_localhost( - "system" - , RRD_TYPE_NET_NETSTAT - , NULL - , "network" - , NULL - , "IP Bandwidth" - , "kilobits/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_SYSTEM_IP - , update_every - , RRDSET_TYPE_AREA - ); - - rd_in = rrddim_add(st_system_ip, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_system_ip, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_system_ip); - - rrddim_set_by_pointer(st_system_ip, rd_in, ipext_InOctets); - rrddim_set_by_pointer(st_system_ip, rd_out, ipext_OutOctets); - - rrdset_done(st_system_ip); + parse_line_pair(ff_netstat, arl_ipext, h, l); + + } + else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) { + size_t h = l++; + + words = procfile_linewords(ff_netstat, l); + if(unlikely(words < 2)) { + error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %zu.", words); + continue; + } + + parse_line_pair(ff_netstat, arl_tcpext, h, l); + } + } + + // parse /proc/net/snmp + + if(unlikely(!ff_snmp)) { + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp"); + ff_snmp = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff_snmp)) return 1; + } + + ff_snmp = procfile_readall(ff_snmp); + if(unlikely(!ff_snmp)) return 0; // we return 0, so that we will retry to open it next time + + lines = procfile_lines(ff_snmp); + size_t w; + + for(l = 0; l < lines ;l++) { + char *key = procfile_lineword(ff_snmp, l, 0); + uint32_t hash = simple_hash(key); + + if(unlikely(hash == hash_ip && strcmp(key, "Ip") == 0)) { + size_t h = l++; + + if(strcmp(procfile_lineword(ff_snmp, l, 0), "Ip") != 0) { + error("Cannot read Ip line from /proc/net/snmp."); + break; } - // -------------------------------------------------------------------- - - if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && - (ipext_InNoRoutes || - ipext_InTruncatedPkts || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_inerrors = CONFIG_BOOLEAN_YES; - static RRDSET *st_ip_inerrors = NULL; - static RRDDIM *rd_noroutes = NULL, *rd_truncated = NULL, *rd_checksum = NULL; - - if(unlikely(!st_ip_inerrors)) { - st_ip_inerrors = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "inerrors" - , NULL - , "errors" - , NULL - , "IP Input Errors" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_ERRORS - , update_every - , RRDSET_TYPE_LINE - ); - - rrdset_flag_set(st_ip_inerrors, RRDSET_FLAG_DETAIL); - - rd_noroutes = rrddim_add(st_ip_inerrors, "InNoRoutes", "noroutes", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_truncated = rrddim_add(st_ip_inerrors, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_checksum = rrddim_add(st_ip_inerrors, "InCsumErrors", "checksum", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_ip_inerrors); - - rrddim_set_by_pointer(st_ip_inerrors, rd_noroutes, ipext_InNoRoutes); - rrddim_set_by_pointer(st_ip_inerrors, rd_truncated, ipext_InTruncatedPkts); - rrddim_set_by_pointer(st_ip_inerrors, rd_checksum, ipext_InCsumErrors); - - rrdset_done(st_ip_inerrors); + words = procfile_linewords(ff_snmp, l); + if(words < 3) { + error("Cannot read /proc/net/snmp Ip line. Expected 3+ params, read %zu.", words); + continue; } - // -------------------------------------------------------------------- + arl_begin(arl_ip); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_ip, procfile_lineword(ff_snmp, h, w), procfile_lineword(ff_snmp, l, w)) != 0)) + break; + } + } + else if(unlikely(hash == hash_icmp && strcmp(key, "Icmp") == 0)) { + size_t h = l++; - if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && - (ipext_InMcastOctets || - ipext_OutMcastOctets || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_mcast = CONFIG_BOOLEAN_YES; - static RRDSET *st_ip_mcast = NULL; - static RRDDIM *rd_in = NULL, *rd_out = NULL; - - if(unlikely(!st_ip_mcast)) { - st_ip_mcast = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "mcast" - , NULL - , "multicast" - , NULL - , "IP Multicast Bandwidth" - , "kilobits/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_MCAST - , update_every - , RRDSET_TYPE_AREA - ); - - rrdset_flag_set(st_ip_mcast, RRDSET_FLAG_DETAIL); - - rd_in = rrddim_add(st_ip_mcast, "InMcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ip_mcast, "OutMcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_ip_mcast); - - rrddim_set_by_pointer(st_ip_mcast, rd_in, ipext_InMcastOctets); - rrddim_set_by_pointer(st_ip_mcast, rd_out, ipext_OutMcastOctets); - - rrdset_done(st_ip_mcast); + if(strcmp(procfile_lineword(ff_snmp, l, 0), "Icmp") != 0) { + error("Cannot read Icmp line from /proc/net/snmp."); + break; } - // -------------------------------------------------------------------- + words = procfile_linewords(ff_snmp, l); + if(words < 3) { + error("Cannot read /proc/net/snmp Icmp line. Expected 3+ params, read %zu.", words); + continue; + } - if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && - (ipext_InBcastOctets || - ipext_OutBcastOctets || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_bcast = CONFIG_BOOLEAN_YES; - - static RRDSET *st_ip_bcast = NULL; - static RRDDIM *rd_in = NULL, *rd_out = NULL; - - if(unlikely(!st_ip_bcast)) { - st_ip_bcast = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "bcast" - , NULL - , "broadcast" - , NULL - , "IP Broadcast Bandwidth" - , "kilobits/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_BCAST - , update_every - , RRDSET_TYPE_AREA - ); - - rrdset_flag_set(st_ip_bcast, RRDSET_FLAG_DETAIL); - - rd_in = rrddim_add(st_ip_bcast, "InBcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ip_bcast, "OutBcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_ip_bcast); - - rrddim_set_by_pointer(st_ip_bcast, rd_in, ipext_InBcastOctets); - rrddim_set_by_pointer(st_ip_bcast, rd_out, ipext_OutBcastOctets); - - rrdset_done(st_ip_bcast); + arl_begin(arl_icmp); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_icmp, procfile_lineword(ff_snmp, h, w), procfile_lineword(ff_snmp, l, w)) != 0)) + break; } + } + else if(unlikely(hash == hash_icmpmsg && strcmp(key, "IcmpMsg") == 0)) { + size_t h = l++; - // -------------------------------------------------------------------- + if(strcmp(procfile_lineword(ff_snmp, l, 0), "IcmpMsg") != 0) { + error("Cannot read IcmpMsg line from /proc/net/snmp."); + break; + } - if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && - (ipext_InMcastPkts || - ipext_OutMcastPkts || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_mcast_p = CONFIG_BOOLEAN_YES; - - static RRDSET *st_ip_mcastpkts = NULL; - static RRDDIM *rd_in = NULL, *rd_out = NULL; - - if(unlikely(!st_ip_mcastpkts)) { - st_ip_mcastpkts = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "mcastpkts" - , NULL - , "multicast" - , NULL - , "IP Multicast Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_MCAST_PACKETS - , update_every - , RRDSET_TYPE_LINE - ); - - rrdset_flag_set(st_ip_mcastpkts, RRDSET_FLAG_DETAIL); - - rd_in = rrddim_add(st_ip_mcastpkts, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ip_mcastpkts, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else rrdset_next(st_ip_mcastpkts); - - rrddim_set_by_pointer(st_ip_mcastpkts, rd_in, ipext_InMcastPkts); - rrddim_set_by_pointer(st_ip_mcastpkts, rd_out, ipext_OutMcastPkts); - - rrdset_done(st_ip_mcastpkts); + words = procfile_linewords(ff_snmp, l); + if(words < 2) { + error("Cannot read /proc/net/snmp IcmpMsg line. Expected 2+ params, read %zu.", words); + continue; } - // -------------------------------------------------------------------- + arl_begin(arl_icmpmsg); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_icmpmsg, procfile_lineword(ff_snmp, h, w), procfile_lineword(ff_snmp, l, w)) != 0)) + break; + } + } + else if(unlikely(hash == hash_tcp && strcmp(key, "Tcp") == 0)) { + size_t h = l++; - if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && - (ipext_InBcastPkts || - ipext_OutBcastPkts || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_bcast_p = CONFIG_BOOLEAN_YES; - - static RRDSET *st_ip_bcastpkts = NULL; - static RRDDIM *rd_in = NULL, *rd_out = NULL; - - if(unlikely(!st_ip_bcastpkts)) { - st_ip_bcastpkts = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "bcastpkts" - , NULL - , "broadcast" - , NULL - , "IP Broadcast Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_BCAST_PACKETS - , update_every - , RRDSET_TYPE_LINE - ); - - rrdset_flag_set(st_ip_bcastpkts, RRDSET_FLAG_DETAIL); - - rd_in = rrddim_add(st_ip_bcastpkts, "InBcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ip_bcastpkts, "OutBcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_ip_bcastpkts); - - rrddim_set_by_pointer(st_ip_bcastpkts, rd_in, ipext_InBcastPkts); - rrddim_set_by_pointer(st_ip_bcastpkts, rd_out, ipext_OutBcastPkts); - - rrdset_done(st_ip_bcastpkts); + if(strcmp(procfile_lineword(ff_snmp, l, 0), "Tcp") != 0) { + error("Cannot read Tcp line from /proc/net/snmp."); + break; } - // -------------------------------------------------------------------- + words = procfile_linewords(ff_snmp, l); + if(words < 3) { + error("Cannot read /proc/net/snmp Tcp line. Expected 3+ params, read %zu.", words); + continue; + } - if(do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && - (ipext_InCEPkts || - ipext_InECT0Pkts || - ipext_InECT1Pkts || - ipext_InNoECTPkts || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ecn = CONFIG_BOOLEAN_YES; - - static RRDSET *st_ecnpkts = NULL; - static RRDDIM *rd_cep = NULL, *rd_noectp = NULL, *rd_ectp0 = NULL, *rd_ectp1 = NULL; - - if(unlikely(!st_ecnpkts)) { - st_ecnpkts = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "ecnpkts" - , NULL - , "ecn" - , NULL - , "IP ECN Statistics" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_ECN - , update_every - , RRDSET_TYPE_LINE - ); - - rrdset_flag_set(st_ecnpkts, RRDSET_FLAG_DETAIL); - - rd_cep = rrddim_add(st_ecnpkts, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_noectp = rrddim_add(st_ecnpkts, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_ectp0 = rrddim_add(st_ecnpkts, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_ectp1 = rrddim_add(st_ecnpkts, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else rrdset_next(st_ecnpkts); - - rrddim_set_by_pointer(st_ecnpkts, rd_cep, ipext_InCEPkts); - rrddim_set_by_pointer(st_ecnpkts, rd_noectp, ipext_InNoECTPkts); - rrddim_set_by_pointer(st_ecnpkts, rd_ectp0, ipext_InECT0Pkts); - rrddim_set_by_pointer(st_ecnpkts, rd_ectp1, ipext_InECT1Pkts); - - rrdset_done(st_ecnpkts); + arl_begin(arl_tcp); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_tcp, procfile_lineword(ff_snmp, h, w), procfile_lineword(ff_snmp, l, w)) != 0)) + break; } } - else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) { + else if(unlikely(hash == hash_udp && strcmp(key, "Udp") == 0)) { size_t h = l++; - words = procfile_linewords(ff, l); - if(unlikely(words < 2)) { - error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %zu.", words); + if(strcmp(procfile_lineword(ff_snmp, l, 0), "Udp") != 0) { + error("Cannot read Udp line from /proc/net/snmp."); + break; + } + + words = procfile_linewords(ff_snmp, l); + if(words < 3) { + error("Cannot read /proc/net/snmp Udp line. Expected 3+ params, read %zu.", words); continue; } - parse_line_pair(ff, arl_tcpext, h, l); - - // -------------------------------------------------------------------- - - if(do_tcpext_memory == CONFIG_BOOLEAN_YES || (do_tcpext_memory == CONFIG_BOOLEAN_AUTO && - (tcpext_TCPMemoryPressures || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcpext_memory = CONFIG_BOOLEAN_YES; - - static RRDSET *st_tcpmemorypressures = NULL; - static RRDDIM *rd_pressures = NULL; - - if(unlikely(!st_tcpmemorypressures)) { - st_tcpmemorypressures = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "tcpmemorypressures" - , NULL - , "tcp" - , NULL - , "TCP Memory Pressures" - , "events/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_TCP_MEM - , update_every - , RRDSET_TYPE_LINE - ); - - rd_pressures = rrddim_add(st_tcpmemorypressures, "TCPMemoryPressures", "pressures", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_tcpmemorypressures); - - rrddim_set_by_pointer(st_tcpmemorypressures, rd_pressures, tcpext_TCPMemoryPressures); - - rrdset_done(st_tcpmemorypressures); + arl_begin(arl_udp); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_udp, procfile_lineword(ff_snmp, h, w), procfile_lineword(ff_snmp, l, w)) != 0)) + break; } + } + else if(unlikely(hash == hash_udplite && strcmp(key, "UdpLite") == 0)) { + size_t h = l++; - // -------------------------------------------------------------------- - - if(do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && - (tcpext_TCPAbortOnData || - tcpext_TCPAbortOnClose || - tcpext_TCPAbortOnMemory || - tcpext_TCPAbortOnTimeout || - tcpext_TCPAbortOnLinger || - tcpext_TCPAbortFailed || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcpext_connaborts = CONFIG_BOOLEAN_YES; - - static RRDSET *st_tcpconnaborts = NULL; - static RRDDIM *rd_baddata = NULL, *rd_userclosed = NULL, *rd_nomemory = NULL, *rd_timeout = NULL, *rd_linger = NULL, *rd_failed = NULL; - - if(unlikely(!st_tcpconnaborts)) { - st_tcpconnaborts = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "tcpconnaborts" - , NULL - , "tcp" - , NULL - , "TCP Connection Aborts" - , "connections/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_TCP_CONNABORTS - , update_every - , RRDSET_TYPE_LINE - ); - - rd_baddata = rrddim_add(st_tcpconnaborts, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_userclosed = rrddim_add(st_tcpconnaborts, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_nomemory = rrddim_add(st_tcpconnaborts, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_timeout = rrddim_add(st_tcpconnaborts, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_linger = rrddim_add(st_tcpconnaborts, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_failed = rrddim_add(st_tcpconnaborts, "TCPAbortFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_tcpconnaborts); - - rrddim_set_by_pointer(st_tcpconnaborts, rd_baddata, tcpext_TCPAbortOnData); - rrddim_set_by_pointer(st_tcpconnaborts, rd_userclosed, tcpext_TCPAbortOnClose); - rrddim_set_by_pointer(st_tcpconnaborts, rd_nomemory, tcpext_TCPAbortOnMemory); - rrddim_set_by_pointer(st_tcpconnaborts, rd_timeout, tcpext_TCPAbortOnTimeout); - rrddim_set_by_pointer(st_tcpconnaborts, rd_linger, tcpext_TCPAbortOnLinger); - rrddim_set_by_pointer(st_tcpconnaborts, rd_failed, tcpext_TCPAbortFailed); - - rrdset_done(st_tcpconnaborts); + if(strcmp(procfile_lineword(ff_snmp, l, 0), "UdpLite") != 0) { + error("Cannot read UdpLite line from /proc/net/snmp."); + break; } - // -------------------------------------------------------------------- + words = procfile_linewords(ff_snmp, l); + if(words < 3) { + error("Cannot read /proc/net/snmp UdpLite line. Expected 3+ params, read %zu.", words); + continue; + } - if(do_tcpext_reorder == CONFIG_BOOLEAN_YES || (do_tcpext_reorder == CONFIG_BOOLEAN_AUTO && - (tcpext_TCPRenoReorder || - tcpext_TCPFACKReorder || - tcpext_TCPSACKReorder || - tcpext_TCPTSReorder || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcpext_reorder = CONFIG_BOOLEAN_YES; - - static RRDSET *st_tcpreorders = NULL; - static RRDDIM *rd_timestamp = NULL, *rd_sack = NULL, *rd_fack = NULL, *rd_reno = NULL; - - if(unlikely(!st_tcpreorders)) { - st_tcpreorders = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "tcpreorders" - , NULL - , "tcp" - , NULL - , "TCP Reordered Packets by Detection Method" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_TCP_REORDERS - , update_every - , RRDSET_TYPE_LINE - ); - - rd_timestamp = rrddim_add(st_tcpreorders, "TCPTSReorder", "timestamp", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_sack = rrddim_add(st_tcpreorders, "TCPSACKReorder", "sack", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_fack = rrddim_add(st_tcpreorders, "TCPFACKReorder", "fack", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_reno = rrddim_add(st_tcpreorders, "TCPRenoReorder", "reno", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_tcpreorders); - - rrddim_set_by_pointer(st_tcpreorders, rd_timestamp, tcpext_TCPTSReorder); - rrddim_set_by_pointer(st_tcpreorders, rd_sack, tcpext_TCPSACKReorder); - rrddim_set_by_pointer(st_tcpreorders, rd_fack, tcpext_TCPFACKReorder); - rrddim_set_by_pointer(st_tcpreorders, rd_reno, tcpext_TCPRenoReorder); - - rrdset_done(st_tcpreorders); + arl_begin(arl_udplite); + for(w = 1; w < words ; w++) { + if (unlikely(arl_check(arl_udplite, procfile_lineword(ff_snmp, h, w), procfile_lineword(ff_snmp, l, w)) != 0)) + break; } + } + } + + // parse /proc/net/snmp + + if(unlikely(!ff_snmp6)) { + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp6"); + ff_snmp6 = procfile_open(config_get("plugin:proc:/proc/net/snmp6", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff_snmp6)) + return 1; + } + + ff_snmp6 = procfile_readall(ff_snmp6); + if(unlikely(!ff_snmp6)) + return 0; // we return 0, so that we will retry to open it next time - // -------------------------------------------------------------------- + lines = procfile_lines(ff_snmp6); - if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && - (tcpext_TCPOFOQueue || - tcpext_TCPOFODrop || - tcpext_TCPOFOMerge || + arl_begin(arl_ipv6); + + for(l = 0; l < lines ;l++) { + size_t words = procfile_linewords(ff_snmp6, l); + if(unlikely(words < 2)) { + if(unlikely(words)) error("Cannot read /proc/net/snmp6 line %zu. Expected 2 params, read %zu.", l, words); + continue; + } + + if(unlikely(arl_check(arl_ipv6, + procfile_lineword(ff_snmp6, l, 0), + procfile_lineword(ff_snmp6, l, 1)))) break; + } + + // netstat IpExt charts + + if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && + (ipext_InOctets || + ipext_OutOctets || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_bandwidth = CONFIG_BOOLEAN_YES; + static RRDSET *st_system_ip = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if(unlikely(!st_system_ip)) { + st_system_ip = rrdset_create_localhost( + "system" + , RRD_TYPE_NET_NETSTAT + , NULL + , "network" + , NULL + , "IP Bandwidth" + , "kilobits/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_IP + , update_every + , RRDSET_TYPE_AREA + ); + + rd_in = rrddim_add(st_system_ip, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_system_ip, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_system_ip, rd_in, ipext_InOctets); + rrddim_set_by_pointer(st_system_ip, rd_out, ipext_OutOctets); + rrdset_done(st_system_ip); + } + + if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && + (ipext_InNoRoutes || + ipext_InTruncatedPkts || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_inerrors = CONFIG_BOOLEAN_YES; + static RRDSET *st_ip_inerrors = NULL; + static RRDDIM *rd_noroutes = NULL, *rd_truncated = NULL, *rd_checksum = NULL; + + if(unlikely(!st_ip_inerrors)) { + st_ip_inerrors = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "inerrors" + , NULL + , "errors" + , NULL + , "IP Input Errors" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_ERRORS + , update_every + , RRDSET_TYPE_LINE + ); + + rrdset_flag_set(st_ip_inerrors, RRDSET_FLAG_DETAIL); + + rd_noroutes = rrddim_add(st_ip_inerrors, "InNoRoutes", "noroutes", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_truncated = rrddim_add(st_ip_inerrors, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_checksum = rrddim_add(st_ip_inerrors, "InCsumErrors", "checksum", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ip_inerrors, rd_noroutes, ipext_InNoRoutes); + rrddim_set_by_pointer(st_ip_inerrors, rd_truncated, ipext_InTruncatedPkts); + rrddim_set_by_pointer(st_ip_inerrors, rd_checksum, ipext_InCsumErrors); + rrdset_done(st_ip_inerrors); + } + + if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && + (ipext_InMcastOctets || + ipext_OutMcastOctets || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_mcast = CONFIG_BOOLEAN_YES; + static RRDSET *st_ip_mcast = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if(unlikely(!st_ip_mcast)) { + st_ip_mcast = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "mcast" + , NULL + , "multicast" + , NULL + , "IP Multicast Bandwidth" + , "kilobits/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_MCAST + , update_every + , RRDSET_TYPE_AREA + ); + + rrdset_flag_set(st_ip_mcast, RRDSET_FLAG_DETAIL); + + rd_in = rrddim_add(st_ip_mcast, "InMcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_ip_mcast, "OutMcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ip_mcast, rd_in, ipext_InMcastOctets); + rrddim_set_by_pointer(st_ip_mcast, rd_out, ipext_OutMcastOctets); + + rrdset_done(st_ip_mcast); + } + + // -------------------------------------------------------------------- + + if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && + (ipext_InBcastOctets || + ipext_OutBcastOctets || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_bcast = CONFIG_BOOLEAN_YES; + + static RRDSET *st_ip_bcast = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if(unlikely(!st_ip_bcast)) { + st_ip_bcast = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "bcast" + , NULL + , "broadcast" + , NULL + , "IP Broadcast Bandwidth" + , "kilobits/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_BCAST + , update_every + , RRDSET_TYPE_AREA + ); + + rrdset_flag_set(st_ip_bcast, RRDSET_FLAG_DETAIL); + + rd_in = rrddim_add(st_ip_bcast, "InBcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_ip_bcast, "OutBcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ip_bcast, rd_in, ipext_InBcastOctets); + rrddim_set_by_pointer(st_ip_bcast, rd_out, ipext_OutBcastOctets); + + rrdset_done(st_ip_bcast); + } + + // -------------------------------------------------------------------- + + if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && + (ipext_InMcastPkts || + ipext_OutMcastPkts || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_mcast_p = CONFIG_BOOLEAN_YES; + + static RRDSET *st_ip_mcastpkts = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if(unlikely(!st_ip_mcastpkts)) { + st_ip_mcastpkts = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "mcastpkts" + , NULL + , "multicast" + , NULL + , "IP Multicast Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_MCAST_PACKETS + , update_every + , RRDSET_TYPE_LINE + ); + + rrdset_flag_set(st_ip_mcastpkts, RRDSET_FLAG_DETAIL); + + rd_in = rrddim_add(st_ip_mcastpkts, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_ip_mcastpkts, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ip_mcastpkts, rd_in, ipext_InMcastPkts); + rrddim_set_by_pointer(st_ip_mcastpkts, rd_out, ipext_OutMcastPkts); + rrdset_done(st_ip_mcastpkts); + } + + if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && + (ipext_InBcastPkts || + ipext_OutBcastPkts || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_bcast_p = CONFIG_BOOLEAN_YES; + + static RRDSET *st_ip_bcastpkts = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if(unlikely(!st_ip_bcastpkts)) { + st_ip_bcastpkts = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "bcastpkts" + , NULL + , "broadcast" + , NULL + , "IP Broadcast Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_BCAST_PACKETS + , update_every + , RRDSET_TYPE_LINE + ); + + rrdset_flag_set(st_ip_bcastpkts, RRDSET_FLAG_DETAIL); + + rd_in = rrddim_add(st_ip_bcastpkts, "InBcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_out = rrddim_add(st_ip_bcastpkts, "OutBcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ip_bcastpkts, rd_in, ipext_InBcastPkts); + rrddim_set_by_pointer(st_ip_bcastpkts, rd_out, ipext_OutBcastPkts); + rrdset_done(st_ip_bcastpkts); + } + + if(do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && + (ipext_InCEPkts || + ipext_InECT0Pkts || + ipext_InECT1Pkts || + ipext_InNoECTPkts || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ecn = CONFIG_BOOLEAN_YES; + + static RRDSET *st_ecnpkts = NULL; + static RRDDIM *rd_cep = NULL, *rd_noectp = NULL, *rd_ectp0 = NULL, *rd_ectp1 = NULL; + + if(unlikely(!st_ecnpkts)) { + st_ecnpkts = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "ecnpkts" + , NULL + , "ecn" + , NULL + , "IP ECN Statistics" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_ECN + , update_every + , RRDSET_TYPE_LINE + ); + + rrdset_flag_set(st_ecnpkts, RRDSET_FLAG_DETAIL); + + rd_cep = rrddim_add(st_ecnpkts, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_noectp = rrddim_add(st_ecnpkts, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ectp0 = rrddim_add(st_ecnpkts, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_ectp1 = rrddim_add(st_ecnpkts, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ecnpkts, rd_cep, ipext_InCEPkts); + rrddim_set_by_pointer(st_ecnpkts, rd_noectp, ipext_InNoECTPkts); + rrddim_set_by_pointer(st_ecnpkts, rd_ectp0, ipext_InECT0Pkts); + rrddim_set_by_pointer(st_ecnpkts, rd_ectp1, ipext_InECT1Pkts); + rrdset_done(st_ecnpkts); + } + + // netstat TcpExt charts + + if(do_tcpext_memory == CONFIG_BOOLEAN_YES || (do_tcpext_memory == CONFIG_BOOLEAN_AUTO && + (tcpext_TCPMemoryPressures || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcpext_memory = CONFIG_BOOLEAN_YES; + + static RRDSET *st_tcpmemorypressures = NULL; + static RRDDIM *rd_pressures = NULL; + + if(unlikely(!st_tcpmemorypressures)) { + st_tcpmemorypressures = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcpmemorypressures" + , NULL + , "tcp" + , NULL + , "TCP Memory Pressures" + , "events/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_MEM + , update_every + , RRDSET_TYPE_LINE + ); + + rd_pressures = rrddim_add(st_tcpmemorypressures, "TCPMemoryPressures", "pressures", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_tcpmemorypressures, rd_pressures, tcpext_TCPMemoryPressures); + rrdset_done(st_tcpmemorypressures); + } + + if(do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && + (tcpext_TCPAbortOnData || + tcpext_TCPAbortOnClose || + tcpext_TCPAbortOnMemory || + tcpext_TCPAbortOnTimeout || + tcpext_TCPAbortOnLinger || + tcpext_TCPAbortFailed || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcpext_ofo = CONFIG_BOOLEAN_YES; - - static RRDSET *st_ip_tcpofo = NULL; - static RRDDIM *rd_inqueue = NULL, *rd_dropped = NULL, *rd_merged = NULL, *rd_pruned = NULL; - - if(unlikely(!st_ip_tcpofo)) { - - st_ip_tcpofo = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "tcpofo" - , NULL - , "tcp" - , NULL - , "TCP Out-Of-Order Queue" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_TCP_OFO - , update_every - , RRDSET_TYPE_LINE - ); - - rd_inqueue = rrddim_add(st_ip_tcpofo, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_dropped = rrddim_add(st_ip_tcpofo, "TCPOFODrop", "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_merged = rrddim_add(st_ip_tcpofo, "TCPOFOMerge", "merged", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_pruned = rrddim_add(st_ip_tcpofo, "OfoPruned", "pruned", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_ip_tcpofo); - - rrddim_set_by_pointer(st_ip_tcpofo, rd_inqueue, tcpext_TCPOFOQueue); - rrddim_set_by_pointer(st_ip_tcpofo, rd_dropped, tcpext_TCPOFODrop); - rrddim_set_by_pointer(st_ip_tcpofo, rd_merged, tcpext_TCPOFOMerge); - rrddim_set_by_pointer(st_ip_tcpofo, rd_pruned, tcpext_OfoPruned); - - rrdset_done(st_ip_tcpofo); + do_tcpext_connaborts = CONFIG_BOOLEAN_YES; + + static RRDSET *st_tcpconnaborts = NULL; + static RRDDIM *rd_baddata = NULL, *rd_userclosed = NULL, *rd_nomemory = NULL, *rd_timeout = NULL, *rd_linger = NULL, *rd_failed = NULL; + + if(unlikely(!st_tcpconnaborts)) { + st_tcpconnaborts = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcpconnaborts" + , NULL + , "tcp" + , NULL + , "TCP Connection Aborts" + , "connections/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_CONNABORTS + , update_every + , RRDSET_TYPE_LINE + ); + + rd_baddata = rrddim_add(st_tcpconnaborts, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_userclosed = rrddim_add(st_tcpconnaborts, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_nomemory = rrddim_add(st_tcpconnaborts, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_timeout = rrddim_add(st_tcpconnaborts, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_linger = rrddim_add(st_tcpconnaborts, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_failed = rrddim_add(st_tcpconnaborts, "TCPAbortFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_tcpconnaborts, rd_baddata, tcpext_TCPAbortOnData); + rrddim_set_by_pointer(st_tcpconnaborts, rd_userclosed, tcpext_TCPAbortOnClose); + rrddim_set_by_pointer(st_tcpconnaborts, rd_nomemory, tcpext_TCPAbortOnMemory); + rrddim_set_by_pointer(st_tcpconnaborts, rd_timeout, tcpext_TCPAbortOnTimeout); + rrddim_set_by_pointer(st_tcpconnaborts, rd_linger, tcpext_TCPAbortOnLinger); + rrddim_set_by_pointer(st_tcpconnaborts, rd_failed, tcpext_TCPAbortFailed); + rrdset_done(st_tcpconnaborts); + } + + if(do_tcpext_reorder == CONFIG_BOOLEAN_YES || (do_tcpext_reorder == CONFIG_BOOLEAN_AUTO && + (tcpext_TCPRenoReorder || + tcpext_TCPFACKReorder || + tcpext_TCPSACKReorder || + tcpext_TCPTSReorder || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcpext_reorder = CONFIG_BOOLEAN_YES; + + static RRDSET *st_tcpreorders = NULL; + static RRDDIM *rd_timestamp = NULL, *rd_sack = NULL, *rd_fack = NULL, *rd_reno = NULL; + + if(unlikely(!st_tcpreorders)) { + st_tcpreorders = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcpreorders" + , NULL + , "tcp" + , NULL + , "TCP Reordered Packets by Detection Method" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_REORDERS + , update_every + , RRDSET_TYPE_LINE + ); + + rd_timestamp = rrddim_add(st_tcpreorders, "TCPTSReorder", "timestamp", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_sack = rrddim_add(st_tcpreorders, "TCPSACKReorder", "sack", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_fack = rrddim_add(st_tcpreorders, "TCPFACKReorder", "fack", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_reno = rrddim_add(st_tcpreorders, "TCPRenoReorder", "reno", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_tcpreorders, rd_timestamp, tcpext_TCPTSReorder); + rrddim_set_by_pointer(st_tcpreorders, rd_sack, tcpext_TCPSACKReorder); + rrddim_set_by_pointer(st_tcpreorders, rd_fack, tcpext_TCPFACKReorder); + rrddim_set_by_pointer(st_tcpreorders, rd_reno, tcpext_TCPRenoReorder); + rrdset_done(st_tcpreorders); + } + + // -------------------------------------------------------------------- + + if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && + (tcpext_TCPOFOQueue || + tcpext_TCPOFODrop || + tcpext_TCPOFOMerge || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcpext_ofo = CONFIG_BOOLEAN_YES; + + static RRDSET *st_ip_tcpofo = NULL; + static RRDDIM *rd_inqueue = NULL, *rd_dropped = NULL, *rd_merged = NULL, *rd_pruned = NULL; + + if(unlikely(!st_ip_tcpofo)) { + + st_ip_tcpofo = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcpofo" + , NULL + , "tcp" + , NULL + , "TCP Out-Of-Order Queue" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_OFO + , update_every + , RRDSET_TYPE_LINE + ); + + rd_inqueue = rrddim_add(st_ip_tcpofo, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_dropped = rrddim_add(st_ip_tcpofo, "TCPOFODrop", "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_merged = rrddim_add(st_ip_tcpofo, "TCPOFOMerge", "merged", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_pruned = rrddim_add(st_ip_tcpofo, "OfoPruned", "pruned", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ip_tcpofo, rd_inqueue, tcpext_TCPOFOQueue); + rrddim_set_by_pointer(st_ip_tcpofo, rd_dropped, tcpext_TCPOFODrop); + rrddim_set_by_pointer(st_ip_tcpofo, rd_merged, tcpext_TCPOFOMerge); + rrddim_set_by_pointer(st_ip_tcpofo, rd_pruned, tcpext_OfoPruned); + rrdset_done(st_ip_tcpofo); + } + + if(do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && + (tcpext_SyncookiesSent || + tcpext_SyncookiesRecv || + tcpext_SyncookiesFailed || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcpext_syscookies = CONFIG_BOOLEAN_YES; + + static RRDSET *st_syncookies = NULL; + static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_failed = NULL; + + if(unlikely(!st_syncookies)) { + + st_syncookies = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcpsyncookies" + , NULL + , "tcp" + , NULL + , "TCP SYN Cookies" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_SYNCOOKIES + , update_every + , RRDSET_TYPE_LINE + ); + + rd_received = rrddim_add(st_syncookies, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_sent = rrddim_add(st_syncookies, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_failed = rrddim_add(st_syncookies, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_syncookies, rd_received, tcpext_SyncookiesRecv); + rrddim_set_by_pointer(st_syncookies, rd_sent, tcpext_SyncookiesSent); + rrddim_set_by_pointer(st_syncookies, rd_failed, tcpext_SyncookiesFailed); + rrdset_done(st_syncookies); + } + + if(do_tcpext_syn_queue == CONFIG_BOOLEAN_YES || (do_tcpext_syn_queue == CONFIG_BOOLEAN_AUTO && + (tcpext_TCPReqQFullDrop || + tcpext_TCPReqQFullDoCookies || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcpext_syn_queue = CONFIG_BOOLEAN_YES; + + static RRDSET *st_syn_queue = NULL; + static RRDDIM + *rd_TCPReqQFullDrop = NULL, + *rd_TCPReqQFullDoCookies = NULL; + + if(unlikely(!st_syn_queue)) { + + st_syn_queue = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcp_syn_queue" + , NULL + , "tcp" + , NULL + , "TCP SYN Queue Issues" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_SYN_QUEUE + , update_every + , RRDSET_TYPE_LINE + ); + + rd_TCPReqQFullDrop = rrddim_add(st_syn_queue, "TCPReqQFullDrop", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_TCPReqQFullDoCookies = rrddim_add(st_syn_queue, "TCPReqQFullDoCookies", "cookies", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_syn_queue, rd_TCPReqQFullDrop, tcpext_TCPReqQFullDrop); + rrddim_set_by_pointer(st_syn_queue, rd_TCPReqQFullDoCookies, tcpext_TCPReqQFullDoCookies); + rrdset_done(st_syn_queue); + } + + if(do_tcpext_accept_queue == CONFIG_BOOLEAN_YES || (do_tcpext_accept_queue == CONFIG_BOOLEAN_AUTO && + (tcpext_ListenOverflows || + tcpext_ListenDrops || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcpext_accept_queue = CONFIG_BOOLEAN_YES; + + static RRDSET *st_accept_queue = NULL; + static RRDDIM *rd_overflows = NULL, + *rd_drops = NULL; + + if(unlikely(!st_accept_queue)) { + + st_accept_queue = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcp_accept_queue" + , NULL + , "tcp" + , NULL + , "TCP Accept Queue Issues" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_ACCEPT_QUEUE + , update_every + , RRDSET_TYPE_LINE + ); + + rd_overflows = rrddim_add(st_accept_queue, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_drops = rrddim_add(st_accept_queue, "ListenDrops", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_accept_queue, rd_overflows, tcpext_ListenOverflows); + rrddim_set_by_pointer(st_accept_queue, rd_drops, tcpext_ListenDrops); + rrdset_done(st_accept_queue); + } + + // snmp Ip charts + + if(do_ip_packets == CONFIG_BOOLEAN_YES || (do_ip_packets == CONFIG_BOOLEAN_AUTO && + (snmp_root.ip_OutRequests || + snmp_root.ip_InReceives || + snmp_root.ip_ForwDatagrams || + snmp_root.ip_InDelivers || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip_packets = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_PACKETS + , 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); + } + + 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 == CONFIG_BOOLEAN_YES || (do_ip_fragsout == CONFIG_BOOLEAN_AUTO && + (snmp_root.ip_FragOKs || + snmp_root.ip_FragFails || + snmp_root.ip_FragCreates || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip_fragsout = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_FRAGMENTS + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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 == CONFIG_BOOLEAN_YES || (do_ip_fragsin == CONFIG_BOOLEAN_AUTO && + (snmp_root.ip_ReasmOKs || + snmp_root.ip_ReasmFails || + snmp_root.ip_ReasmReqds || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip_fragsin = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_FRAGMENTS + 1 + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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 == CONFIG_BOOLEAN_YES || (do_ip_errors == CONFIG_BOOLEAN_AUTO && + (snmp_root.ip_InDiscards || + snmp_root.ip_OutDiscards || + snmp_root.ip_InHdrErrors || + snmp_root.ip_InAddrErrors || + snmp_root.ip_InUnknownProtos || + snmp_root.ip_OutNoRoutes || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip_errors = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_ERRORS + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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_OutNoRoutes = rrddim_add(st, "OutNoRoutes", 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); + } + + 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); + } + + // snmp Icmp charts + + if(do_icmp_packets == CONFIG_BOOLEAN_YES || (do_icmp_packets == CONFIG_BOOLEAN_AUTO && + (snmp_root.icmp_InMsgs || + snmp_root.icmp_OutMsgs || + snmp_root.icmp_InErrors || + snmp_root.icmp_OutErrors || + snmp_root.icmp_InCsumErrors || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_icmp_packets = CONFIG_BOOLEAN_YES; + + { + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_ICMP + , 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); } - // -------------------------------------------------------------------- - - if(do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && - (tcpext_SyncookiesSent || - tcpext_SyncookiesRecv || - tcpext_SyncookiesFailed || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcpext_syscookies = CONFIG_BOOLEAN_YES; - - static RRDSET *st_syncookies = NULL; - static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_failed = NULL; - - if(unlikely(!st_syncookies)) { - - st_syncookies = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "tcpsyncookies" - , NULL - , "tcp" - , NULL - , "TCP SYN Cookies" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_TCP_SYNCOOKIES - , update_every - , RRDSET_TYPE_LINE - ); - - rd_received = rrddim_add(st_syncookies, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_sent = rrddim_add(st_syncookies, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_failed = rrddim_add(st_syncookies, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_syncookies); - - rrddim_set_by_pointer(st_syncookies, rd_received, tcpext_SyncookiesRecv); - rrddim_set_by_pointer(st_syncookies, rd_sent, tcpext_SyncookiesSent); - rrddim_set_by_pointer(st_syncookies, rd_failed, tcpext_SyncookiesFailed); - - rrdset_done(st_syncookies); + 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); + } + + { + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_ICMP + 1 + , 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); } - // -------------------------------------------------------------------- - - if(do_tcpext_syn_queue == CONFIG_BOOLEAN_YES || (do_tcpext_syn_queue == CONFIG_BOOLEAN_AUTO && - (tcpext_TCPReqQFullDrop || - tcpext_TCPReqQFullDoCookies || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcpext_syn_queue = CONFIG_BOOLEAN_YES; - - static RRDSET *st_syn_queue = NULL; - static RRDDIM - *rd_TCPReqQFullDrop = NULL, - *rd_TCPReqQFullDoCookies = NULL; - - if(unlikely(!st_syn_queue)) { - - st_syn_queue = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "tcp_syn_queue" - , NULL - , "tcp" - , NULL - , "TCP SYN Queue Issues" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_TCP_SYN_QUEUE - , update_every - , RRDSET_TYPE_LINE - ); - - rd_TCPReqQFullDrop = rrddim_add(st_syn_queue, "TCPReqQFullDrop", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_TCPReqQFullDoCookies = rrddim_add(st_syn_queue, "TCPReqQFullDoCookies", "cookies", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_syn_queue); - - rrddim_set_by_pointer(st_syn_queue, rd_TCPReqQFullDrop, tcpext_TCPReqQFullDrop); - rrddim_set_by_pointer(st_syn_queue, rd_TCPReqQFullDoCookies, tcpext_TCPReqQFullDoCookies); - - rrdset_done(st_syn_queue); + 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); + } + } + + // snmp IcmpMsg charts + + if(do_icmpmsg == CONFIG_BOOLEAN_YES || (do_icmpmsg == CONFIG_BOOLEAN_AUTO && + (snmp_root.icmpmsg_InEchoReps || + snmp_root.icmpmsg_OutEchoReps || + snmp_root.icmpmsg_InDestUnreachs || + snmp_root.icmpmsg_OutDestUnreachs || + snmp_root.icmpmsg_InRedirects || + snmp_root.icmpmsg_OutRedirects || + snmp_root.icmpmsg_InEchos || + snmp_root.icmpmsg_OutEchos || + snmp_root.icmpmsg_InRouterAdvert || + snmp_root.icmpmsg_OutRouterAdvert || + snmp_root.icmpmsg_InRouterSelect || + snmp_root.icmpmsg_OutRouterSelect || + snmp_root.icmpmsg_InTimeExcds || + snmp_root.icmpmsg_OutTimeExcds || + snmp_root.icmpmsg_InParmProbs || + snmp_root.icmpmsg_OutParmProbs || + snmp_root.icmpmsg_InTimestamps || + snmp_root.icmpmsg_OutTimestamps || + snmp_root.icmpmsg_InTimestampReps || + snmp_root.icmpmsg_OutTimestampReps || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_icmpmsg = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_ICMP + 2 + , update_every + , RRDSET_TYPE_LINE + ); + + 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); + } + + 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); + } + + // snmp Tcp charts + + // this is smart enough to update it, only when it is changed + rrdvar_custom_host_variable_set(localhost, tcp_max_connections_var, snmp_root.tcp_MaxConn); + + // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html + if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && + (snmp_root.tcp_CurrEstab || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcp_sockets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_CurrEstab = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "tcpsock" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Connections" + , "active connections" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + , update_every + , RRDSET_TYPE_LINE + ); + + rd_CurrEstab = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + + rrddim_set_by_pointer(st, rd_CurrEstab, (collected_number)snmp_root.tcp_CurrEstab); + rrdset_done(st); + } + + if(do_tcp_packets == CONFIG_BOOLEAN_YES || (do_tcp_packets == CONFIG_BOOLEAN_AUTO && + (snmp_root.tcp_InSegs || + snmp_root.tcp_OutSegs || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcp_packets = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + 4 + , update_every + , RRDSET_TYPE_LINE + ); + + rd_InSegs = rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutSegs = rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + 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 == CONFIG_BOOLEAN_YES || (do_tcp_errors == CONFIG_BOOLEAN_AUTO && + (snmp_root.tcp_InErrs || + snmp_root.tcp_InCsumErrors || + snmp_root.tcp_RetransSegs || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcp_errors = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + 20 + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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_opens == CONFIG_BOOLEAN_YES || (do_tcp_opens == CONFIG_BOOLEAN_AUTO && + (snmp_root.tcp_ActiveOpens || + snmp_root.tcp_PassiveOpens || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcp_opens = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_ActiveOpens = NULL, + *rd_PassiveOpens = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "tcpopens" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Opens" + , "connections/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + 5 + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rd_ActiveOpens = rrddim_add(st, "ActiveOpens", "active", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_PassiveOpens = rrddim_add(st, "PassiveOpens", "passive", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + 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); + rrdset_done(st); + } + + if(do_tcp_handshake == CONFIG_BOOLEAN_YES || (do_tcp_handshake == CONFIG_BOOLEAN_AUTO && + (snmp_root.tcp_EstabResets || + snmp_root.tcp_OutRsts || + snmp_root.tcp_AttemptFails || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_tcp_handshake = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_EstabResets = NULL, + *rd_OutRsts = NULL, + *rd_AttemptFails = NULL, + *rd_TCPSynRetrans = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "tcphandshake" + , NULL + , "tcp" + , NULL + , "IPv4 TCP Handshake Issues" + , "events/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + 30 + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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_AttemptFails = rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_TCPSynRetrans = rrddim_add(st, "TCPSynRetrans", "SynRetrans", 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + 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_AttemptFails, (collected_number)snmp_root.tcp_AttemptFails); + rrddim_set_by_pointer(st, rd_TCPSynRetrans, tcpext_TCPSynRetrans); + rrdset_done(st); + } + + // snmp Udp charts + + // see http://net-snmp.sourceforge.net/docs/mibs/udp.html + if(do_udp_packets == CONFIG_BOOLEAN_YES || (do_udp_packets == CONFIG_BOOLEAN_AUTO && + (snmp_root.udp_InDatagrams || + snmp_root.udp_OutDatagrams || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_udp_packets = CONFIG_BOOLEAN_YES; + + static RRDSET *st = NULL; + static RRDDIM *rd_InDatagrams = NULL, + *rd_OutDatagrams = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP + , "udppackets" + , NULL + , "udp" + , NULL + , "IPv4 UDP Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_UDP + , 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); + } + + 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 == CONFIG_BOOLEAN_YES || (do_udp_errors == CONFIG_BOOLEAN_AUTO && + (snmp_root.udp_InErrors || + snmp_root.udp_NoPorts || + snmp_root.udp_RcvbufErrors || + snmp_root.udp_SndbufErrors || + snmp_root.udp_InCsumErrors || + snmp_root.udp_IgnoredMulti || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_udp_errors = CONFIG_BOOLEAN_YES; + + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_UDP + 10 + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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); + } + + // snmp UdpLite charts + + if(do_udplite_packets == CONFIG_BOOLEAN_YES || (do_udplite_packets == CONFIG_BOOLEAN_AUTO && + (snmp_root.udplite_InDatagrams || + snmp_root.udplite_OutDatagrams || + snmp_root.udplite_NoPorts || + snmp_root.udplite_InErrors || + snmp_root.udplite_InCsumErrors || + snmp_root.udplite_RcvbufErrors || + snmp_root.udplite_SndbufErrors || + snmp_root.udplite_IgnoredMulti || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_udplite_packets = CONFIG_BOOLEAN_YES; + + { + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_UDPLITE + , 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); } - // -------------------------------------------------------------------- - - if(do_tcpext_accept_queue == CONFIG_BOOLEAN_YES || (do_tcpext_accept_queue == CONFIG_BOOLEAN_AUTO && - (tcpext_ListenOverflows || - tcpext_ListenDrops || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcpext_accept_queue = CONFIG_BOOLEAN_YES; - - static RRDSET *st_accept_queue = NULL; - static RRDDIM *rd_overflows = NULL, - *rd_drops = NULL; - - if(unlikely(!st_accept_queue)) { - - st_accept_queue = rrdset_create_localhost( - RRD_TYPE_NET_NETSTAT - , "tcp_accept_queue" - , NULL - , "tcp" - , NULL - , "TCP Accept Queue Issues" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NETSTAT_NAME - , NETDATA_CHART_PRIO_IP_TCP_ACCEPT_QUEUE - , update_every - , RRDSET_TYPE_LINE - ); - - rd_overflows = rrddim_add(st_accept_queue, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_drops = rrddim_add(st_accept_queue, "ListenDrops", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st_accept_queue); - - rrddim_set_by_pointer(st_accept_queue, rd_overflows, tcpext_ListenOverflows); - rrddim_set_by_pointer(st_accept_queue, rd_drops, tcpext_ListenDrops); - - rrdset_done(st_accept_queue); + 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); + } + + { + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_UDPLITE + 10 + , 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); } + 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); } } + // snmp6 charts + + if(do_ip6_bandwidth == CONFIG_BOOLEAN_YES || (do_ip6_bandwidth == CONFIG_BOOLEAN_AUTO && + (Ip6InOctets || + Ip6OutOctets || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_bandwidth = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + "system" + , "ipv6" + , NULL + , "network" + , NULL + , "IPv6 Bandwidth" + , "kilobits/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_IPV6 + , 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); + } + + rrddim_set_by_pointer(st, rd_received, Ip6InOctets); + rrddim_set_by_pointer(st, rd_sent, Ip6OutOctets); + rrdset_done(st); + } + + if(do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO && + (Ip6InReceives || + Ip6OutRequests || + Ip6InDelivers || + Ip6OutForwDatagrams || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_packets = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL, + *rd_forwarded = NULL, + *rd_delivers = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "packets" + , NULL + , "packets" + , NULL + , "IPv6 Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_PACKETS + , 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); + } + + 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); + } + + if(do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO && + (Ip6FragOKs || + Ip6FragFails || + Ip6FragCreates || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_fragsout = CONFIG_BOOLEAN_YES; + 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 + , "fragments6" + , NULL + , "IPv6 Fragments Sent" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_FRAGSOUT + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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); + } + + if(do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO && + (Ip6ReasmOKs || + Ip6ReasmFails || + Ip6ReasmTimeout || + Ip6ReasmReqds || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_fragsin = CONFIG_BOOLEAN_YES; + + 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 + , "fragments6" + , NULL + , "IPv6 Fragments Reassembly" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_FRAGSIN + , update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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); + } + + if(do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && + (Ip6InDiscards || + Ip6OutDiscards || + Ip6InHdrErrors || + Ip6InAddrErrors || + Ip6InUnknownProtos || + Ip6InTooBigErrors || + Ip6InTruncatedPkts || + Ip6InNoRoutes || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_errors = CONFIG_BOOLEAN_YES; + 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" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ERRORS + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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); + } + + if(do_ip6_udp_packets == CONFIG_BOOLEAN_YES || (do_ip6_udp_packets == CONFIG_BOOLEAN_AUTO && + (Udp6InDatagrams || + Udp6OutDatagrams || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_udp_packets = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "udppackets" + , NULL + , "udp6" + , NULL + , "IPv6 UDP Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_UDP_PACKETS + , 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); + } + + rrddim_set_by_pointer(st, rd_received, Udp6InDatagrams); + rrddim_set_by_pointer(st, rd_sent, Udp6OutDatagrams); + rrdset_done(st); + } + + if(do_ip6_udp_errors == CONFIG_BOOLEAN_YES || (do_ip6_udp_errors == CONFIG_BOOLEAN_AUTO && + (Udp6InErrors || + Udp6NoPorts || + Udp6RcvbufErrors || + Udp6SndbufErrors || + Udp6InCsumErrors || + Udp6IgnoredMulti || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_udp_errors = CONFIG_BOOLEAN_YES; + 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 + , "udp6" + , NULL + , "IPv6 UDP Errors" + , "events/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_UDP_ERRORS + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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); + } + + if(do_ip6_udplite_packets == CONFIG_BOOLEAN_YES || (do_ip6_udplite_packets == CONFIG_BOOLEAN_AUTO && + (UdpLite6InDatagrams || + UdpLite6OutDatagrams || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_udplite_packets = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_received = NULL, + *rd_sent = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "udplitepackets" + , NULL + , "udplite6" + , NULL + , "IPv6 UDPlite Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_UDPLITE_PACKETS + , 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); + } + + rrddim_set_by_pointer(st, rd_received, UdpLite6InDatagrams); + rrddim_set_by_pointer(st, rd_sent, UdpLite6OutDatagrams); + rrdset_done(st); + } + + if(do_ip6_udplite_errors == CONFIG_BOOLEAN_YES || (do_ip6_udplite_errors == CONFIG_BOOLEAN_AUTO && + (UdpLite6InErrors || + UdpLite6NoPorts || + UdpLite6RcvbufErrors || + UdpLite6SndbufErrors || + Udp6InCsumErrors || + UdpLite6InCsumErrors || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_udplite_errors = CONFIG_BOOLEAN_YES; + 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 + , "udplite6" + , NULL + , "IPv6 UDP Lite Errors" + , "events/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_UDPLITE_ERRORS + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + 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); + } + + if(do_ip6_mcast == CONFIG_BOOLEAN_YES || (do_ip6_mcast == CONFIG_BOOLEAN_AUTO && + (Ip6OutMcastOctets || + Ip6InMcastOctets || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_mcast = CONFIG_BOOLEAN_YES; + 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 + , "multicast6" + , NULL + , "IPv6 Multicast Bandwidth" + , "kilobits/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_MCAST + , update_every + , RRDSET_TYPE_AREA + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + rrddim_set_by_pointer(st, rd_Ip6InMcastOctets, Ip6InMcastOctets); + rrddim_set_by_pointer(st, rd_Ip6OutMcastOctets, Ip6OutMcastOctets); + rrdset_done(st); + } + + if(do_ip6_bcast == CONFIG_BOOLEAN_YES || (do_ip6_bcast == CONFIG_BOOLEAN_AUTO && + (Ip6OutBcastOctets || + Ip6InBcastOctets || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_bcast = CONFIG_BOOLEAN_YES; + 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 + , "broadcast6" + , NULL + , "IPv6 Broadcast Bandwidth" + , "kilobits/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_BCAST + , update_every + , RRDSET_TYPE_AREA + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + 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); + } + + rrddim_set_by_pointer(st, rd_Ip6InBcastOctets, Ip6InBcastOctets); + rrddim_set_by_pointer(st, rd_Ip6OutBcastOctets, Ip6OutBcastOctets); + rrdset_done(st); + } + + if(do_ip6_mcast_p == CONFIG_BOOLEAN_YES || (do_ip6_mcast_p == CONFIG_BOOLEAN_AUTO && + (Ip6OutMcastPkts || + Ip6InMcastPkts || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_mcast_p = CONFIG_BOOLEAN_YES; + 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 + , "multicast6" + , NULL + , "IPv6 Multicast Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_MCAST_PACKETS + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rd_Ip6InMcastPkts = rrddim_add(st, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_Ip6OutMcastPkts = rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st, rd_Ip6InMcastPkts, Ip6InMcastPkts); + rrddim_set_by_pointer(st, rd_Ip6OutMcastPkts, Ip6OutMcastPkts); + rrdset_done(st); + } + + if(do_ip6_icmp == CONFIG_BOOLEAN_YES || (do_ip6_icmp == CONFIG_BOOLEAN_AUTO && + (Icmp6InMsgs || + Icmp6OutMsgs || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_Icmp6InMsgs = NULL, + *rd_Icmp6OutMsgs = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmp" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Messages" + , "messages/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP + , 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); + } + + rrddim_set_by_pointer(st, rd_Icmp6InMsgs, Icmp6InMsgs); + rrddim_set_by_pointer(st, rd_Icmp6OutMsgs, Icmp6OutMsgs); + rrdset_done(st); + } + + if(do_ip6_icmp_redir == CONFIG_BOOLEAN_YES || (do_ip6_icmp_redir == CONFIG_BOOLEAN_AUTO && + (Icmp6InRedirects || + Icmp6OutRedirects || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_redir = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_Icmp6InRedirects = NULL, + *rd_Icmp6OutRedirects = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmpredir" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Redirects" + , "redirects/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_REDIR + , 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); + } + + rrddim_set_by_pointer(st, rd_Icmp6InRedirects, Icmp6InRedirects); + rrddim_set_by_pointer(st, rd_Icmp6OutRedirects, Icmp6OutRedirects); + rrdset_done(st); + } + + if(do_ip6_icmp_errors == CONFIG_BOOLEAN_YES || (do_ip6_icmp_errors == CONFIG_BOOLEAN_AUTO && + (Icmp6InErrors || + Icmp6OutErrors || + Icmp6InCsumErrors || + Icmp6InDestUnreachs || + Icmp6InPktTooBigs || + Icmp6InTimeExcds || + Icmp6InParmProblems || + Icmp6OutDestUnreachs || + Icmp6OutPktTooBigs || + Icmp6OutTimeExcds || + Icmp6OutParmProblems || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_errors = CONFIG_BOOLEAN_YES; + 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 + , "icmp6" + , NULL + , "IPv6 ICMP Errors" + , "errors/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_ERRORS + , 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); + } + + 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); + } + + if(do_ip6_icmp_echos == CONFIG_BOOLEAN_YES || (do_ip6_icmp_echos == CONFIG_BOOLEAN_AUTO && + (Icmp6InEchos || + Icmp6OutEchos || + Icmp6InEchoReplies || + Icmp6OutEchoReplies || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_echos = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_InEchos = NULL, + *rd_OutEchos = NULL, + *rd_InEchoReplies = NULL, + *rd_OutEchoReplies = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmpechos" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP Echo" + , "messages/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_ECHOS + , 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); + } + + 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); + } + + if(do_ip6_icmp_groupmemb == CONFIG_BOOLEAN_YES || (do_ip6_icmp_groupmemb == CONFIG_BOOLEAN_AUTO && + (Icmp6InGroupMembQueries || + Icmp6OutGroupMembQueries || + Icmp6InGroupMembResponses || + Icmp6OutGroupMembResponses || + Icmp6InGroupMembReductions || + Icmp6OutGroupMembReductions || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_groupmemb = CONFIG_BOOLEAN_YES; + 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 + , "icmp6" + , NULL + , "IPv6 ICMP Group Membership" + , "messages/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_GROUPMEMB + , 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); + } + + 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); + } + + if(do_ip6_icmp_router == CONFIG_BOOLEAN_YES || (do_ip6_icmp_router == CONFIG_BOOLEAN_AUTO && + (Icmp6InRouterSolicits || + Icmp6OutRouterSolicits || + Icmp6InRouterAdvertisements || + Icmp6OutRouterAdvertisements || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_router = CONFIG_BOOLEAN_YES; + 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 + , "icmprouter" + , NULL + , "icmp6" + , NULL + , "IPv6 Router Messages" + , "messages/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_ROUTER + , 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); + } + + 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); + } + + if(do_ip6_icmp_neighbor == CONFIG_BOOLEAN_YES || (do_ip6_icmp_neighbor == CONFIG_BOOLEAN_AUTO && + (Icmp6InNeighborSolicits || + Icmp6OutNeighborSolicits || + Icmp6InNeighborAdvertisements || + Icmp6OutNeighborAdvertisements || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_neighbor = CONFIG_BOOLEAN_YES; + 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 + , "icmp6" + , NULL + , "IPv6 Neighbor Messages" + , "messages/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_NEIGHBOR + , 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); + } + + 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); + } + + if(do_ip6_icmp_mldv2 == CONFIG_BOOLEAN_YES || (do_ip6_icmp_mldv2 == CONFIG_BOOLEAN_AUTO && + (Icmp6InMLDv2Reports || + Icmp6OutMLDv2Reports || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_mldv2 = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_InMLDv2Reports = NULL, + *rd_OutMLDv2Reports = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "icmpmldv2" + , NULL + , "icmp6" + , NULL + , "IPv6 ICMP MLDv2 Reports" + , "reports/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_LDV2 + , 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); + } + + rrddim_set_by_pointer(st, rd_InMLDv2Reports, Icmp6InMLDv2Reports); + rrddim_set_by_pointer(st, rd_OutMLDv2Reports, Icmp6OutMLDv2Reports); + rrdset_done(st); + } + + if(do_ip6_icmp_types == CONFIG_BOOLEAN_YES || (do_ip6_icmp_types == CONFIG_BOOLEAN_AUTO && + (Icmp6InType1 || + Icmp6InType128 || + Icmp6InType129 || + Icmp6InType136 || + Icmp6OutType1 || + Icmp6OutType128 || + Icmp6OutType129 || + Icmp6OutType133 || + Icmp6OutType135 || + Icmp6OutType143 || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_icmp_types = CONFIG_BOOLEAN_YES; + 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 + , "icmp6" + , NULL + , "IPv6 ICMP Types" + , "messages/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_TYPES + , 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); + } + + 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); + } + + if(do_ip6_ect == CONFIG_BOOLEAN_YES || (do_ip6_ect == CONFIG_BOOLEAN_AUTO && + (Ip6InNoECTPkts || + Ip6InECT1Pkts || + Ip6InECT0Pkts || + Ip6InCEPkts || + netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + do_ip6_ect = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; + static RRDDIM *rd_InNoECTPkts = NULL, + *rd_InECT1Pkts = NULL, + *rd_InECT0Pkts = NULL, + *rd_InCEPkts = NULL; + + if(unlikely(!st)) { + st = rrdset_create_localhost( + RRD_TYPE_NET_SNMP6 + , "ect" + , NULL + , "packets" + , NULL + , "IPv6 ECT Packets" + , "packets/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IPV6_ECT + , 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); + } + + 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); + } + return 0; } diff --git a/collectors/proc.plugin/proc_net_rpc_nfs.c b/collectors/proc.plugin/proc_net_rpc_nfs.c index f5702859c..b1ff4e05a 100644 --- a/collectors/proc.plugin/proc_net_rpc_nfs.c +++ b/collectors/proc.plugin/proc_net_rpc_nfs.c @@ -275,8 +275,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if(do_net == 2) { static RRDSET *st = NULL; static RRDDIM *rd_udp = NULL, @@ -303,7 +301,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { 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 (void)net_count; @@ -314,8 +311,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_rpc == 2) { static RRDSET *st = NULL; static RRDDIM *rd_calls = NULL, @@ -343,7 +338,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { 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_by_pointer(st, rd_calls, rpc_calls); rrddim_set_by_pointer(st, rd_retransmits, rpc_retransmits); @@ -351,8 +345,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_proc2 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -371,7 +363,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , RRDSET_TYPE_STACKED ); } - else rrdset_next(st); size_t i; for(i = 0; nfs_proc2_values[i].present ; i++) { @@ -384,8 +375,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_proc3 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -404,7 +393,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , RRDSET_TYPE_STACKED ); } - else rrdset_next(st); size_t i; for(i = 0; nfs_proc3_values[i].present ; i++) { @@ -417,8 +405,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_proc4 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -437,7 +423,6 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , RRDSET_TYPE_STACKED ); } - else rrdset_next(st); size_t i; for(i = 0; nfs_proc4_values[i].present ; i++) { diff --git a/collectors/proc.plugin/proc_net_rpc_nfsd.c b/collectors/proc.plugin/proc_net_rpc_nfsd.c index 48f218e44..bd1da8889 100644 --- a/collectors/proc.plugin/proc_net_rpc_nfsd.c +++ b/collectors/proc.plugin/proc_net_rpc_nfsd.c @@ -225,8 +225,8 @@ struct nfsd_procs nfsd4_ops_values[] = { int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; - static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1; - static int ra_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0; + static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1; + static int proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0; if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; @@ -243,7 +243,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { do_fh = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "file handles", 1); do_io = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "I/O", 1); do_th = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "threads", 1); - do_ra = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read ahead", 1); do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "network", 1); do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "rpc", 1); do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v2 procedures", 1); @@ -258,7 +257,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { if(do_fh) do_fh = 1; if(do_io) do_io = 1; if(do_th) do_th = 1; - if(do_ra) do_ra = 1; if(do_net) do_net = 1; if(do_rpc) do_rpc = 1; if(do_proc2) do_proc2 = 1; @@ -273,7 +271,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { unsigned long long fh_stale = 0; unsigned long long io_read = 0, io_write = 0; unsigned long long th_threads = 0; - unsigned long long ra_size = 0, ra_hist10 = 0, ra_hist20 = 0, ra_hist30 = 0, ra_hist40 = 0, ra_hist50 = 0, ra_hist60 = 0, ra_hist70 = 0, ra_hist80 = 0, ra_hist90 = 0, ra_hist100 = 0, ra_none = 0; unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0; unsigned long long rpc_calls = 0, rpc_bad_format = 0, rpc_bad_auth = 0, rpc_bad_client = 0; @@ -336,38 +333,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { do_th = 2; } - else if(do_ra == 1 && strcmp(type, "ra") == 0) { - if(unlikely(words < 13)) { - error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 13); - continue; - } - - // readahead cache has been disabled since 2019 (kernel 5.4) - // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/fs/nfsd/vfs.c?id=501cb1849f865960501d19d54e6a5af306f9b6fd - - ra_size = str2ull(procfile_lineword(ff, l, 1)); - ra_hist10 = str2ull(procfile_lineword(ff, l, 2)); - ra_hist20 = str2ull(procfile_lineword(ff, l, 3)); - ra_hist30 = str2ull(procfile_lineword(ff, l, 4)); - ra_hist40 = str2ull(procfile_lineword(ff, l, 5)); - ra_hist50 = str2ull(procfile_lineword(ff, l, 6)); - ra_hist60 = str2ull(procfile_lineword(ff, l, 7)); - ra_hist70 = str2ull(procfile_lineword(ff, l, 8)); - ra_hist80 = str2ull(procfile_lineword(ff, l, 9)); - ra_hist90 = str2ull(procfile_lineword(ff, l, 10)); - ra_hist100 = str2ull(procfile_lineword(ff, l, 11)); - ra_none = str2ull(procfile_lineword(ff, l, 12)); - - unsigned long long sum = ra_hist10 + ra_hist20 + ra_hist30 + ra_hist40 + ra_hist50 + ra_hist60 + ra_hist70 + ra_hist80 + ra_hist90 + ra_hist100 + ra_none; - if(sum == 0ULL) { - if(!ra_warning) { - info("Disabling /proc/net/rpc/nfsd read ahead histogram. It seems unused on this machine. It will be enabled automatically when found with data in it."); - ra_warning = 1; - } - do_ra = -1; - } - else do_ra = 2; - } else if(do_net == 1 && strcmp(type, "net") == 0) { if(unlikely(words < 5)) { error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 5); @@ -484,8 +449,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { } } - // -------------------------------------------------------------------- - if(do_rc == 2) { static RRDSET *st = NULL; static RRDDIM *rd_hits = NULL, @@ -512,7 +475,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { 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_by_pointer(st, rd_hits, rc_hits); rrddim_set_by_pointer(st, rd_misses, rc_misses); @@ -520,8 +482,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_fh == 2) { static RRDSET *st = NULL; static RRDDIM *rd_stale = NULL; @@ -545,14 +505,11 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rd_stale = rrddim_add(st, "stale", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_stale, fh_stale); rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_io == 2) { static RRDSET *st = NULL; static RRDDIM *rd_read = NULL, @@ -577,15 +534,12 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { 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_by_pointer(st, rd_read, io_read); rrddim_set_by_pointer(st, rd_write, io_write); rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_th == 2) { static RRDSET *st = NULL; static RRDDIM *rd_threads = NULL; @@ -608,78 +562,11 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rd_threads = rrddim_add(st, "threads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_threads, th_threads); rrdset_done(st); - - } - - // -------------------------------------------------------------------- - - if(do_ra == 2) { - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NFSD_NAME - , NETDATA_CHART_PRIO_NFSD_READAHEAD - , 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 - (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) { static RRDSET *st = NULL; static RRDDIM *rd_udp = NULL, @@ -705,7 +592,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { 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 (void)net_count; @@ -716,8 +602,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_rpc == 2) { static RRDSET *st = NULL; static RRDDIM *rd_calls = NULL, @@ -745,7 +629,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { 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 (void)rpc_bad_client; @@ -756,8 +639,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_proc2 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -776,7 +657,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , RRDSET_TYPE_STACKED ); } - else rrdset_next(st); size_t i; for(i = 0; nfsd_proc2_values[i].present ; i++) { @@ -789,8 +669,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_proc3 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -809,7 +687,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , RRDSET_TYPE_STACKED ); } - else rrdset_next(st); size_t i; for(i = 0; nfsd_proc3_values[i].present ; i++) { @@ -822,8 +699,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_proc4 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -842,7 +717,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , RRDSET_TYPE_STACKED ); } - else rrdset_next(st); size_t i; for(i = 0; nfsd_proc4_values[i].present ; i++) { @@ -855,8 +729,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { rrdset_done(st); } - // -------------------------------------------------------------------- - if(do_proc4ops == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { @@ -875,7 +747,6 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , RRDSET_TYPE_STACKED ); } - else rrdset_next(st); size_t i; for(i = 0; nfsd4_ops_values[i].present ; i++) { diff --git a/collectors/proc.plugin/proc_net_sctp_snmp.c b/collectors/proc.plugin/proc_net_sctp_snmp.c index 343cc5afb..292449a73 100644 --- a/collectors/proc.plugin/proc_net_sctp_snmp.c +++ b/collectors/proc.plugin/proc_net_sctp_snmp.c @@ -148,7 +148,6 @@ int do_proc_net_sctp_snmp(int update_every, usec_t dt) { rd_established = rrddim_add(st, "SctpCurrEstab", "established", 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_established, SctpCurrEstab); rrdset_done(st); @@ -190,7 +189,6 @@ int do_proc_net_sctp_snmp(int update_every, usec_t dt) { rd_aborted = rrddim_add(st, "SctpAborteds", "aborted", -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_shutdown = rrddim_add(st, "SctpShutdowns", "shutdown", -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_active, SctpActiveEstabs); rrddim_set_by_pointer(st, rd_passive, SctpPassiveEstabs); @@ -230,7 +228,6 @@ int do_proc_net_sctp_snmp(int update_every, usec_t dt) { rd_received = rrddim_add(st, "SctpInSCTPPacks", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_sent = rrddim_add(st, "SctpOutSCTPPacks", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_received, SctpInSCTPPacks); rrddim_set_by_pointer(st, rd_sent, SctpOutSCTPPacks); @@ -268,7 +265,6 @@ int do_proc_net_sctp_snmp(int update_every, usec_t dt) { rd_invalid = rrddim_add(st, "SctpOutOfBlues", "invalid", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_csum = rrddim_add(st, "SctpChecksumErrors", "checksum", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_invalid, SctpOutOfBlues); rrddim_set_by_pointer(st, rd_csum, SctpChecksumErrors); @@ -306,7 +302,6 @@ int do_proc_net_sctp_snmp(int update_every, usec_t dt) { rd_reassembled = rrddim_add(st, "SctpReasmUsrMsgs", "reassembled", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_fragmented = rrddim_add(st, "SctpFragUsrMsgs", "fragmented", -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_reassembled, SctpReasmUsrMsgs); rrddim_set_by_pointer(st, rd_fragmented, SctpFragUsrMsgs); @@ -357,7 +352,6 @@ int do_proc_net_sctp_snmp(int update_every, usec_t dt) { rd_OutOrder = rrddim_add(st, "SctpOutOrderChunks", "OutOrder", -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_OutUnorder = rrddim_add(st, "SctpOutUnorderChunks", "OutUnorder", -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_InCtrl, SctpInCtrlChunks); rrddim_set_by_pointer(st, rd_InOrder, SctpInOrderChunks); diff --git a/collectors/proc.plugin/proc_net_snmp.c b/collectors/proc.plugin/proc_net_snmp.c deleted file mode 100644 index b03a6ac74..000000000 --- a/collectors/proc.plugin/proc_net_snmp.c +++ /dev/null @@ -1,1130 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "plugin_proc.h" -#define PLUGIN_PROC_MODULE_NET_SNMP_NAME "/proc/net/snmp" - -#define RRD_TYPE_NET_SNMP "ipv4" - -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; - - static procfile *ff = NULL; - static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1, - do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_tcp_opens = -1, - 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 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; - - if(unlikely(!arl_ip)) { - do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 packets", CONFIG_BOOLEAN_AUTO); - do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", CONFIG_BOOLEAN_AUTO); - do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", CONFIG_BOOLEAN_AUTO); - do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 errors", CONFIG_BOOLEAN_AUTO); - do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", CONFIG_BOOLEAN_AUTO); - do_tcp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", CONFIG_BOOLEAN_AUTO); - do_tcp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", CONFIG_BOOLEAN_AUTO); - do_tcp_opens = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP opens", CONFIG_BOOLEAN_AUTO); - do_tcp_handshake = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", CONFIG_BOOLEAN_AUTO); - do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", CONFIG_BOOLEAN_AUTO); - do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", CONFIG_BOOLEAN_AUTO); - do_icmp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 ICMP packets", CONFIG_BOOLEAN_AUTO); - do_icmpmsg = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 ICMP messages", CONFIG_BOOLEAN_AUTO); - do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 UDPLite packets", CONFIG_BOOLEAN_AUTO); - - hash_ip = simple_hash("Ip"); - hash_tcp = simple_hash("Tcp"); - hash_udp = simple_hash("Udp"); - hash_icmp = simple_hash("Icmp"); - hash_icmpmsg = simple_hash("IcmpMsg"); - hash_udplite = simple_hash("UdpLite"); - - 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_custom(arl_tcp, "MaxConn", arl_callback_ssize_t, &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)) { - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp"); - ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "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; - size_t words, w; - - for(l = 0; l < lines ;l++) { - char *key = procfile_lineword(ff, l, 0); - uint32_t hash = simple_hash(key); - - if(unlikely(hash == hash_ip && strcmp(key, "Ip") == 0)) { - size_t h = l++; - - if(strcmp(procfile_lineword(ff, l, 0), "Ip") != 0) { - error("Cannot read Ip line from /proc/net/snmp."); - break; - } - - words = procfile_linewords(ff, l); - if(words < 3) { - error("Cannot read /proc/net/snmp Ip line. Expected 3+ params, read %zu.", words); - continue; - } - - 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 == CONFIG_BOOLEAN_YES || (do_ip_packets == CONFIG_BOOLEAN_AUTO && - (snmp_root.ip_OutRequests || - snmp_root.ip_InReceives || - snmp_root.ip_ForwDatagrams || - snmp_root.ip_InDelivers || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_packets = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_PACKETS - , 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_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 == CONFIG_BOOLEAN_YES || (do_ip_fragsout == CONFIG_BOOLEAN_AUTO && - (snmp_root.ip_FragOKs || - snmp_root.ip_FragFails || - snmp_root.ip_FragCreates || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_fragsout = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_FRAGMENTS - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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 == CONFIG_BOOLEAN_YES || (do_ip_fragsin == CONFIG_BOOLEAN_AUTO && - (snmp_root.ip_ReasmOKs || - snmp_root.ip_ReasmFails || - snmp_root.ip_ReasmReqds || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_fragsin = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_FRAGMENTS + 1 - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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 == CONFIG_BOOLEAN_YES || (do_ip_errors == CONFIG_BOOLEAN_AUTO && - (snmp_root.ip_InDiscards || - snmp_root.ip_OutDiscards || - snmp_root.ip_InHdrErrors || - snmp_root.ip_InAddrErrors || - snmp_root.ip_InUnknownProtos || - snmp_root.ip_OutNoRoutes || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_errors = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_ERRORS - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_OutNoRoutes = rrddim_add(st, "OutNoRoutes", 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_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); - } - } - else if(unlikely(hash == hash_icmp && strcmp(key, "Icmp") == 0)) { - size_t h = l++; - - if(strcmp(procfile_lineword(ff, l, 0), "Icmp") != 0) { - error("Cannot read Icmp line from /proc/net/snmp."); - break; - } - - words = procfile_linewords(ff, l); - if(words < 3) { - error("Cannot read /proc/net/snmp Icmp line. Expected 3+ params, read %zu.", words); - continue; - } - - 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 == CONFIG_BOOLEAN_YES || (do_icmp_packets == CONFIG_BOOLEAN_AUTO && - (snmp_root.icmp_InMsgs || - snmp_root.icmp_OutMsgs || - snmp_root.icmp_InErrors || - snmp_root.icmp_OutErrors || - snmp_root.icmp_InCsumErrors || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_packets = CONFIG_BOOLEAN_YES; - - { - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_ICMP - , 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); - } - - { - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_ICMP + 1 - , 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 if(unlikely(hash == hash_icmpmsg && strcmp(key, "IcmpMsg") == 0)) { - size_t h = l++; - - if(strcmp(procfile_lineword(ff, l, 0), "IcmpMsg") != 0) { - error("Cannot read IcmpMsg line from /proc/net/snmp."); - break; - } - - words = procfile_linewords(ff, l); - if(words < 2) { - error("Cannot read /proc/net/snmp IcmpMsg line. Expected 2+ 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 == CONFIG_BOOLEAN_YES || (do_icmpmsg == CONFIG_BOOLEAN_AUTO && - (snmp_root.icmpmsg_InEchoReps || - snmp_root.icmpmsg_OutEchoReps || - snmp_root.icmpmsg_InDestUnreachs || - snmp_root.icmpmsg_OutDestUnreachs || - snmp_root.icmpmsg_InRedirects || - snmp_root.icmpmsg_OutRedirects || - snmp_root.icmpmsg_InEchos || - snmp_root.icmpmsg_OutEchos || - snmp_root.icmpmsg_InRouterAdvert || - snmp_root.icmpmsg_OutRouterAdvert || - snmp_root.icmpmsg_InRouterSelect || - snmp_root.icmpmsg_OutRouterSelect || - snmp_root.icmpmsg_InTimeExcds || - snmp_root.icmpmsg_OutTimeExcds || - snmp_root.icmpmsg_InParmProbs || - snmp_root.icmpmsg_OutParmProbs || - snmp_root.icmpmsg_InTimestamps || - snmp_root.icmpmsg_OutTimestamps || - snmp_root.icmpmsg_InTimestampReps || - snmp_root.icmpmsg_OutTimestampReps || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmpmsg = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_ICMP + 2 - , update_every - , RRDSET_TYPE_LINE - ); - - 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); - - 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); - } - } - else if(unlikely(hash == hash_tcp && strcmp(key, "Tcp") == 0)) { - size_t h = l++; - - if(strcmp(procfile_lineword(ff, l, 0), "Tcp") != 0) { - error("Cannot read Tcp line from /proc/net/snmp."); - break; - } - - words = procfile_linewords(ff, l); - if(words < 3) { - error("Cannot read /proc/net/snmp Tcp line. Expected 3+ params, read %zu.", words); - continue; - } - - 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; - } - - // -------------------------------------------------------------------- - - // this is smart enough to update it, only when it is changed - rrdvar_custom_host_variable_set(localhost, tcp_max_connections_var, snmp_root.tcp_MaxConn); - - // -------------------------------------------------------------------- - - // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html - if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && - (snmp_root.tcp_CurrEstab || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcp_sockets = CONFIG_BOOLEAN_YES; - - static RRDSET *st = NULL; - static RRDDIM *rd_CurrEstab = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP - , "tcpsock" - , NULL - , "tcp" - , NULL - , "IPv4 TCP Connections" - , "active connections" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_TCP - , update_every - , RRDSET_TYPE_LINE - ); - - rd_CurrEstab = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); - } - else rrdset_next(st); - - rrddim_set_by_pointer(st, rd_CurrEstab, (collected_number)snmp_root.tcp_CurrEstab); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_tcp_packets == CONFIG_BOOLEAN_YES || (do_tcp_packets == CONFIG_BOOLEAN_AUTO && - (snmp_root.tcp_InSegs || - snmp_root.tcp_OutSegs || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcp_packets = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_TCP + 4 - , update_every - , RRDSET_TYPE_LINE - ); - - 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_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 == CONFIG_BOOLEAN_YES || (do_tcp_errors == CONFIG_BOOLEAN_AUTO && - (snmp_root.tcp_InErrs || - snmp_root.tcp_InCsumErrors || - snmp_root.tcp_RetransSegs || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcp_errors = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_TCP + 20 - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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_opens == CONFIG_BOOLEAN_YES || (do_tcp_opens == CONFIG_BOOLEAN_AUTO && - (snmp_root.tcp_ActiveOpens || - snmp_root.tcp_PassiveOpens || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcp_opens = CONFIG_BOOLEAN_YES; - - static RRDSET *st = NULL; - static RRDDIM *rd_ActiveOpens = NULL, - *rd_PassiveOpens = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP - , "tcpopens" - , NULL - , "tcp" - , NULL - , "IPv4 TCP Opens" - , "connections/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_TCP + 5 - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - rd_ActiveOpens = rrddim_add(st, "ActiveOpens", "active", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_PassiveOpens = rrddim_add(st, "PassiveOpens", "passive", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else rrdset_next(st); - - 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); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_tcp_handshake == CONFIG_BOOLEAN_YES || (do_tcp_handshake == CONFIG_BOOLEAN_AUTO && - (snmp_root.tcp_EstabResets || - snmp_root.tcp_OutRsts || - snmp_root.tcp_AttemptFails || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_tcp_handshake = CONFIG_BOOLEAN_YES; - - static RRDSET *st = NULL; - static RRDDIM *rd_EstabResets = NULL, - *rd_OutRsts = NULL, - *rd_AttemptFails = NULL, - *rd_TCPSynRetrans = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP - , "tcphandshake" - , NULL - , "tcp" - , NULL - , "IPv4 TCP Handshake Issues" - , "events/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_TCP + 30 - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_AttemptFails = rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_TCPSynRetrans = rrddim_add(st, "TCPSynRetrans", "SynRetrans", 1, 1, RRD_ALGORITHM_INCREMENTAL); - } - else rrdset_next(st); - - 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_AttemptFails, (collected_number)snmp_root.tcp_AttemptFails); - rrddim_set_by_pointer(st, rd_TCPSynRetrans, tcpext_TCPSynRetrans); - rrdset_done(st); - } - } - else if(unlikely(hash == hash_udp && strcmp(key, "Udp") == 0)) { - size_t h = l++; - - if(strcmp(procfile_lineword(ff, l, 0), "Udp") != 0) { - error("Cannot read Udp line from /proc/net/snmp."); - break; - } - - words = procfile_linewords(ff, l); - if(words < 3) { - error("Cannot read /proc/net/snmp Udp line. Expected 3+ params, read %zu.", words); - continue; - } - - 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 == CONFIG_BOOLEAN_YES || (do_udp_packets == CONFIG_BOOLEAN_AUTO && - (snmp_root.udp_InDatagrams || - snmp_root.udp_OutDatagrams || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_udp_packets = CONFIG_BOOLEAN_YES; - - static RRDSET *st = NULL; - static RRDDIM *rd_InDatagrams = NULL, - *rd_OutDatagrams = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP - , "udppackets" - , NULL - , "udp" - , NULL - , "IPv4 UDP Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_UDP - , 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.udp_InDatagrams); - rrddim_set_by_pointer(st, rd_OutDatagrams, (collected_number)snmp_root.udp_OutDatagrams); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_udp_errors == CONFIG_BOOLEAN_YES || (do_udp_errors == CONFIG_BOOLEAN_AUTO && - (snmp_root.udp_InErrors || - snmp_root.udp_NoPorts || - snmp_root.udp_RcvbufErrors || - snmp_root.udp_SndbufErrors || - snmp_root.udp_InCsumErrors || - snmp_root.udp_IgnoredMulti || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_udp_errors = CONFIG_BOOLEAN_YES; - - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_UDP + 10 - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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); - } - } - else if(unlikely(hash == hash_udplite && strcmp(key, "UdpLite") == 0)) { - size_t h = l++; - - if(strcmp(procfile_lineword(ff, l, 0), "UdpLite") != 0) { - error("Cannot read UdpLite line from /proc/net/snmp."); - break; - } - - words = procfile_linewords(ff, l); - if(words < 3) { - error("Cannot read /proc/net/snmp UdpLite line. Expected 3+ params, read %zu.", words); - continue; - } - - 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 == CONFIG_BOOLEAN_YES || (do_udplite_packets == CONFIG_BOOLEAN_AUTO && - (snmp_root.udplite_InDatagrams || - snmp_root.udplite_OutDatagrams || - snmp_root.udplite_NoPorts || - snmp_root.udplite_InErrors || - snmp_root.udplite_InCsumErrors || - snmp_root.udplite_RcvbufErrors || - snmp_root.udplite_SndbufErrors || - snmp_root.udplite_IgnoredMulti || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_udplite_packets = CONFIG_BOOLEAN_YES; - - { - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_UDPLITE - , 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); - } - - { - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP_NAME - , NETDATA_CHART_PRIO_IPV4_UDPLITE + 10 - , 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); - } - } - } - } - - return 0; -} - diff --git a/collectors/proc.plugin/proc_net_snmp6.c b/collectors/proc.plugin/proc_net_snmp6.c deleted file mode 100644 index 445e0dcab..000000000 --- a/collectors/proc.plugin/proc_net_snmp6.c +++ /dev/null @@ -1,1293 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "plugin_proc.h" - -#define RRD_TYPE_NET_SNMP6 "ipv6" -#define PLUGIN_PROC_MODULE_NET_SNMP6_NAME "/proc/net/snmp6" - -int do_proc_net_snmp6(int update_every, usec_t dt) { - (void)dt; - - static procfile *ff = NULL; - - static int do_ip_packets = -1, - do_ip_fragsout = -1, - do_ip_fragsin = -1, - do_ip_errors = -1, - do_udplite_packets = -1, - do_udplite_errors = -1, - do_udp_packets = -1, - do_udp_errors = -1, - do_bandwidth = -1, - do_mcast = -1, - do_bcast = -1, - do_mcast_p = -1, - do_icmp = -1, - do_icmp_redir = -1, - do_icmp_errors = -1, - do_icmp_echos = -1, - do_icmp_groupmemb = -1, - do_icmp_router = -1, - do_icmp_neighbor = -1, - do_icmp_mldv2 = -1, - do_icmp_types = -1, - do_ect = -1; - - static ARL_BASE *arl_base = NULL; - - static unsigned long long Ip6InReceives = 0ULL; - static unsigned long long Ip6InHdrErrors = 0ULL; - static unsigned long long Ip6InTooBigErrors = 0ULL; - static unsigned long long Ip6InNoRoutes = 0ULL; - static unsigned long long Ip6InAddrErrors = 0ULL; - static unsigned long long Ip6InUnknownProtos = 0ULL; - static unsigned long long Ip6InTruncatedPkts = 0ULL; - static unsigned long long Ip6InDiscards = 0ULL; - static unsigned long long Ip6InDelivers = 0ULL; - static unsigned long long Ip6OutForwDatagrams = 0ULL; - static unsigned long long Ip6OutRequests = 0ULL; - static unsigned long long Ip6OutDiscards = 0ULL; - static unsigned long long Ip6OutNoRoutes = 0ULL; - static unsigned long long Ip6ReasmTimeout = 0ULL; - static unsigned long long Ip6ReasmReqds = 0ULL; - static unsigned long long Ip6ReasmOKs = 0ULL; - static unsigned long long Ip6ReasmFails = 0ULL; - static unsigned long long Ip6FragOKs = 0ULL; - static unsigned long long Ip6FragFails = 0ULL; - static unsigned long long Ip6FragCreates = 0ULL; - static unsigned long long Ip6InMcastPkts = 0ULL; - static unsigned long long Ip6OutMcastPkts = 0ULL; - static unsigned long long Ip6InOctets = 0ULL; - static unsigned long long Ip6OutOctets = 0ULL; - static unsigned long long Ip6InMcastOctets = 0ULL; - static unsigned long long Ip6OutMcastOctets = 0ULL; - static unsigned long long Ip6InBcastOctets = 0ULL; - static unsigned long long Ip6OutBcastOctets = 0ULL; - static unsigned long long Ip6InNoECTPkts = 0ULL; - static unsigned long long Ip6InECT1Pkts = 0ULL; - static unsigned long long Ip6InECT0Pkts = 0ULL; - static unsigned long long Ip6InCEPkts = 0ULL; - static unsigned long long Icmp6InMsgs = 0ULL; - static unsigned long long Icmp6InErrors = 0ULL; - static unsigned long long Icmp6OutMsgs = 0ULL; - static unsigned long long Icmp6OutErrors = 0ULL; - static unsigned long long Icmp6InCsumErrors = 0ULL; - static unsigned long long Icmp6InDestUnreachs = 0ULL; - static unsigned long long Icmp6InPktTooBigs = 0ULL; - static unsigned long long Icmp6InTimeExcds = 0ULL; - static unsigned long long Icmp6InParmProblems = 0ULL; - static unsigned long long Icmp6InEchos = 0ULL; - static unsigned long long Icmp6InEchoReplies = 0ULL; - static unsigned long long Icmp6InGroupMembQueries = 0ULL; - static unsigned long long Icmp6InGroupMembResponses = 0ULL; - static unsigned long long Icmp6InGroupMembReductions = 0ULL; - static unsigned long long Icmp6InRouterSolicits = 0ULL; - static unsigned long long Icmp6InRouterAdvertisements = 0ULL; - static unsigned long long Icmp6InNeighborSolicits = 0ULL; - static unsigned long long Icmp6InNeighborAdvertisements = 0ULL; - static unsigned long long Icmp6InRedirects = 0ULL; - static unsigned long long Icmp6InMLDv2Reports = 0ULL; - static unsigned long long Icmp6OutDestUnreachs = 0ULL; - static unsigned long long Icmp6OutPktTooBigs = 0ULL; - static unsigned long long Icmp6OutTimeExcds = 0ULL; - static unsigned long long Icmp6OutParmProblems = 0ULL; - static unsigned long long Icmp6OutEchos = 0ULL; - static unsigned long long Icmp6OutEchoReplies = 0ULL; - static unsigned long long Icmp6OutGroupMembQueries = 0ULL; - static unsigned long long Icmp6OutGroupMembResponses = 0ULL; - static unsigned long long Icmp6OutGroupMembReductions = 0ULL; - static unsigned long long Icmp6OutRouterSolicits = 0ULL; - static unsigned long long Icmp6OutRouterAdvertisements = 0ULL; - static unsigned long long Icmp6OutNeighborSolicits = 0ULL; - static unsigned long long Icmp6OutNeighborAdvertisements = 0ULL; - static unsigned long long Icmp6OutRedirects = 0ULL; - static unsigned long long Icmp6OutMLDv2Reports = 0ULL; - static unsigned long long Icmp6InType1 = 0ULL; - static unsigned long long Icmp6InType128 = 0ULL; - static unsigned long long Icmp6InType129 = 0ULL; - static unsigned long long Icmp6InType136 = 0ULL; - static unsigned long long Icmp6OutType1 = 0ULL; - static unsigned long long Icmp6OutType128 = 0ULL; - static unsigned long long Icmp6OutType129 = 0ULL; - static unsigned long long Icmp6OutType133 = 0ULL; - static unsigned long long Icmp6OutType135 = 0ULL; - static unsigned long long Icmp6OutType143 = 0ULL; - static unsigned long long Udp6InDatagrams = 0ULL; - static unsigned long long Udp6NoPorts = 0ULL; - static unsigned long long Udp6InErrors = 0ULL; - static unsigned long long Udp6OutDatagrams = 0ULL; - static unsigned long long Udp6RcvbufErrors = 0ULL; - static unsigned long long Udp6SndbufErrors = 0ULL; - static unsigned long long Udp6InCsumErrors = 0ULL; - static unsigned long long Udp6IgnoredMulti = 0ULL; - static unsigned long long UdpLite6InDatagrams = 0ULL; - static unsigned long long UdpLite6NoPorts = 0ULL; - static unsigned long long UdpLite6InErrors = 0ULL; - static unsigned long long UdpLite6OutDatagrams = 0ULL; - static unsigned long long UdpLite6RcvbufErrors = 0ULL; - static unsigned long long UdpLite6SndbufErrors = 0ULL; - static unsigned long long UdpLite6InCsumErrors = 0ULL; - - if(unlikely(!arl_base)) { - do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_BOOLEAN_AUTO); - do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO); - do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_BOOLEAN_AUTO); - do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_BOOLEAN_AUTO); - do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_BOOLEAN_AUTO); - do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_BOOLEAN_AUTO); - do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_BOOLEAN_AUTO); - do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_BOOLEAN_AUTO); - do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_BOOLEAN_AUTO); - do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_BOOLEAN_AUTO); - do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO); - do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_BOOLEAN_AUTO); - do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_BOOLEAN_AUTO); - do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_BOOLEAN_AUTO); - do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_BOOLEAN_AUTO); - do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_BOOLEAN_AUTO); - do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_BOOLEAN_AUTO); - do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_BOOLEAN_AUTO); - do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_BOOLEAN_AUTO); - do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_BOOLEAN_AUTO); - do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_BOOLEAN_AUTO); - do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_BOOLEAN_AUTO); - - arl_base = arl_create("snmp6", NULL, 60); - arl_expect(arl_base, "Ip6InReceives", &Ip6InReceives); - arl_expect(arl_base, "Ip6InHdrErrors", &Ip6InHdrErrors); - arl_expect(arl_base, "Ip6InTooBigErrors", &Ip6InTooBigErrors); - arl_expect(arl_base, "Ip6InNoRoutes", &Ip6InNoRoutes); - arl_expect(arl_base, "Ip6InAddrErrors", &Ip6InAddrErrors); - arl_expect(arl_base, "Ip6InUnknownProtos", &Ip6InUnknownProtos); - arl_expect(arl_base, "Ip6InTruncatedPkts", &Ip6InTruncatedPkts); - arl_expect(arl_base, "Ip6InDiscards", &Ip6InDiscards); - arl_expect(arl_base, "Ip6InDelivers", &Ip6InDelivers); - arl_expect(arl_base, "Ip6OutForwDatagrams", &Ip6OutForwDatagrams); - arl_expect(arl_base, "Ip6OutRequests", &Ip6OutRequests); - arl_expect(arl_base, "Ip6OutDiscards", &Ip6OutDiscards); - arl_expect(arl_base, "Ip6OutNoRoutes", &Ip6OutNoRoutes); - arl_expect(arl_base, "Ip6ReasmTimeout", &Ip6ReasmTimeout); - arl_expect(arl_base, "Ip6ReasmReqds", &Ip6ReasmReqds); - arl_expect(arl_base, "Ip6ReasmOKs", &Ip6ReasmOKs); - arl_expect(arl_base, "Ip6ReasmFails", &Ip6ReasmFails); - arl_expect(arl_base, "Ip6FragOKs", &Ip6FragOKs); - arl_expect(arl_base, "Ip6FragFails", &Ip6FragFails); - arl_expect(arl_base, "Ip6FragCreates", &Ip6FragCreates); - arl_expect(arl_base, "Ip6InMcastPkts", &Ip6InMcastPkts); - arl_expect(arl_base, "Ip6OutMcastPkts", &Ip6OutMcastPkts); - arl_expect(arl_base, "Ip6InOctets", &Ip6InOctets); - arl_expect(arl_base, "Ip6OutOctets", &Ip6OutOctets); - arl_expect(arl_base, "Ip6InMcastOctets", &Ip6InMcastOctets); - arl_expect(arl_base, "Ip6OutMcastOctets", &Ip6OutMcastOctets); - arl_expect(arl_base, "Ip6InBcastOctets", &Ip6InBcastOctets); - arl_expect(arl_base, "Ip6OutBcastOctets", &Ip6OutBcastOctets); - arl_expect(arl_base, "Ip6InNoECTPkts", &Ip6InNoECTPkts); - arl_expect(arl_base, "Ip6InECT1Pkts", &Ip6InECT1Pkts); - arl_expect(arl_base, "Ip6InECT0Pkts", &Ip6InECT0Pkts); - arl_expect(arl_base, "Ip6InCEPkts", &Ip6InCEPkts); - arl_expect(arl_base, "Icmp6InMsgs", &Icmp6InMsgs); - arl_expect(arl_base, "Icmp6InErrors", &Icmp6InErrors); - arl_expect(arl_base, "Icmp6OutMsgs", &Icmp6OutMsgs); - arl_expect(arl_base, "Icmp6OutErrors", &Icmp6OutErrors); - arl_expect(arl_base, "Icmp6InCsumErrors", &Icmp6InCsumErrors); - arl_expect(arl_base, "Icmp6InDestUnreachs", &Icmp6InDestUnreachs); - arl_expect(arl_base, "Icmp6InPktTooBigs", &Icmp6InPktTooBigs); - arl_expect(arl_base, "Icmp6InTimeExcds", &Icmp6InTimeExcds); - arl_expect(arl_base, "Icmp6InParmProblems", &Icmp6InParmProblems); - arl_expect(arl_base, "Icmp6InEchos", &Icmp6InEchos); - arl_expect(arl_base, "Icmp6InEchoReplies", &Icmp6InEchoReplies); - arl_expect(arl_base, "Icmp6InGroupMembQueries", &Icmp6InGroupMembQueries); - arl_expect(arl_base, "Icmp6InGroupMembResponses", &Icmp6InGroupMembResponses); - arl_expect(arl_base, "Icmp6InGroupMembReductions", &Icmp6InGroupMembReductions); - arl_expect(arl_base, "Icmp6InRouterSolicits", &Icmp6InRouterSolicits); - arl_expect(arl_base, "Icmp6InRouterAdvertisements", &Icmp6InRouterAdvertisements); - arl_expect(arl_base, "Icmp6InNeighborSolicits", &Icmp6InNeighborSolicits); - arl_expect(arl_base, "Icmp6InNeighborAdvertisements", &Icmp6InNeighborAdvertisements); - arl_expect(arl_base, "Icmp6InRedirects", &Icmp6InRedirects); - arl_expect(arl_base, "Icmp6InMLDv2Reports", &Icmp6InMLDv2Reports); - arl_expect(arl_base, "Icmp6OutDestUnreachs", &Icmp6OutDestUnreachs); - arl_expect(arl_base, "Icmp6OutPktTooBigs", &Icmp6OutPktTooBigs); - arl_expect(arl_base, "Icmp6OutTimeExcds", &Icmp6OutTimeExcds); - arl_expect(arl_base, "Icmp6OutParmProblems", &Icmp6OutParmProblems); - arl_expect(arl_base, "Icmp6OutEchos", &Icmp6OutEchos); - arl_expect(arl_base, "Icmp6OutEchoReplies", &Icmp6OutEchoReplies); - arl_expect(arl_base, "Icmp6OutGroupMembQueries", &Icmp6OutGroupMembQueries); - arl_expect(arl_base, "Icmp6OutGroupMembResponses", &Icmp6OutGroupMembResponses); - arl_expect(arl_base, "Icmp6OutGroupMembReductions", &Icmp6OutGroupMembReductions); - arl_expect(arl_base, "Icmp6OutRouterSolicits", &Icmp6OutRouterSolicits); - arl_expect(arl_base, "Icmp6OutRouterAdvertisements", &Icmp6OutRouterAdvertisements); - arl_expect(arl_base, "Icmp6OutNeighborSolicits", &Icmp6OutNeighborSolicits); - arl_expect(arl_base, "Icmp6OutNeighborAdvertisements", &Icmp6OutNeighborAdvertisements); - arl_expect(arl_base, "Icmp6OutRedirects", &Icmp6OutRedirects); - arl_expect(arl_base, "Icmp6OutMLDv2Reports", &Icmp6OutMLDv2Reports); - arl_expect(arl_base, "Icmp6InType1", &Icmp6InType1); - arl_expect(arl_base, "Icmp6InType128", &Icmp6InType128); - arl_expect(arl_base, "Icmp6InType129", &Icmp6InType129); - arl_expect(arl_base, "Icmp6InType136", &Icmp6InType136); - arl_expect(arl_base, "Icmp6OutType1", &Icmp6OutType1); - arl_expect(arl_base, "Icmp6OutType128", &Icmp6OutType128); - arl_expect(arl_base, "Icmp6OutType129", &Icmp6OutType129); - arl_expect(arl_base, "Icmp6OutType133", &Icmp6OutType133); - arl_expect(arl_base, "Icmp6OutType135", &Icmp6OutType135); - arl_expect(arl_base, "Icmp6OutType143", &Icmp6OutType143); - arl_expect(arl_base, "Udp6InDatagrams", &Udp6InDatagrams); - arl_expect(arl_base, "Udp6NoPorts", &Udp6NoPorts); - arl_expect(arl_base, "Udp6InErrors", &Udp6InErrors); - arl_expect(arl_base, "Udp6OutDatagrams", &Udp6OutDatagrams); - arl_expect(arl_base, "Udp6RcvbufErrors", &Udp6RcvbufErrors); - arl_expect(arl_base, "Udp6SndbufErrors", &Udp6SndbufErrors); - arl_expect(arl_base, "Udp6InCsumErrors", &Udp6InCsumErrors); - arl_expect(arl_base, "Udp6IgnoredMulti", &Udp6IgnoredMulti); - arl_expect(arl_base, "UdpLite6InDatagrams", &UdpLite6InDatagrams); - arl_expect(arl_base, "UdpLite6NoPorts", &UdpLite6NoPorts); - arl_expect(arl_base, "UdpLite6InErrors", &UdpLite6InErrors); - arl_expect(arl_base, "UdpLite6OutDatagrams", &UdpLite6OutDatagrams); - arl_expect(arl_base, "UdpLite6RcvbufErrors", &UdpLite6RcvbufErrors); - arl_expect(arl_base, "UdpLite6SndbufErrors", &UdpLite6SndbufErrors); - arl_expect(arl_base, "UdpLite6InCsumErrors", &UdpLite6InCsumErrors); - } - - if(unlikely(!ff)) { - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp6"); - ff = procfile_open(config_get("plugin:proc:/proc/net/snmp6", "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; - - arl_begin(arl_base); - - for(l = 0; l < lines ;l++) { - size_t words = procfile_linewords(ff, l); - if(unlikely(words < 2)) { - if(unlikely(words)) error("Cannot read /proc/net/snmp6 line %zu. Expected 2 params, read %zu.", l, words); - continue; - } - - if(unlikely(arl_check(arl_base, - procfile_lineword(ff, l, 0), - procfile_lineword(ff, l, 1)))) break; - } - - // -------------------------------------------------------------------- - - if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && - (Ip6InOctets || - Ip6OutOctets || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_bandwidth = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_received = NULL, - *rd_sent = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - "system" - , "ipv6" - , NULL - , "network" - , NULL - , "IPv6 Bandwidth" - , "kilobits/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_SYSTEM_IPV6 - , 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_by_pointer(st, rd_received, Ip6InOctets); - rrddim_set_by_pointer(st, rd_sent, Ip6OutOctets); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_ip_packets == CONFIG_BOOLEAN_YES || (do_ip_packets == CONFIG_BOOLEAN_AUTO && - (Ip6InReceives || - Ip6OutRequests || - Ip6InDelivers || - Ip6OutForwDatagrams || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_packets = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_received = NULL, - *rd_sent = NULL, - *rd_forwarded = NULL, - *rd_delivers = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "packets" - , NULL - , "packets" - , NULL - , "IPv6 Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_PACKETS - , 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_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); - } - - // -------------------------------------------------------------------- - - if(do_ip_fragsout == CONFIG_BOOLEAN_YES || (do_ip_fragsout == CONFIG_BOOLEAN_AUTO && - (Ip6FragOKs || - Ip6FragFails || - Ip6FragCreates || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_fragsout = CONFIG_BOOLEAN_YES; - 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 - , "fragments6" - , NULL - , "IPv6 Fragments Sent" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_FRAGSOUT - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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); - } - - // -------------------------------------------------------------------- - - if(do_ip_fragsin == CONFIG_BOOLEAN_YES || (do_ip_fragsin == CONFIG_BOOLEAN_AUTO && - (Ip6ReasmOKs || - Ip6ReasmFails || - Ip6ReasmTimeout || - Ip6ReasmReqds || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_fragsin = CONFIG_BOOLEAN_YES; - - 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 - , "fragments6" - , NULL - , "IPv6 Fragments Reassembly" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_FRAGSIN - , update_every - , RRDSET_TYPE_LINE); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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); - } - - // -------------------------------------------------------------------- - - if(do_ip_errors == CONFIG_BOOLEAN_YES || (do_ip_errors == CONFIG_BOOLEAN_AUTO && - (Ip6InDiscards || - Ip6OutDiscards || - Ip6InHdrErrors || - Ip6InAddrErrors || - Ip6InUnknownProtos || - Ip6InTooBigErrors || - Ip6InTruncatedPkts || - Ip6InNoRoutes || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ip_errors = CONFIG_BOOLEAN_YES; - 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" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ERRORS - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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); - } - - // -------------------------------------------------------------------- - - if(do_udp_packets == CONFIG_BOOLEAN_YES || (do_udp_packets == CONFIG_BOOLEAN_AUTO && - (Udp6InDatagrams || - Udp6OutDatagrams || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_udp_packets = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_received = NULL, - *rd_sent = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "udppackets" - , NULL - , "udp6" - , NULL - , "IPv6 UDP Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_UDP_PACKETS - , 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_by_pointer(st, rd_received, Udp6InDatagrams); - rrddim_set_by_pointer(st, rd_sent, Udp6OutDatagrams); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_udp_errors == CONFIG_BOOLEAN_YES || (do_udp_errors == CONFIG_BOOLEAN_AUTO && - (Udp6InErrors || - Udp6NoPorts || - Udp6RcvbufErrors || - Udp6SndbufErrors || - Udp6InCsumErrors || - Udp6IgnoredMulti || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_udp_errors = CONFIG_BOOLEAN_YES; - 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 - , "udp6" - , NULL - , "IPv6 UDP Errors" - , "events/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_UDP_ERRORS - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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); - } - - // -------------------------------------------------------------------- - - if(do_udplite_packets == CONFIG_BOOLEAN_YES || (do_udplite_packets == CONFIG_BOOLEAN_AUTO && - (UdpLite6InDatagrams || - UdpLite6OutDatagrams || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_udplite_packets = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_received = NULL, - *rd_sent = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "udplitepackets" - , NULL - , "udplite6" - , NULL - , "IPv6 UDPlite Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_UDPLITE_PACKETS - , 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_by_pointer(st, rd_received, UdpLite6InDatagrams); - rrddim_set_by_pointer(st, rd_sent, UdpLite6OutDatagrams); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_udplite_errors == CONFIG_BOOLEAN_YES || (do_udplite_errors == CONFIG_BOOLEAN_AUTO && - (UdpLite6InErrors || - UdpLite6NoPorts || - UdpLite6RcvbufErrors || - UdpLite6SndbufErrors || - Udp6InCsumErrors || - UdpLite6InCsumErrors || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_udplite_errors = CONFIG_BOOLEAN_YES; - 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 - , "udplite6" - , NULL - , "IPv6 UDP Lite Errors" - , "events/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_UDPLITE_ERRORS - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_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); - } - - // -------------------------------------------------------------------- - - if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && - (Ip6OutMcastOctets || - Ip6InMcastOctets || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_mcast = CONFIG_BOOLEAN_YES; - 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 - , "multicast6" - , NULL - , "IPv6 Multicast Bandwidth" - , "kilobits/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_MCAST - , update_every - , RRDSET_TYPE_AREA - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_by_pointer(st, rd_Ip6InMcastOctets, Ip6InMcastOctets); - rrddim_set_by_pointer(st, rd_Ip6OutMcastOctets, Ip6OutMcastOctets); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && - (Ip6OutBcastOctets || - Ip6InBcastOctets || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_bcast = CONFIG_BOOLEAN_YES; - 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 - , "broadcast6" - , NULL - , "IPv6 Broadcast Bandwidth" - , "kilobits/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_BCAST - , update_every - , RRDSET_TYPE_AREA - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_by_pointer(st, rd_Ip6InBcastOctets, Ip6InBcastOctets); - rrddim_set_by_pointer(st, rd_Ip6OutBcastOctets, Ip6OutBcastOctets); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && - (Ip6OutMcastPkts || - Ip6InMcastPkts || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_mcast_p = CONFIG_BOOLEAN_YES; - 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 - , "multicast6" - , NULL - , "IPv6 Multicast Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_MCAST_PACKETS - , update_every - , RRDSET_TYPE_LINE - ); - rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - - 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_by_pointer(st, rd_Ip6InMcastPkts, Ip6InMcastPkts); - rrddim_set_by_pointer(st, rd_Ip6OutMcastPkts, Ip6OutMcastPkts); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_icmp == CONFIG_BOOLEAN_YES || (do_icmp == CONFIG_BOOLEAN_AUTO && - (Icmp6InMsgs || - Icmp6OutMsgs || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_Icmp6InMsgs = NULL, - *rd_Icmp6OutMsgs = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "icmp" - , NULL - , "icmp6" - , NULL - , "IPv6 ICMP Messages" - , "messages/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP - , 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_by_pointer(st, rd_Icmp6InMsgs, Icmp6InMsgs); - rrddim_set_by_pointer(st, rd_Icmp6OutMsgs, Icmp6OutMsgs); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_icmp_redir == CONFIG_BOOLEAN_YES || (do_icmp_redir == CONFIG_BOOLEAN_AUTO && - (Icmp6InRedirects || - Icmp6OutRedirects || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_redir = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_Icmp6InRedirects = NULL, - *rd_Icmp6OutRedirects = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "icmpredir" - , NULL - , "icmp6" - , NULL - , "IPv6 ICMP Redirects" - , "redirects/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_REDIR - , 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_by_pointer(st, rd_Icmp6InRedirects, Icmp6InRedirects); - rrddim_set_by_pointer(st, rd_Icmp6OutRedirects, Icmp6OutRedirects); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_icmp_errors == CONFIG_BOOLEAN_YES || (do_icmp_errors == CONFIG_BOOLEAN_AUTO && - (Icmp6InErrors || - Icmp6OutErrors || - Icmp6InCsumErrors || - Icmp6InDestUnreachs || - Icmp6InPktTooBigs || - Icmp6InTimeExcds || - Icmp6InParmProblems || - Icmp6OutDestUnreachs || - Icmp6OutPktTooBigs || - Icmp6OutTimeExcds || - Icmp6OutParmProblems || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_errors = CONFIG_BOOLEAN_YES; - 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 - , "icmp6" - , NULL - , "IPv6 ICMP Errors" - , "errors/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_ERRORS - , 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_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); - } - - // -------------------------------------------------------------------- - - if(do_icmp_echos == CONFIG_BOOLEAN_YES || (do_icmp_echos == CONFIG_BOOLEAN_AUTO && - (Icmp6InEchos || - Icmp6OutEchos || - Icmp6InEchoReplies || - Icmp6OutEchoReplies || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_echos = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_InEchos = NULL, - *rd_OutEchos = NULL, - *rd_InEchoReplies = NULL, - *rd_OutEchoReplies = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "icmpechos" - , NULL - , "icmp6" - , NULL - , "IPv6 ICMP Echo" - , "messages/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_ECHOS - , 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_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); - } - - // -------------------------------------------------------------------- - - if(do_icmp_groupmemb == CONFIG_BOOLEAN_YES || (do_icmp_groupmemb == CONFIG_BOOLEAN_AUTO && - (Icmp6InGroupMembQueries || - Icmp6OutGroupMembQueries || - Icmp6InGroupMembResponses || - Icmp6OutGroupMembResponses || - Icmp6InGroupMembReductions || - Icmp6OutGroupMembReductions || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_groupmemb = CONFIG_BOOLEAN_YES; - 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 - , "icmp6" - , NULL - , "IPv6 ICMP Group Membership" - , "messages/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_GROUPMEMB - , 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_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); - } - - // -------------------------------------------------------------------- - - if(do_icmp_router == CONFIG_BOOLEAN_YES || (do_icmp_router == CONFIG_BOOLEAN_AUTO && - (Icmp6InRouterSolicits || - Icmp6OutRouterSolicits || - Icmp6InRouterAdvertisements || - Icmp6OutRouterAdvertisements || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_router = CONFIG_BOOLEAN_YES; - 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 - , "icmprouter" - , NULL - , "icmp6" - , NULL - , "IPv6 Router Messages" - , "messages/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_ROUTER - , 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_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); - } - - // -------------------------------------------------------------------- - - if(do_icmp_neighbor == CONFIG_BOOLEAN_YES || (do_icmp_neighbor == CONFIG_BOOLEAN_AUTO && - (Icmp6InNeighborSolicits || - Icmp6OutNeighborSolicits || - Icmp6InNeighborAdvertisements || - Icmp6OutNeighborAdvertisements || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_neighbor = CONFIG_BOOLEAN_YES; - 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 - , "icmp6" - , NULL - , "IPv6 Neighbor Messages" - , "messages/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_NEIGHBOR - , 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_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); - } - - // -------------------------------------------------------------------- - - if(do_icmp_mldv2 == CONFIG_BOOLEAN_YES || (do_icmp_mldv2 == CONFIG_BOOLEAN_AUTO && - (Icmp6InMLDv2Reports || - Icmp6OutMLDv2Reports || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_mldv2 = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_InMLDv2Reports = NULL, - *rd_OutMLDv2Reports = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "icmpmldv2" - , NULL - , "icmp6" - , NULL - , "IPv6 ICMP MLDv2 Reports" - , "reports/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_LDV2 - , 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_by_pointer(st, rd_InMLDv2Reports, Icmp6InMLDv2Reports); - rrddim_set_by_pointer(st, rd_OutMLDv2Reports, Icmp6OutMLDv2Reports); - rrdset_done(st); - } - - // -------------------------------------------------------------------- - - if(do_icmp_types == CONFIG_BOOLEAN_YES || (do_icmp_types == CONFIG_BOOLEAN_AUTO && - (Icmp6InType1 || - Icmp6InType128 || - Icmp6InType129 || - Icmp6InType136 || - Icmp6OutType1 || - Icmp6OutType128 || - Icmp6OutType129 || - Icmp6OutType133 || - Icmp6OutType135 || - Icmp6OutType143 || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_icmp_types = CONFIG_BOOLEAN_YES; - 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 - , "icmp6" - , NULL - , "IPv6 ICMP Types" - , "messages/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ICMP_TYPES - , 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_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); - } - - // -------------------------------------------------------------------- - - if(do_ect == CONFIG_BOOLEAN_YES || (do_ect == CONFIG_BOOLEAN_AUTO && - (Ip6InNoECTPkts || - Ip6InECT1Pkts || - Ip6InECT0Pkts || - Ip6InCEPkts || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { - do_ect = CONFIG_BOOLEAN_YES; - static RRDSET *st = NULL; - static RRDDIM *rd_InNoECTPkts = NULL, - *rd_InECT1Pkts = NULL, - *rd_InECT0Pkts = NULL, - *rd_InCEPkts = NULL; - - if(unlikely(!st)) { - st = rrdset_create_localhost( - RRD_TYPE_NET_SNMP6 - , "ect" - , NULL - , "packets" - , NULL - , "IPv6 ECT Packets" - , "packets/s" - , PLUGIN_PROC_NAME - , PLUGIN_PROC_MODULE_NET_SNMP6_NAME - , NETDATA_CHART_PRIO_IPV6_ECT - , 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_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); - } - - return 0; -} - diff --git a/collectors/proc.plugin/proc_net_sockstat.c b/collectors/proc.plugin/proc_net_sockstat.c index 994cbad7b..e94b891ca 100644 --- a/collectors/proc.plugin/proc_net_sockstat.c +++ b/collectors/proc.plugin/proc_net_sockstat.c @@ -27,14 +27,14 @@ static struct proc_net_sockstat { static int read_tcp_mem(void) { static char *filename = NULL; - static RRDVAR *tcp_mem_low_threshold = NULL, + static const RRDVAR_ACQUIRED *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"); + tcp_mem_low_threshold = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_mem_low"); + tcp_mem_pressure_threshold = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_mem_pressure"); + tcp_mem_high_threshold = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_mem_high"); } if(unlikely(!filename)) { @@ -69,7 +69,7 @@ static int read_tcp_mem(void) { static kernel_uint_t read_tcp_max_orphans(void) { static char *filename = NULL; - static RRDVAR *tcp_max_orphans_var = NULL; + static const RRDVAR_ACQUIRED *tcp_max_orphans_var = NULL; if(unlikely(!filename)) { char buffer[FILENAME_MAX + 1]; @@ -81,7 +81,7 @@ static kernel_uint_t read_tcp_max_orphans(void) { 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"); + tcp_max_orphans_var = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_max_orphans"); rrdvar_custom_host_variable_set(localhost, tcp_max_orphans_var, tcp_max_orphans); return tcp_max_orphans; @@ -244,7 +244,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -287,7 +286,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -323,7 +321,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -357,7 +354,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -391,7 +387,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -425,7 +420,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -459,7 +453,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -493,7 +486,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); @@ -527,7 +519,6 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { 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); diff --git a/collectors/proc.plugin/proc_net_sockstat6.c b/collectors/proc.plugin/proc_net_sockstat6.c index ce8c9e093..065cf6055 100644 --- a/collectors/proc.plugin/proc_net_sockstat6.c +++ b/collectors/proc.plugin/proc_net_sockstat6.c @@ -137,7 +137,6 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { 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); @@ -171,7 +170,6 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { 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); @@ -205,7 +203,6 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { 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); @@ -239,7 +236,6 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { 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); @@ -273,7 +269,6 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { 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); diff --git a/collectors/proc.plugin/proc_net_softnet_stat.c b/collectors/proc.plugin/proc_net_softnet_stat.c index 1f704a427..65239246a 100644 --- a/collectors/proc.plugin/proc_net_softnet_stat.c +++ b/collectors/proc.plugin/proc_net_softnet_stat.c @@ -101,7 +101,6 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { if(unlikely(softnet_column_name(w))) rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); for(w = 0; w < allocated_columns ;w++) if(unlikely(softnet_column_name(w))) @@ -137,7 +136,6 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { if(unlikely(softnet_column_name(w))) rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); for(w = 0; w < allocated_columns ;w++) if(unlikely(softnet_column_name(w))) diff --git a/collectors/proc.plugin/proc_net_stat_conntrack.c b/collectors/proc.plugin/proc_net_stat_conntrack.c index 642e33f8e..f9dbdf47c 100644 --- a/collectors/proc.plugin/proc_net_stat_conntrack.c +++ b/collectors/proc.plugin/proc_net_stat_conntrack.c @@ -12,7 +12,7 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { static usec_t get_max_every = 10 * USEC_PER_SEC, usec_since_last_max = 0; static int read_full = 1; static char *nf_conntrack_filename, *nf_conntrack_count_filename, *nf_conntrack_max_filename; - static RRDVAR *rrdvar_max = NULL; + static const RRDVAR_ACQUIRED *rrdvar_max = NULL; unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0, ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0; @@ -50,7 +50,7 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { if(!do_sockets && !read_full) return 1; - rrdvar_max = rrdvar_custom_host_variable_create(localhost, "netfilter_conntrack_max"); + rrdvar_max = rrdvar_custom_host_variable_add_and_acquire(localhost, "netfilter_conntrack_max"); } if(likely(read_full)) { @@ -152,7 +152,6 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { rd_connections = rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd_connections, aentries); rrdset_done(st); @@ -187,7 +186,6 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { 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_by_pointer(st, rd_new, anew); rrddim_set_by_pointer(st, rd_ignore, aignore); @@ -225,7 +223,6 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { 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_by_pointer(st, rd_inserted, ainsert); rrddim_set_by_pointer(st, rd_deleted, adelete); @@ -262,7 +259,6 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { 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_by_pointer(st, rd_created, aexpect_create); rrddim_set_by_pointer(st, rd_deleted, aexpect_delete); @@ -299,7 +295,6 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { 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_by_pointer(st, rd_searched, asearched); rrddim_set_by_pointer(st, rd_restarted, asearch_restart); @@ -338,7 +333,6 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { 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_by_pointer(st, rd_icmp_error, aicmp_error); rrddim_set_by_pointer(st, rd_insert_failed, ainsert_failed); diff --git a/collectors/proc.plugin/proc_net_stat_synproxy.c b/collectors/proc.plugin/proc_net_stat_synproxy.c index c74c5374d..0a74b3575 100644 --- a/collectors/proc.plugin/proc_net_stat_synproxy.c +++ b/collectors/proc.plugin/proc_net_stat_synproxy.c @@ -80,7 +80,6 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "received", syn_received); rrdset_done(st); @@ -111,7 +110,6 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { rrddim_add(st, "reopened", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "reopened", conn_reopened); rrdset_done(st); @@ -144,7 +142,6 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "retransmits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st); rrddim_set(st, "valid", cookie_valid); rrddim_set(st, "invalid", cookie_invalid); diff --git a/collectors/proc.plugin/proc_net_wireless.c b/collectors/proc.plugin/proc_net_wireless.c index c6ee4ff70..08ab2eada 100644 --- a/collectors/proc.plugin/proc_net_wireless.c +++ b/collectors/proc.plugin/proc_net_wireless.c @@ -199,7 +199,7 @@ static void configure_device(int do_status, int do_quality, int do_discarded_pac } static void add_labels_to_wireless(struct netwireless *w, RRDSET *st) { - rrdlabels_add(st->state->chart_labels, "device", w->name, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device", w->name, RRDLABEL_SRC_AUTO); } int do_proc_net_wireless(int update_every, usec_t dt) @@ -269,8 +269,6 @@ int do_proc_net_wireless(int update_every, usec_t dt) add_labels_to_wireless(wireless_dev, wireless_dev->st_status); } - else - rrdset_next(wireless_dev->st_status); rrddim_set_by_pointer(wireless_dev->st_status, wireless_dev->rd_status, (collected_number)wireless_dev->status); @@ -302,8 +300,6 @@ int do_proc_net_wireless(int update_every, usec_t dt) add_labels_to_wireless(wireless_dev, wireless_dev->st_link); } - else - rrdset_next(wireless_dev->st_link); if (unlikely(!wireless_dev->st_level)) { wireless_dev->st_level = rrdset_create_localhost( @@ -325,8 +321,6 @@ int do_proc_net_wireless(int update_every, usec_t dt) add_labels_to_wireless(wireless_dev, wireless_dev->st_level); } - else - rrdset_next(wireless_dev->st_level); if (unlikely(!wireless_dev->st_noise)) { wireless_dev->st_noise = rrdset_create_localhost( @@ -348,8 +342,6 @@ int do_proc_net_wireless(int update_every, usec_t dt) add_labels_to_wireless(wireless_dev, wireless_dev->st_noise); } - else - rrdset_next(wireless_dev->st_noise); rrddim_set_by_pointer(wireless_dev->st_link, wireless_dev->rd_link, (collected_number)wireless_dev->link); rrdset_done(wireless_dev->st_link); @@ -393,8 +385,6 @@ int do_proc_net_wireless(int update_every, usec_t dt) add_labels_to_wireless(wireless_dev, wireless_dev->st_discarded_packets); } - else - rrdset_next(wireless_dev->st_discarded_packets); rrddim_set_by_pointer(wireless_dev->st_discarded_packets, wireless_dev->rd_nwid, (collected_number)wireless_dev->nwid); rrddim_set_by_pointer(wireless_dev->st_discarded_packets, wireless_dev->rd_crypt, (collected_number)wireless_dev->crypt); @@ -429,11 +419,8 @@ int do_proc_net_wireless(int update_every, usec_t dt) add_labels_to_wireless(wireless_dev, wireless_dev->st_missed_beacon); } - else - rrdset_next(wireless_dev->st_missed_beacon); rrddim_set_by_pointer(wireless_dev->st_missed_beacon, wireless_dev->rd_missed_beacon, (collected_number)wireless_dev->missed_beacon); - rrdset_done(wireless_dev->st_missed_beacon); } diff --git a/collectors/proc.plugin/proc_pagetypeinfo.c b/collectors/proc.plugin/proc_pagetypeinfo.c index 017edc49a..dc006aa59 100644 --- a/collectors/proc.plugin/proc_pagetypeinfo.c +++ b/collectors/proc.plugin/proc_pagetypeinfo.c @@ -79,7 +79,7 @@ int do_proc_pagetypeinfo(int update_every, usec_t dt) { static RRDSET **st_nodezonetype = NULL; // Local temp variables - size_t l, o, p; + long unsigned int l, o, p; struct pageline *pgl = NULL; // -------------------------------------------------------------------- @@ -149,7 +149,8 @@ int do_proc_pagetypeinfo(int update_every, usec_t dt) { pageorders_cnt -= 9; if (pageorders_cnt > MAX_PAGETYPE_ORDER) { - error("PLUGIN: PROC_PAGETYPEINFO: pageorder found (%lu) is higher than max %d", pageorders_cnt, MAX_PAGETYPE_ORDER); + error("PLUGIN: PROC_PAGETYPEINFO: pageorder found (%lu) is higher than max %d", + (long unsigned int) pageorders_cnt, MAX_PAGETYPE_ORDER); return 1; } @@ -157,7 +158,8 @@ int do_proc_pagetypeinfo(int update_every, usec_t dt) { if (!pagelines) { pagelines = callocz(pagelines_cnt, sizeof(struct pageline)); if (!pagelines) { - error("PLUGIN: PROC_PAGETYPEINFO: Cannot allocate %lu pagelines of %lu B", pagelines_cnt, sizeof(struct pageline)); + error("PLUGIN: PROC_PAGETYPEINFO: Cannot allocate %lu pagelines of %lu B", + (long unsigned int) pagelines_cnt, (long unsigned int) sizeof(struct pageline)); return 1; } } @@ -261,9 +263,9 @@ int do_proc_pagetypeinfo(int update_every, usec_t dt) { char node[50+1]; snprintfz(node, 50, "node%d", pgl->node); - rrdlabels_add(st_nodezonetype[p]->state->chart_labels, "node_id", node, RRDLABEL_SRC_AUTO); - rrdlabels_add(st_nodezonetype[p]->state->chart_labels, "node_zone", pgl->zone, RRDLABEL_SRC_AUTO); - rrdlabels_add(st_nodezonetype[p]->state->chart_labels, "node_type", pgl->type, RRDLABEL_SRC_AUTO); + rrdlabels_add(st_nodezonetype[p]->rrdlabels, "node_id", node, RRDLABEL_SRC_AUTO); + rrdlabels_add(st_nodezonetype[p]->rrdlabels, "node_zone", pgl->zone, RRDLABEL_SRC_AUTO); + rrdlabels_add(st_nodezonetype[p]->rrdlabels, "node_type", pgl->type, RRDLABEL_SRC_AUTO); for (o = 0; o < pageorders_cnt; o++) { char dimid[3+1]; @@ -289,7 +291,8 @@ int do_proc_pagetypeinfo(int update_every, usec_t dt) { size_t words = procfile_linewords(ff, l); if (words != 7+pageorders_cnt) { - error("PLUGIN: PROC_PAGETYPEINFO: Unable to read line %lu, %lu words found instead of %lu", l+1, words, 7+pageorders_cnt); + error("PLUGIN: PROC_PAGETYPEINFO: Unable to read line %lu, %lu words found instead of %lu", + l+1, (long unsigned int) words, (long unsigned int) 7+pageorders_cnt); break; } @@ -313,10 +316,8 @@ int do_proc_pagetypeinfo(int update_every, usec_t dt) { // Global system per order if (st_order) { - rrdset_next(st_order); - for (o = 0; o < pageorders_cnt; o++) { + for (o = 0; o < pageorders_cnt; o++) rrddim_set_by_pointer(st_order, systemorders[o].rd, systemorders[o].size); - } rrdset_done(st_order); } @@ -327,10 +328,8 @@ int do_proc_pagetypeinfo(int update_every, usec_t dt) { if (!st_nodezonetype[p]) continue; - rrdset_next(st_nodezonetype[p]); for (o = 0; o < pageorders_cnt; o++) rrddim_set_by_pointer(st_nodezonetype[p], pagelines[p].rd[o], pagelines[p].free_pages_size[o]); - rrdset_done(st_nodezonetype[p]); } } diff --git a/collectors/proc.plugin/proc_pressure.c b/collectors/proc.plugin/proc_pressure.c index 66884dbcb..6649aa630 100644 --- a/collectors/proc.plugin/proc_pressure.c +++ b/collectors/proc.plugin/proc_pressure.c @@ -91,9 +91,8 @@ static void proc_pressure_do_resource(procfile *ff, int res_idx, int some) { rrddim_add(pcs->share_time.st, some ? "some 60" : "full 60", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); pcs->share_time.rd300 = rrddim_add(pcs->share_time.st, some ? "some 300" : "full 300", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(pcs->share_time.st); } + pcs->share_time.value10 = strtod(procfile_lineword(ff, some ? 0 : 1, 2), NULL); pcs->share_time.value60 = strtod(procfile_lineword(ff, some ? 0 : 1, 4), NULL); pcs->share_time.value300 = strtod(procfile_lineword(ff, some ? 0 : 1, 6), NULL); @@ -113,9 +112,8 @@ static void proc_pressure_do_resource(procfile *ff, int res_idx, int some) { pressure_update_every, RRDSET_TYPE_LINE); pcs->total_time.rdtotal = rrddim_add(pcs->total_time.st, "time", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - } else { - rrdset_next(pcs->total_time.st); } + pcs->total_time.value_total = str2ull(procfile_lineword(ff, some ? 0 : 1, 8)) / 1000; } diff --git a/collectors/proc.plugin/proc_pressure.h b/collectors/proc.plugin/proc_pressure.h index a421cf8a4..0cb233152 100644 --- a/collectors/proc.plugin/proc_pressure.h +++ b/collectors/proc.plugin/proc_pressure.h @@ -38,6 +38,6 @@ struct pressure { } some, full; }; -extern void update_pressure_charts(struct pressure_charts *charts); +void update_pressure_charts(struct pressure_charts *charts); #endif //NETDATA_PROC_PRESSURE_H diff --git a/collectors/proc.plugin/proc_self_mountinfo.c b/collectors/proc.plugin/proc_self_mountinfo.c index 4456d5978..9310f2ffc 100644 --- a/collectors/proc.plugin/proc_self_mountinfo.c +++ b/collectors/proc.plugin/proc_self_mountinfo.c @@ -227,7 +227,8 @@ struct mountinfo *mountinfo_read(int do_statvfs) { struct mountinfo *root = NULL, *last = NULL, *mi = NULL; // create a dictionary to track uniqueness - DICTIONARY *dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED|DICTIONARY_FLAG_DONT_OVERWRITE_VALUE|DICTIONARY_FLAG_NAME_LINK_DONT_CLONE); + DICTIONARY *dict = dictionary_create( + DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_NAME_LINK_DONT_CLONE); unsigned long l, lines = procfile_lines(ff); for(l = 0; l < lines ;l++) { diff --git a/collectors/proc.plugin/proc_self_mountinfo.h b/collectors/proc.plugin/proc_self_mountinfo.h index b915550a7..4bd24d2d2 100644 --- a/collectors/proc.plugin/proc_self_mountinfo.h +++ b/collectors/proc.plugin/proc_self_mountinfo.h @@ -51,11 +51,11 @@ struct mountinfo { struct mountinfo *next; }; -extern struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor, char *device); -extern struct mountinfo *mountinfo_find_by_filesystem_mount_source(struct mountinfo *root, const char *filesystem, const char *mount_source); -extern struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *root, const char *filesystem, const char *super_options); +struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor, char *device); +struct mountinfo *mountinfo_find_by_filesystem_mount_source(struct mountinfo *root, const char *filesystem, const char *mount_source); +struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *root, const char *filesystem, const char *super_options); -extern void mountinfo_free_all(struct mountinfo *mi); -extern struct mountinfo *mountinfo_read(int do_statvfs); +void mountinfo_free_all(struct mountinfo *mi); +struct mountinfo *mountinfo_read(int do_statvfs); #endif /* NETDATA_PROC_SELF_MOUNTINFO_H */ diff --git a/collectors/proc.plugin/proc_softirqs.c b/collectors/proc.plugin/proc_softirqs.c index 7eff28c98..4c4df7668 100644 --- a/collectors/proc.plugin/proc_softirqs.c +++ b/collectors/proc.plugin/proc_softirqs.c @@ -128,7 +128,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { // -------------------------------------------------------------------- static RRDSET *st_system_softirqs = NULL; - if(unlikely(!st_system_softirqs)) + if(unlikely(!st_system_softirqs)) { st_system_softirqs = rrdset_create_localhost( "system" , "softirqs" @@ -143,8 +143,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { , update_every , RRDSET_TYPE_STACKED ); - else - rrdset_next(st_system_softirqs); + } for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); @@ -153,9 +152,9 @@ int do_proc_softirqs(int update_every, usec_t dt) { // some interrupt may have changed without changing the total number of lines // if the same number of interrupts have been added and removed between two // calls of this function. - if(unlikely(!irr->rd || strncmp(irr->name, irr->rd->name, MAX_INTERRUPT_NAME) != 0)) { + if(unlikely(!irr->rd || strncmp(irr->name, rrddim_name(irr->rd), MAX_INTERRUPT_NAME) != 0)) { irr->rd = rrddim_add(st_system_softirqs, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(st_system_softirqs, irr->rd, irr->name); + rrddim_reset_name(st_system_softirqs, irr->rd, irr->name); // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { @@ -220,10 +219,8 @@ int do_proc_softirqs(int update_every, usec_t dt) { char core[50+1]; snprintfz(core, 50, "cpu%d", c); - rrdlabels_add(core_st[c]->state->chart_labels, "cpu", core, RRDLABEL_SRC_AUTO); + rrdlabels_add(core_st[c]->rrdlabels, "cpu", core, RRDLABEL_SRC_AUTO); } - else - rrdset_next(core_st[c]); for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); @@ -231,7 +228,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { if(irr->used && (do_per_core == CONFIG_BOOLEAN_YES || irr->cpu[c].value)) { if(unlikely(!irr->cpu[c].rd)) { irr->cpu[c].rd = rrddim_add(core_st[c], irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(core_st[c], irr->cpu[c].rd, irr->name); + rrddim_reset_name(core_st[c], irr->cpu[c].rd, irr->name); } rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value); diff --git a/collectors/proc.plugin/proc_spl_kstat_zfs.c b/collectors/proc.plugin/proc_spl_kstat_zfs.c index fae112249..8938d6431 100644 --- a/collectors/proc.plugin/proc_spl_kstat_zfs.c +++ b/collectors/proc.plugin/proc_spl_kstat_zfs.c @@ -252,8 +252,8 @@ void disable_zfs_pool_state(struct zfs_pool *pool) pool->disabled = 1; } -int update_zfs_pool_state_chart(const char *name, void *pool_p, void *update_every_p) -{ +int update_zfs_pool_state_chart(const DICTIONARY_ITEM *item, void *pool_p, void *update_every_p) { + const char *name = dictionary_acquired_item_name(item); struct zfs_pool *pool = (struct zfs_pool *)pool_p; int update_every = *(int *)update_every_p; @@ -285,8 +285,7 @@ int update_zfs_pool_state_chart(const char *name, void *pool_p, void *update_eve pool->rd_offline = rrddim_add(pool->st, "offline", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); pool->rd_removed = rrddim_add(pool->st, "removed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); pool->rd_unavail = rrddim_add(pool->st, "unavail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else - rrdset_next(pool->st); + } rrddim_set_by_pointer(pool->st, pool->rd_online, pool->online); rrddim_set_by_pointer(pool->st, pool->rd_degraded, pool->degraded); @@ -321,7 +320,7 @@ int do_proc_spl_kstat_zfs_pool_state(int update_every, usec_t dt) snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/spl/kstat/zfs"); dirname = config_get("plugin:proc:" ZFS_PROC_POOLS, "directory to monitor", filename); - zfs_pools = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + zfs_pools = dictionary_create(DICT_OPTION_SINGLE_THREADED); do_zfs_pool_state = 1; } diff --git a/collectors/proc.plugin/proc_stat.c b/collectors/proc.plugin/proc_stat.c index 6faba55a9..33fe93234 100644 --- a/collectors/proc.plugin/proc_stat.c +++ b/collectors/proc.plugin/proc_stat.c @@ -481,7 +481,7 @@ int do_proc_stat(int update_every, usec_t dt) { static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked; static char *core_throttle_count_filename = NULL, *package_throttle_count_filename = NULL, *scaling_cur_freq_filename = NULL, *time_in_state_filename = NULL, *schedstat_filename = NULL, *cpuidle_name_filename = NULL, *cpuidle_time_filename = NULL; - static RRDVAR *cpus_var = NULL; + static const RRDVAR_ACQUIRED *cpus_var = NULL; static int accurate_freq_avail = 0, accurate_freq_is_used = 0; size_t cores_found = (size_t)processors; @@ -713,9 +713,8 @@ int do_proc_stat(int update_every, usec_t dt) { rrddim_hide(cpu_chart->st, "idle"); if(unlikely(core == 0 && cpus_var == NULL)) - cpus_var = rrdvar_custom_host_variable_create(localhost, "active_processors"); + cpus_var = rrdvar_custom_host_variable_add_and_acquire(localhost, "active_processors"); } - else rrdset_next(cpu_chart->st); rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_user, user); rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_nice, nice); @@ -756,7 +755,6 @@ int do_proc_stat(int update_every, usec_t dt) { rd_interrupts = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st_intr); rrddim_set_by_pointer(st_intr, rd_interrupts, value); rrdset_done(st_intr); @@ -786,7 +784,6 @@ int do_proc_stat(int update_every, usec_t dt) { rd_switches = rrddim_add(st_ctxt, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st_ctxt); rrddim_set_by_pointer(st_ctxt, rd_switches, value); rrdset_done(st_ctxt); @@ -828,7 +825,6 @@ int do_proc_stat(int update_every, usec_t dt) { rd_started = rrddim_add(st_forks, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st_forks); rrddim_set_by_pointer(st_forks, rd_started, processes); rrdset_done(st_forks); @@ -860,7 +856,6 @@ int do_proc_stat(int update_every, usec_t dt) { rd_running = rrddim_add(st_processes, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rd_blocked = rrddim_add(st_processes, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st_processes); rrddim_set_by_pointer(st_processes, rd_running, running); rrddim_set_by_pointer(st_processes, rd_blocked, blocked); @@ -875,7 +870,7 @@ int do_proc_stat(int update_every, usec_t dt) { static RRDSET *st_core_throttle_count = NULL; - if (unlikely(!st_core_throttle_count)) + if (unlikely(!st_core_throttle_count)) { st_core_throttle_count = rrdset_create_localhost( "cpu" , "core_throttling" @@ -890,8 +885,7 @@ int do_proc_stat(int update_every, usec_t dt) { , update_every , RRDSET_TYPE_LINE ); - else - rrdset_next(st_core_throttle_count); + } chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CORE_THROTTLE_COUNT_INDEX, st_core_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrdset_done(st_core_throttle_count); @@ -905,7 +899,7 @@ int do_proc_stat(int update_every, usec_t dt) { static RRDSET *st_package_throttle_count = NULL; - if(unlikely(!st_package_throttle_count)) + if(unlikely(!st_package_throttle_count)) { st_package_throttle_count = rrdset_create_localhost( "cpu" , "package_throttling" @@ -920,8 +914,7 @@ int do_proc_stat(int update_every, usec_t dt) { , update_every , RRDSET_TYPE_LINE ); - else - rrdset_next(st_package_throttle_count); + } chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, PACKAGE_THROTTLE_COUNT_INDEX, st_package_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrdset_done(st_package_throttle_count); @@ -954,7 +947,7 @@ int do_proc_stat(int update_every, usec_t dt) { static RRDSET *st_scaling_cur_freq = NULL; - if(unlikely(!st_scaling_cur_freq)) + if(unlikely(!st_scaling_cur_freq)) { st_scaling_cur_freq = rrdset_create_localhost( "cpu" , "cpufreq" @@ -969,8 +962,7 @@ int do_proc_stat(int update_every, usec_t dt) { , update_every , RRDSET_TYPE_LINE ); - else - rrdset_next(st_scaling_cur_freq); + } chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CPU_FREQ_INDEX, st_scaling_cur_freq, 1, 1000, RRD_ALGORITHM_ABSOLUTE); rrdset_done(st_scaling_cur_freq); @@ -1041,7 +1033,7 @@ int do_proc_stat(int update_every, usec_t dt) { char corebuf[50+1]; snprintfz(corebuf, 50, "cpu%zu", core); - rrdlabels_add(cpuidle_charts[core].st->state->chart_labels, "cpu", corebuf, RRDLABEL_SRC_AUTO); + rrdlabels_add(cpuidle_charts[core].st->rrdlabels, "cpu", corebuf, RRDLABEL_SRC_AUTO); char cpuidle_dim_id[RRD_ID_LENGTH_MAX + 1]; cpuidle_charts[core].active_time_rd = rrddim_add(cpuidle_charts[core].st, "active", "C0 (active)", 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); @@ -1054,8 +1046,6 @@ int do_proc_stat(int update_every, usec_t dt) { 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } } - else - rrdset_next(cpuidle_charts[core].st); rrddim_set_by_pointer(cpuidle_charts[core].st, cpuidle_charts[core].active_time_rd, cpuidle_charts[core].active_time); for(state = 0; state < cpuidle_charts[core].cpuidle_state_len; state++) { diff --git a/collectors/proc.plugin/proc_sys_kernel_random_entropy_avail.c b/collectors/proc.plugin/proc_sys_kernel_random_entropy_avail.c index 20d2116ce..a04d43039 100644 --- a/collectors/proc.plugin/proc_sys_kernel_random_entropy_avail.c +++ b/collectors/proc.plugin/proc_sys_kernel_random_entropy_avail.c @@ -40,10 +40,8 @@ int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) { rd = rrddim_add(st, "entropy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else rrdset_next(st); rrddim_set_by_pointer(st, rd, entropy); rrdset_done(st); - return 0; } diff --git a/collectors/proc.plugin/proc_uptime.c b/collectors/proc.plugin/proc_uptime.c index 28b00e0da..ddab7269b 100644 --- a/collectors/proc.plugin/proc_uptime.c +++ b/collectors/proc.plugin/proc_uptime.c @@ -35,12 +35,8 @@ int do_proc_uptime(int update_every, usec_t dt) { rd = rrddim_add(st, "uptime", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st); rrddim_set_by_pointer(st, rd, uptime_msec(uptime_filename)); - rrdset_done(st); - return 0; } diff --git a/collectors/proc.plugin/proc_vmstat.c b/collectors/proc.plugin/proc_vmstat.c index c1a137161..b8defc455 100644 --- a/collectors/proc.plugin/proc_vmstat.c +++ b/collectors/proc.plugin/proc_vmstat.c @@ -138,7 +138,6 @@ int do_proc_vmstat(int update_every, usec_t dt) { rd_in = rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st_swapio); rrddim_set_by_pointer(st_swapio, rd_in, pswpin); rrddim_set_by_pointer(st_swapio, rd_out, pswpout); @@ -170,7 +169,6 @@ int do_proc_vmstat(int update_every, usec_t dt) { 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, pgpgin); rrddim_set_by_pointer(st_io, rd_out, pgpgout); @@ -204,7 +202,6 @@ int do_proc_vmstat(int update_every, usec_t dt) { rd_minor = rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_major = rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st_pgfaults); rrddim_set_by_pointer(st_pgfaults, rd_minor, pgfault); rrddim_set_by_pointer(st_pgfaults, rd_major, pgmajfault); @@ -240,7 +237,6 @@ int do_proc_vmstat(int update_every, usec_t dt) { rd_oom_kill = rrddim_add(st_oom_kill, "kills", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st_oom_kill); rrddim_set_by_pointer(st_oom_kill, rd_oom_kill, oom_kill); rrdset_done(st_oom_kill); @@ -295,7 +291,6 @@ int do_proc_vmstat(int update_every, usec_t dt) { rd_hint_faults_local = rrddim_add(st_numa, "hint_faults_local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_pages_migrated = rrddim_add(st_numa, "pages_migrated", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(st_numa); rrddim_set_by_pointer(st_numa, rd_local, numa_local); rrddim_set_by_pointer(st_numa, rd_foreign, numa_foreign); diff --git a/collectors/proc.plugin/sys_block_zram.c b/collectors/proc.plugin/sys_block_zram.c index ddd1e7ae0..6bae54243 100644 --- a/collectors/proc.plugin/sys_block_zram.c +++ b/collectors/proc.plugin/sys_block_zram.c @@ -33,8 +33,6 @@ typedef struct zram_device { RRDDIM *rd_alloc_efficiency; } ZRAM_DEVICE; - // -------------------------------------------------------------------- - static int try_get_zram_major_number(procfile *file) { size_t i; unsigned int lines = procfile_lines(file); @@ -75,7 +73,7 @@ static inline void init_rrd(const char *name, ZRAM_DEVICE *d, int update_every) , RRDSET_TYPE_AREA); d->rd_compr_data_size = rrddim_add(d->st_usage, "compressed", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); d->rd_metadata_size = rrddim_add(d->st_usage, "metadata", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); - rrdlabels_add(d->st_usage->state->chart_labels, "device", name, RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_usage->rrdlabels, "device", name, RRDLABEL_SRC_AUTO); snprintfz(chart_name, RRD_ID_LENGTH_MAX, "zram_savings.%s", name); d->st_savings = rrdset_create_localhost( @@ -93,7 +91,7 @@ static inline void init_rrd(const char *name, ZRAM_DEVICE *d, int update_every) , RRDSET_TYPE_AREA); d->rd_savings_size = rrddim_add(d->st_savings, "savings", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); d->rd_original_size = rrddim_add(d->st_savings, "original", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); - rrdlabels_add(d->st_savings->state->chart_labels, "device", name, RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_savings->rrdlabels, "device", name, RRDLABEL_SRC_AUTO); snprintfz(chart_name, RRD_ID_LENGTH_MAX, "zram_ratio.%s", name); d->st_comp_ratio = rrdset_create_localhost( @@ -110,7 +108,7 @@ static inline void init_rrd(const char *name, ZRAM_DEVICE *d, int update_every) , update_every , RRDSET_TYPE_LINE); d->rd_comp_ratio = rrddim_add(d->st_comp_ratio, "ratio", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); - rrdlabels_add(d->st_comp_ratio->state->chart_labels, "device", name, RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_comp_ratio->rrdlabels, "device", name, RRDLABEL_SRC_AUTO); snprintfz(chart_name, RRD_ID_LENGTH_MAX, "zram_efficiency.%s", name); d->st_alloc_efficiency = rrdset_create_localhost( @@ -127,7 +125,7 @@ static inline void init_rrd(const char *name, ZRAM_DEVICE *d, int update_every) , update_every , RRDSET_TYPE_LINE); d->rd_alloc_efficiency = rrddim_add(d->st_alloc_efficiency, "percent", NULL, 1, 10000, RRD_ALGORITHM_ABSOLUTE); - rrdlabels_add(d->st_alloc_efficiency->state->chart_labels, "device", name, RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_alloc_efficiency->rrdlabels, "device", name, RRDLABEL_SRC_AUTO); } static int init_devices(DICTIONARY *devices, unsigned int zram_id, int update_every) { @@ -177,9 +175,8 @@ static void free_device(DICTIONARY *dict, const char *name) rrdset_obsolete_and_pointer_null(d->st_savings); rrdset_obsolete_and_pointer_null(d->st_alloc_efficiency); rrdset_obsolete_and_pointer_null(d->st_comp_ratio); - dictionary_del_having_write_lock(dict, name); + dictionary_del(dict, name); } - // -------------------------------------------------------------------- static inline int read_mm_stat(procfile *ff, MM_STAT *stats) { ff = procfile_readall(ff); @@ -204,61 +201,51 @@ static inline int read_mm_stat(procfile *ff, MM_STAT *stats) { return 0; } -static inline int _collect_zram_metrics(const char* name, ZRAM_DEVICE *d, int advance, DICTIONARY* dict) { +static int collect_zram_metrics(const DICTIONARY_ITEM *item, void *entry, void *data) { + const char *name = dictionary_acquired_item_name(item); + ZRAM_DEVICE *dev = entry; + DICTIONARY *dict = data; + MM_STAT mm; int value; - if (unlikely(read_mm_stat(d->file, &mm) < 0)) - { + + if (unlikely(read_mm_stat(dev->file, &mm) < 0)) { free_device(dict, name); return -1; } - if (likely(advance)) - { - rrdset_next(d->st_usage); - rrdset_next(d->st_savings); - rrdset_next(d->st_comp_ratio); - rrdset_next(d->st_alloc_efficiency); - } // zram_usage - rrddim_set_by_pointer(d->st_usage, d->rd_compr_data_size, mm.compr_data_size); - rrddim_set_by_pointer(d->st_usage, d->rd_metadata_size, mm.mem_used_total - mm.compr_data_size); - rrdset_done(d->st_usage); + rrddim_set_by_pointer(dev->st_usage, dev->rd_compr_data_size, mm.compr_data_size); + rrddim_set_by_pointer(dev->st_usage, dev->rd_metadata_size, mm.mem_used_total - mm.compr_data_size); + rrdset_done(dev->st_usage); + // zram_savings - rrddim_set_by_pointer(d->st_savings, d->rd_savings_size, mm.compr_data_size - mm.orig_data_size); - rrddim_set_by_pointer(d->st_savings, d->rd_original_size, mm.orig_data_size); - rrdset_done(d->st_savings); + rrddim_set_by_pointer(dev->st_savings, dev->rd_savings_size, mm.compr_data_size - mm.orig_data_size); + rrddim_set_by_pointer(dev->st_savings, dev->rd_original_size, mm.orig_data_size); + rrdset_done(dev->st_savings); + // zram_ratio value = mm.compr_data_size == 0 ? 1 : mm.orig_data_size * 100 / mm.compr_data_size; - rrddim_set_by_pointer(d->st_comp_ratio, d->rd_comp_ratio, value); - rrdset_done(d->st_comp_ratio); + rrddim_set_by_pointer(dev->st_comp_ratio, dev->rd_comp_ratio, value); + rrdset_done(dev->st_comp_ratio); + // zram_efficiency value = mm.mem_used_total == 0 ? 100 : (mm.compr_data_size * 1000000 / mm.mem_used_total); - rrddim_set_by_pointer(d->st_alloc_efficiency, d->rd_alloc_efficiency, value); - rrdset_done(d->st_alloc_efficiency); - return 0; -} - -static int collect_first_zram_metrics(const char *name, void *entry, void *data) { - // collect without calling rrdset_next (init only) - return _collect_zram_metrics(name, (ZRAM_DEVICE *)entry, 0, (DICTIONARY *)data); -} + rrddim_set_by_pointer(dev->st_alloc_efficiency, dev->rd_alloc_efficiency, value); + rrdset_done(dev->st_alloc_efficiency); -static int collect_zram_metrics(const char *name, void *entry, void *data) { - (void)name; - // collect with calling rrdset_next - return _collect_zram_metrics(name, (ZRAM_DEVICE *)entry, 1, (DICTIONARY *)data); + return 0; } - // -------------------------------------------------------------------- - int do_sys_block_zram(int update_every, usec_t dt) { - (void)dt; static procfile *ff = NULL; static DICTIONARY *devices = NULL; static int initialized = 0; static int device_count = 0; int zram_id = -1; + + (void)dt; + if (unlikely(!initialized)) { initialized = 1; @@ -280,17 +267,13 @@ int do_sys_block_zram(int update_every, usec_t dt) { } procfile_close(ff); - devices = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + devices = dictionary_create(DICT_OPTION_SINGLE_THREADED); device_count = init_devices(devices, (unsigned int)zram_id, update_every); - if (device_count < 1) - return 1; - dictionary_walkthrough_write(devices, collect_first_zram_metrics, devices); - } - else - { - if (unlikely(device_count < 1)) - return 1; - dictionary_walkthrough_write(devices, collect_zram_metrics, devices); } + + if (unlikely(device_count < 1)) + return 1; + + dictionary_walkthrough_write(devices, collect_zram_metrics, devices); return 0; }
\ No newline at end of file diff --git a/collectors/proc.plugin/sys_class_infiniband.c b/collectors/proc.plugin/sys_class_infiniband.c index 7e63bcbb4..fca0cb8a2 100644 --- a/collectors/proc.plugin/sys_class_infiniband.c +++ b/collectors/proc.plugin/sys_class_infiniband.c @@ -184,7 +184,7 @@ static struct ibport { RRDSET *st_hwpackets; RRDSET *st_hwerrors; - RRDSETVAR *stv_speed; + const RRDSETVAR_ACQUIRED *stv_speed; usec_t speed_last_collected_usec; @@ -543,15 +543,14 @@ int do_sys_class_infiniband(int update_every, usec_t dt) // x4 lanes multiplier as per Documentation/ABI/stable/sysfs-class-infiniband FOREACH_COUNTER_BYTES(GEN_RRD_DIM_ADD_CUSTOM, port, 4 * 8 * port->width, 1024, RRD_ALGORITHM_INCREMENTAL) - port->stv_speed = rrdsetvar_custom_chart_variable_create(port->st_bytes, "link_speed"); - } else - rrdset_next(port->st_bytes); + port->stv_speed = rrdsetvar_custom_chart_variable_add_and_acquire(port->st_bytes, "link_speed"); + } // Link read values to dimensions FOREACH_COUNTER_BYTES(GEN_RRD_DIM_SETP, port) // For link speed set only variable - rrdsetvar_custom_chart_variable_set(port->stv_speed, port->speed); + rrdsetvar_custom_chart_variable_set(port->st_bytes, port->stv_speed, port->speed); rrdset_done(port->st_bytes); } @@ -578,8 +577,7 @@ int do_sys_class_infiniband(int update_every, usec_t dt) // Create Dimensions rrdset_flag_set(port->st_packets, RRDSET_FLAG_DETAIL); FOREACH_COUNTER_PACKETS(GEN_RRD_DIM_ADD, port) - } else - rrdset_next(port->st_packets); + } // Link read values to dimensions FOREACH_COUNTER_PACKETS(GEN_RRD_DIM_SETP, port) @@ -608,8 +606,7 @@ int do_sys_class_infiniband(int update_every, usec_t dt) // Create Dimensions rrdset_flag_set(port->st_errors, RRDSET_FLAG_DETAIL); FOREACH_COUNTER_ERRORS(GEN_RRD_DIM_ADD, port) - } else - rrdset_next(port->st_errors); + } // Link read values to dimensions FOREACH_COUNTER_ERRORS(GEN_RRD_DIM_SETP, port) @@ -658,8 +655,7 @@ int do_sys_class_infiniband(int update_every, usec_t dt) port->name); port->do_hwerrors = CONFIG_BOOLEAN_NO; } - } else - rrdset_next(port->st_hwerrors); + } } if (port->do_hwpackets != CONFIG_BOOLEAN_NO) { @@ -695,8 +691,7 @@ int do_sys_class_infiniband(int update_every, usec_t dt) port->name); port->do_hwpackets = CONFIG_BOOLEAN_NO; } - } else - rrdset_next(port->st_hwpackets); + } } // Update values to rrd (done by vendor-specific function) diff --git a/collectors/proc.plugin/sys_class_power_supply.c b/collectors/proc.plugin/sys_class_power_supply.c index a80d46e93..dde421503 100644 --- a/collectors/proc.plugin/sys_class_power_supply.c +++ b/collectors/proc.plugin/sys_class_power_supply.c @@ -113,7 +113,7 @@ void power_supply_free(struct power_supply *ps) { } static void add_labels_to_power_supply(struct power_supply *ps, RRDSET *st) { - rrdlabels_add(st->state->chart_labels, "device", ps->name, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device", ps->name, RRDLABEL_SRC_AUTO); } int do_sys_class_power_supply(int update_every, usec_t dt) { @@ -365,8 +365,6 @@ int do_sys_class_power_supply(int update_every, usec_t dt) { add_labels_to_power_supply(ps, ps->capacity->st); } - else - rrdset_next(ps->capacity->st); if(unlikely(!ps->capacity->rd)) ps->capacity->rd = rrddim_add(ps->capacity->st, "capacity", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(ps->capacity->st, ps->capacity->rd, ps->capacity->value); @@ -398,8 +396,6 @@ int do_sys_class_power_supply(int update_every, usec_t dt) { add_labels_to_power_supply(ps, pr->st); } - else - rrdset_next(pr->st); struct ps_property_dim *pd; for(pd = pr->property_dim_root; pd; pd = pd->next) { diff --git a/collectors/proc.plugin/sys_devices_system_edac_mc.c b/collectors/proc.plugin/sys_devices_system_edac_mc.c index 290157903..13d209781 100644 --- a/collectors/proc.plugin/sys_devices_system_edac_mc.c +++ b/collectors/proc.plugin/sys_devices_system_edac_mc.c @@ -78,8 +78,8 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { struct mc *m; if(unlikely(do_ce == -1)) { - do_ce = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory correctable errors", CONFIG_BOOLEAN_AUTO); - do_ue = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory uncorrectable errors", CONFIG_BOOLEAN_AUTO); + do_ce = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory correctable errors", CONFIG_BOOLEAN_YES); + do_ue = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory uncorrectable errors", CONFIG_BOOLEAN_YES); } if(do_ce != CONFIG_BOOLEAN_NO) { @@ -150,8 +150,6 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { , RRDSET_TYPE_LINE ); } - else - rrdset_next(ce_st); for(m = mc_root; m; m = m->next) { if (m->ce_count_filename && m->ce_updated) { @@ -189,8 +187,6 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { , RRDSET_TYPE_LINE ); } - else - rrdset_next(ue_st); for(m = mc_root; m; m = m->next) { if (m->ue_count_filename && m->ue_updated) { diff --git a/collectors/proc.plugin/sys_devices_system_node.c b/collectors/proc.plugin/sys_devices_system_node.c index fd3394309..90aafd56a 100644 --- a/collectors/proc.plugin/sys_devices_system_node.c +++ b/collectors/proc.plugin/sys_devices_system_node.c @@ -115,7 +115,7 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) { , RRDSET_TYPE_LINE ); - rrdlabels_add(m->numastat_st->state->chart_labels, "numa_node", m->name, RRDLABEL_SRC_AUTO); + rrdlabels_add(m->numastat_st->rrdlabels, "numa_node", m->name, RRDLABEL_SRC_AUTO); rrdset_flag_set(m->numastat_st, RRDSET_FLAG_DETAIL); @@ -127,7 +127,6 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) { rrddim_add(m->numastat_st, "other_node", "other", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(m->numastat_st); size_t lines = procfile_lines(m->numastat_ff), l; for(l = 0; l < lines; l++) { diff --git a/collectors/proc.plugin/sys_fs_btrfs.c b/collectors/proc.plugin/sys_fs_btrfs.c index 158587a8f..3b9841fec 100644 --- a/collectors/proc.plugin/sys_fs_btrfs.c +++ b/collectors/proc.plugin/sys_fs_btrfs.c @@ -449,8 +449,8 @@ static inline int find_all_btrfs_pools(const char *path) { } static void add_labels_to_btrfs(BTRFS_NODE *n, RRDSET *st) { - rrdlabels_add(st->state->chart_labels, "device", n->id, RRDLABEL_SRC_AUTO); - rrdlabels_add(st->state->chart_labels, "device_label", n->label, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device", n->id, RRDLABEL_SRC_AUTO); + rrdlabels_add(st->rrdlabels, "device_label", n->label, RRDLABEL_SRC_AUTO); } int do_sys_fs_btrfs(int update_every, usec_t dt) { @@ -587,7 +587,6 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { add_labels_to_btrfs(node, node->st_allocation_disks); } - else rrdset_next(node->st_allocation_disks); // unsigned long long disk_used = node->allocation_data_disk_used + node->allocation_metadata_disk_used + node->allocation_system_disk_used; unsigned long long disk_total = node->allocation_data_disk_total + node->allocation_metadata_disk_total + node->allocation_system_disk_total; @@ -642,7 +641,6 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { add_labels_to_btrfs(node, node->st_allocation_data); } - else rrdset_next(node->st_allocation_data); rrddim_set_by_pointer(node->st_allocation_data, node->rd_allocation_data_free, node->allocation_data_total_bytes - node->allocation_data_bytes_used); rrddim_set_by_pointer(node->st_allocation_data, node->rd_allocation_data_used, node->allocation_data_bytes_used); @@ -688,7 +686,6 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { add_labels_to_btrfs(node, node->st_allocation_metadata); } - else rrdset_next(node->st_allocation_metadata); rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_free, node->allocation_metadata_total_bytes - node->allocation_metadata_bytes_used - node->allocation_global_rsv_size); rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_used, node->allocation_metadata_bytes_used); @@ -734,7 +731,6 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { add_labels_to_btrfs(node, node->st_allocation_system); } - else rrdset_next(node->st_allocation_system); rrddim_set_by_pointer(node->st_allocation_system, node->rd_allocation_system_free, node->allocation_system_total_bytes - node->allocation_system_bytes_used); rrddim_set_by_pointer(node->st_allocation_system, node->rd_allocation_system_used, node->allocation_system_bytes_used); diff --git a/collectors/proc.plugin/sys_kernel_mm_ksm.c b/collectors/proc.plugin/sys_kernel_mm_ksm.c index a0e5690fe..e586d5554 100644 --- a/collectors/proc.plugin/sys_kernel_mm_ksm.c +++ b/collectors/proc.plugin/sys_kernel_mm_ksm.c @@ -119,8 +119,6 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { rd_volatile = rrddim_add(st_mem_ksm, "volatile", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); //rd_to_scan = rrddim_add(st_mem_ksm, "to_scan", "to scan", -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_mem_ksm); rrddim_set_by_pointer(st_mem_ksm, rd_shared, pages_shared * page_size); rrddim_set_by_pointer(st_mem_ksm, rd_unshared, pages_unshared * page_size); @@ -156,8 +154,6 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { rd_savings = rrddim_add(st_mem_ksm_savings, "savings", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rd_offered = rrddim_add(st_mem_ksm_savings, "offered", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_mem_ksm_savings); rrddim_set_by_pointer(st_mem_ksm_savings, rd_savings, saved * page_size); rrddim_set_by_pointer(st_mem_ksm_savings, rd_offered, offered * page_size); @@ -189,11 +185,8 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { rd_savings = rrddim_add(st_mem_ksm_ratios, "savings", NULL, 1, 10000, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_mem_ksm_ratios); rrddim_set_by_pointer(st_mem_ksm_ratios, rd_savings, offered ? (saved * 1000000) / offered : 0); - rrdset_done(st_mem_ksm_ratios); } diff --git a/collectors/proc.plugin/zfs_common.c b/collectors/proc.plugin/zfs_common.c index 330bcf18b..cca0ae0e6 100644 --- a/collectors/proc.plugin/zfs_common.c +++ b/collectors/proc.plugin/zfs_common.c @@ -67,8 +67,6 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_arc_target_min_size = rrddim_add(st_arc_size, "min", "min (hard limit)", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rd_arc_target_max_size = rrddim_add(st_arc_size, "max", "max (high water)", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_arc_size); rrddim_set_by_pointer(st_arc_size, rd_arc_size, arcstats.size); rrddim_set_by_pointer(st_arc_size, rd_arc_target_size, arcstats.c); @@ -105,8 +103,6 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_l2_asize = rrddim_add(st_l2_size, "actual", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rd_l2_size = rrddim_add(st_l2_size, "size", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_l2_size); rrddim_set_by_pointer(st_l2_size, rd_l2_size, arcstats.l2_size); rrddim_set_by_pointer(st_l2_size, rd_l2_asize, arcstats.l2_asize); @@ -149,8 +145,6 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z if(arcstats.l2exist) rd_l2read = rrddim_add(st_reads, "l2reads", "l2", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(st_reads); rrddim_set_by_pointer(st_reads, rd_aread, aread); rrddim_set_by_pointer(st_reads, rd_dread, dread); @@ -191,8 +185,6 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_l2_read_bytes = rrddim_add(st_l2bytes, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rd_l2_write_bytes = rrddim_add(st_l2bytes, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(st_l2bytes); rrddim_set_by_pointer(st_l2bytes, rd_l2_read_bytes, arcstats.l2_read_bytes); rrddim_set_by_pointer(st_l2bytes, rd_l2_write_bytes, arcstats.l2_write_bytes); @@ -227,12 +219,38 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_ahits = rrddim_add(st_ahits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_amisses = rrddim_add(st_ahits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_ahits); rrddim_set_by_pointer(st_ahits, rd_ahits, arcstats.hits); rrddim_set_by_pointer(st_ahits, rd_amisses, arcstats.misses); rrdset_done(st_ahits); + + static RRDSET *st_ahits_rate = NULL; + static RRDDIM *rd_ahits_rate = NULL; + static RRDDIM *rd_amisses_rate = NULL; + + if (unlikely(!st_ahits_rate)) { + st_ahits_rate = rrdset_create_localhost( + "zfs" + , "hits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS ARC Hits Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_HITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_ahits_rate = rrddim_add(st_ahits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_amisses_rate = rrddim_add(st_ahits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_ahits_rate, rd_ahits_rate, arcstats.hits); + rrddim_set_by_pointer(st_ahits_rate, rd_amisses_rate, arcstats.misses); + rrdset_done(st_ahits_rate); } // -------------------------------------------------------------------- @@ -263,12 +281,38 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_dhits = rrddim_add(st_dhits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_dmisses = rrddim_add(st_dhits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_dhits); rrddim_set_by_pointer(st_dhits, rd_dhits, dhit); rrddim_set_by_pointer(st_dhits, rd_dmisses, dmiss); rrdset_done(st_dhits); + + static RRDSET *st_dhits_rate = NULL; + static RRDDIM *rd_dhits_rate = NULL; + static RRDDIM *rd_dmisses_rate = NULL; + + if (unlikely(!st_dhits_rate)) { + st_dhits_rate = rrdset_create_localhost( + "zfs" + , "dhits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS Demand Hits Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_DHITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_dhits_rate = rrddim_add(st_dhits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_dmisses_rate = rrddim_add(st_dhits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_dhits_rate, rd_dhits_rate, dhit); + rrddim_set_by_pointer(st_dhits_rate, rd_dmisses_rate, dmiss); + rrdset_done(st_dhits_rate); } // -------------------------------------------------------------------- @@ -299,12 +343,38 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_phits = rrddim_add(st_phits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_pmisses = rrddim_add(st_phits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_phits); rrddim_set_by_pointer(st_phits, rd_phits, phit); rrddim_set_by_pointer(st_phits, rd_pmisses, pmiss); rrdset_done(st_phits); + + static RRDSET *st_phits_rate = NULL; + static RRDDIM *rd_phits_rate = NULL; + static RRDDIM *rd_pmisses_rate = NULL; + + if (unlikely(!st_phits_rate)) { + st_phits_rate = rrdset_create_localhost( + "zfs" + , "phits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS Prefetch Hits Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_PHITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_phits_rate = rrddim_add(st_phits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_pmisses_rate = rrddim_add(st_phits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_phits_rate, rd_phits_rate, phit); + rrddim_set_by_pointer(st_phits_rate, rd_pmisses_rate, pmiss); + rrdset_done(st_phits_rate); } // -------------------------------------------------------------------- @@ -335,12 +405,38 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_mhits = rrddim_add(st_mhits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_mmisses = rrddim_add(st_mhits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_mhits); rrddim_set_by_pointer(st_mhits, rd_mhits, mhit); rrddim_set_by_pointer(st_mhits, rd_mmisses, mmiss); rrdset_done(st_mhits); + + static RRDSET *st_mhits_rate = NULL; + static RRDDIM *rd_mhits_rate = NULL; + static RRDDIM *rd_mmisses_rate = NULL; + + if (unlikely(!st_mhits_rate)) { + st_mhits_rate = rrdset_create_localhost( + "zfs" + , "mhits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS Metadata Hits Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_MHITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_mhits_rate = rrddim_add(st_mhits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_mmisses_rate = rrddim_add(st_mhits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_mhits_rate, rd_mhits_rate, mhit); + rrddim_set_by_pointer(st_mhits_rate, rd_mmisses_rate, mmiss); + rrdset_done(st_mhits_rate); } // -------------------------------------------------------------------- @@ -371,12 +467,38 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_l2hits = rrddim_add(st_l2hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_l2misses = rrddim_add(st_l2hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_l2hits); rrddim_set_by_pointer(st_l2hits, rd_l2hits, l2hit); rrddim_set_by_pointer(st_l2hits, rd_l2misses, l2miss); rrdset_done(st_l2hits); + + static RRDSET *st_l2hits_rate = NULL; + static RRDDIM *rd_l2hits_rate = NULL; + static RRDDIM *rd_l2misses_rate = NULL; + + if (unlikely(!st_l2hits_rate)) { + st_l2hits_rate = rrdset_create_localhost( + "zfs" + , "l2hits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS L2 Hits Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_L2HITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_l2hits_rate = rrddim_add(st_l2hits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_l2misses_rate = rrddim_add(st_l2hits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_l2hits_rate, rd_l2hits_rate, l2hit); + rrddim_set_by_pointer(st_l2hits_rate, rd_l2misses_rate, l2miss); + rrdset_done(st_l2hits_rate); } // -------------------------------------------------------------------- @@ -414,8 +536,6 @@ void generate_charts_arcstats(const char *plugin, const char *module, int show_z rd_mru = rrddim_add(st_list_hits, "mru", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_mrug = rrddim_add(st_list_hits, "mrug", "mru ghost", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(st_list_hits); rrddim_set_by_pointer(st_list_hits, rd_mfu, arcstats.mfu_hits); rrddim_set_by_pointer(st_list_hits, rd_mru, arcstats.mru_hits); @@ -480,8 +600,6 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_most_recent = rrddim_add(st_arc_size_breakdown, "recent", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL); rd_most_frequent = rrddim_add(st_arc_size_breakdown, "frequent", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL); } - else - rrdset_next(st_arc_size_breakdown); rrddim_set_by_pointer(st_arc_size_breakdown, rd_most_recent, mru_size); rrddim_set_by_pointer(st_arc_size_breakdown, rd_most_frequent, mfu_size); @@ -528,8 +646,6 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_indirect = rrddim_add(st_memory, "indirect", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); #endif } - else - rrdset_next(st_memory); #ifndef __FreeBSD__ rrddim_set_by_pointer(st_memory, rd_direct, arcstats.memory_direct_count); @@ -576,8 +692,6 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_mutex_misses = rrddim_add(st_important_ops, "mtxmis", "mutex miss", 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_hash_collisions = rrddim_add(st_important_ops, "hash_collisions", "hash collisions", 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else - rrdset_next(st_important_ops); rrddim_set_by_pointer(st_important_ops, rd_deleted, arcstats.deleted); rrddim_set_by_pointer(st_important_ops, rd_evict_skips, arcstats.evict_skip); @@ -614,12 +728,38 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_actual_hits = rrddim_add(st_actual_hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_actual_misses = rrddim_add(st_actual_hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_actual_hits); rrddim_set_by_pointer(st_actual_hits, rd_actual_hits, real_hits); rrddim_set_by_pointer(st_actual_hits, rd_actual_misses, real_misses); rrdset_done(st_actual_hits); + + static RRDSET *st_actual_hits_rate = NULL; + static RRDDIM *rd_actual_hits_rate = NULL; + static RRDDIM *rd_actual_misses_rate = NULL; + + if (unlikely(!st_actual_hits_rate)) { + st_actual_hits_rate = rrdset_create_localhost( + "zfs" + , "actual_hits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS Actual Cache Hits Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_ACTUAL_HITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_actual_hits_rate = rrddim_add(st_actual_hits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_actual_misses_rate = rrddim_add(st_actual_hits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_actual_hits_rate, rd_actual_hits_rate, real_hits); + rrddim_set_by_pointer(st_actual_hits_rate, rd_actual_misses_rate, real_misses); + rrdset_done(st_actual_hits_rate); } // -------------------------------------------------------------------- @@ -650,12 +790,38 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_demand_data_hits = rrddim_add(st_demand_data_hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_demand_data_misses = rrddim_add(st_demand_data_hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_demand_data_hits); rrddim_set_by_pointer(st_demand_data_hits, rd_demand_data_hits, arcstats.demand_data_hits); rrddim_set_by_pointer(st_demand_data_hits, rd_demand_data_misses, arcstats.demand_data_misses); rrdset_done(st_demand_data_hits); + + static RRDSET *st_demand_data_hits_rate = NULL; + static RRDDIM *rd_demand_data_hits_rate = NULL; + static RRDDIM *rd_demand_data_misses_rate = NULL; + + if (unlikely(!st_demand_data_hits_rate)) { + st_demand_data_hits_rate = rrdset_create_localhost( + "zfs" + , "demand_data_hits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS Data Demand Efficiency Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_DEMAND_DATA_HITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_demand_data_hits_rate = rrddim_add(st_demand_data_hits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_demand_data_misses_rate = rrddim_add(st_demand_data_hits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_demand_data_hits_rate, rd_demand_data_hits_rate, arcstats.demand_data_hits); + rrddim_set_by_pointer(st_demand_data_hits_rate, rd_demand_data_misses_rate, arcstats.demand_data_misses); + rrdset_done(st_demand_data_hits_rate); } // -------------------------------------------------------------------- @@ -687,12 +853,38 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_prefetch_data_hits = rrddim_add(st_prefetch_data_hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rd_prefetch_data_misses = rrddim_add(st_prefetch_data_hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } - else - rrdset_next(st_prefetch_data_hits); rrddim_set_by_pointer(st_prefetch_data_hits, rd_prefetch_data_hits, arcstats.prefetch_data_hits); rrddim_set_by_pointer(st_prefetch_data_hits, rd_prefetch_data_misses, arcstats.prefetch_data_misses); rrdset_done(st_prefetch_data_hits); + + static RRDSET *st_prefetch_data_hits_rate = NULL; + static RRDDIM *rd_prefetch_data_hits_rate = NULL; + static RRDDIM *rd_prefetch_data_misses_rate = NULL; + + if (unlikely(!st_prefetch_data_hits_rate)) { + st_prefetch_data_hits_rate = rrdset_create_localhost( + "zfs" + , "prefetch_data_hits_rate" + , NULL + , ZFS_FAMILY_EFFICIENCY + , NULL + , "ZFS Data Prefetch Efficiency Rate" + , "events/s" + , plugin + , module + , NETDATA_CHART_PRIO_ZFS_PREFETCH_DATA_HITS + 1 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_prefetch_data_hits_rate = rrddim_add(st_prefetch_data_hits_rate, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_prefetch_data_misses_rate = rrddim_add(st_prefetch_data_hits_rate, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + + rrddim_set_by_pointer(st_prefetch_data_hits_rate, rd_prefetch_data_hits_rate, arcstats.prefetch_data_hits); + rrddim_set_by_pointer(st_prefetch_data_hits_rate, rd_prefetch_data_misses_rate, arcstats.prefetch_data_misses); + rrdset_done(st_prefetch_data_hits_rate); } // -------------------------------------------------------------------- @@ -723,8 +915,6 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_hash_elements_current = rrddim_add(st_hash_elements, "current", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rd_hash_elements_max = rrddim_add(st_hash_elements, "max", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_hash_elements); rrddim_set_by_pointer(st_hash_elements, rd_hash_elements_current, arcstats.hash_elements); rrddim_set_by_pointer(st_hash_elements, rd_hash_elements_max, arcstats.hash_elements_max); @@ -759,8 +949,6 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho rd_hash_chains_current = rrddim_add(st_hash_chains, "current", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rd_hash_chains_max = rrddim_add(st_hash_chains, "max", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - else - rrdset_next(st_hash_chains); rrddim_set_by_pointer(st_hash_chains, rd_hash_chains_current, arcstats.hash_chains); rrddim_set_by_pointer(st_hash_chains, rd_hash_chains_max, arcstats.hash_chain_max); @@ -769,4 +957,4 @@ void generate_charts_arc_summary(const char *plugin, const char *module, int sho // -------------------------------------------------------------------- -}
\ No newline at end of file +} diff --git a/collectors/python.d.plugin/Makefile.am b/collectors/python.d.plugin/Makefile.am index 9377ebe8d..1bbbf8ca0 100644 --- a/collectors/python.d.plugin/Makefile.am +++ b/collectors/python.d.plugin/Makefile.am @@ -66,14 +66,13 @@ include megacli/Makefile.inc include memcached/Makefile.inc include mongodb/Makefile.inc include monit/Makefile.inc -include nginx_plus/Makefile.inc include nvidia_smi/Makefile.inc include nsd/Makefile.inc include ntpd/Makefile.inc include openldap/Makefile.inc include oracledb/Makefile.inc +include pandas/Makefile.inc include postfix/Makefile.inc -include postgres/Makefile.inc include proxysql/Makefile.inc include puppet/Makefile.inc include rabbitmq/Makefile.inc diff --git a/collectors/python.d.plugin/alarms/README.md b/collectors/python.d.plugin/alarms/README.md index ee1e59971..8dc666f5b 100644 --- a/collectors/python.d.plugin/alarms/README.md +++ b/collectors/python.d.plugin/alarms/README.md @@ -58,6 +58,9 @@ local: # a "," separated list of words you want to filter alarm names for. For example 'cpu,load' would filter for only # alarms with "cpu" or "load" in alarm name. Default includes all. alarm_contains_words: '' + # a "," separated list of words you want to exclude based on alarm name. For example 'cpu,load' would exclude + # all alarms with "cpu" or "load" in alarm name. Default excludes None. + alarm_excludes_words: '' ``` It will default to pulling all alarms at each time step from the Netdata rest api at `http://127.0.0.1:19999/api/v1/alarms?all` diff --git a/collectors/python.d.plugin/alarms/alarms.chart.py b/collectors/python.d.plugin/alarms/alarms.chart.py index 314b0e7a8..d19427358 100644 --- a/collectors/python.d.plugin/alarms/alarms.chart.py +++ b/collectors/python.d.plugin/alarms/alarms.chart.py @@ -39,6 +39,7 @@ DEFAULT_URL = 'http://127.0.0.1:19999/api/v1/alarms?all' DEFAULT_COLLECT_ALARM_VALUES = False DEFAULT_ALARM_STATUS_CHART_TYPE = 'line' DEFAULT_ALARM_CONTAINS_WORDS = '' +DEFAULT_ALARM_EXCLUDES_WORDS = '' class Service(UrlService): def __init__(self, configuration=None, name=None): @@ -51,6 +52,8 @@ class Service(UrlService): self.collected_dims = {'alarms': set(), 'values': set()} self.alarm_contains_words = self.configuration.get('alarm_contains_words', DEFAULT_ALARM_CONTAINS_WORDS) self.alarm_contains_words_list = [alarm_contains_word.lstrip(' ').rstrip(' ') for alarm_contains_word in self.alarm_contains_words.split(',')] + self.alarm_excludes_words = self.configuration.get('alarm_excludes_words', DEFAULT_ALARM_EXCLUDES_WORDS) + self.alarm_excludes_words_list = [alarm_excludes_word.lstrip(' ').rstrip(' ') for alarm_excludes_word in self.alarm_excludes_words.split(',')] def _get_data(self): raw_data = self._get_raw_data() @@ -62,6 +65,9 @@ class Service(UrlService): if self.alarm_contains_words != '': alarms = {alarm_name: alarms[alarm_name] for alarm_name in alarms for alarm_contains_word in self.alarm_contains_words_list if alarm_contains_word in alarm_name} + if self.alarm_excludes_words != '': + alarms = {alarm_name: alarms[alarm_name] for alarm_name in alarms for alarm_excludes_word in + self.alarm_excludes_words_list if alarm_excludes_word not in alarm_name} data = {a: self.sm[alarms[a]['status']] for a in alarms if alarms[a]['status'] in self.sm} self.update_charts('alarms', data) diff --git a/collectors/python.d.plugin/alarms/alarms.conf b/collectors/python.d.plugin/alarms/alarms.conf index cd48d4411..06d76c3b3 100644 --- a/collectors/python.d.plugin/alarms/alarms.conf +++ b/collectors/python.d.plugin/alarms/alarms.conf @@ -55,3 +55,6 @@ local: # a "," separated list of words you want to filter alarm names for. For example 'cpu,load' would filter for only # alarms with "cpu" or "load" in alarm name. Default includes all. alarm_contains_words: '' + # a "," separated list of words you want to exclude based on alarm name. For example 'cpu,load' would exclude + # all alarms with "cpu" or "load" in alarm name. Default excludes None. + alarm_excludes_words: '' diff --git a/collectors/python.d.plugin/nginx_plus/Makefile.inc b/collectors/python.d.plugin/nginx_plus/Makefile.inc deleted file mode 100644 index d3fdeaf2b..000000000 --- a/collectors/python.d.plugin/nginx_plus/Makefile.inc +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# THIS IS NOT A COMPLETE Makefile -# IT IS INCLUDED BY ITS PARENT'S Makefile.am -# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT - -# install these files -dist_python_DATA += nginx_plus/nginx_plus.chart.py -dist_pythonconfig_DATA += nginx_plus/nginx_plus.conf - -# do not install these files, but include them in the distribution -dist_noinst_DATA += nginx_plus/README.md nginx_plus/Makefile.inc - diff --git a/collectors/python.d.plugin/nginx_plus/README.md b/collectors/python.d.plugin/nginx_plus/README.md deleted file mode 100644 index 489ac9c2a..000000000 --- a/collectors/python.d.plugin/nginx_plus/README.md +++ /dev/null @@ -1,165 +0,0 @@ -<!-- -title: "NGINX Plus monitoring with Netdata" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/python.d.plugin/nginx_plus/README.md -sidebar_label: "NGINX Plus" ---> - -# NGINX Plus monitoring with Netdata - -Monitors one or more NGINX Plus servers depending on configuration. Servers can be either local or remote. - -Example nginx_plus configuration can be found in 'python.d/nginx_plus.conf' - -It produces following charts: - -1. **Requests total** in requests/s - - - total - -2. **Requests current** in requests - - - current - -3. **Connection Statistics** in connections/s - - - accepted - - dropped - -4. **Workers Statistics** in workers - - - idle - - active - -5. **SSL Handshakes** in handshakes/s - - - successful - - failed - -6. **SSL Session Reuses** in sessions/s - - - reused - -7. **SSL Memory Usage** in percent - - - usage - -8. **Processes** in processes - - - respawned - -For every server zone: - -1. **Processing** in requests - -- processing - -2. **Requests** in requests/s - - - requests - -3. **Responses** in requests/s - - - 1xx - - 2xx - - 3xx - - 4xx - - 5xx - -4. **Traffic** in kilobits/s - - - received - - sent - -For every upstream: - -1. **Peers Requests** in requests/s - - - peer name (dimension per peer) - -2. **All Peers Responses** in responses/s - - - 1xx - - 2xx - - 3xx - - 4xx - - 5xx - -3. **Peer Responses** in requests/s (for every peer) - - - 1xx - - 2xx - - 3xx - - 4xx - - 5xx - -4. **Peers Connections** in active - - - peer name (dimension per peer) - -5. **Peers Connections Usage** in percent - - - peer name (dimension per peer) - -6. **All Peers Traffic** in KB - - - received - - sent - -7. **Peer Traffic** in KB/s (for every peer) - - - received - - sent - -8. **Peer Timings** in ms (for every peer) - - - header - - response - -9. **Memory Usage** in percent - - - usage - -10. **Peers Status** in state - - - peer name (dimension per peer) - -11. **Peers Total Downtime** in seconds - - - peer name (dimension per peer) - -For every cache: - -1. **Traffic** in KB - - - served - - written - - bypass - -2. **Memory Usage** in percent - - - usage - -## Configuration - -Edit the `python.d/nginx_plus.conf` configuration file using `edit-config` from the Netdata [config -directory](/docs/configure/nodes.md), which is typically at `/etc/netdata`. - -```bash -cd /etc/netdata # Replace this path with your Netdata config directory, if different -sudo ./edit-config python.d/nginx_plus.conf -``` - -Needs only `url` to server's `status`. - -Here is an example for a local server: - -```yaml -local: - url : 'http://localhost/status' -``` - -Without configuration, module fail to start. - ---- - - diff --git a/collectors/python.d.plugin/nginx_plus/nginx_plus.chart.py b/collectors/python.d.plugin/nginx_plus/nginx_plus.chart.py deleted file mode 100644 index a6c035f68..000000000 --- a/collectors/python.d.plugin/nginx_plus/nginx_plus.chart.py +++ /dev/null @@ -1,487 +0,0 @@ -# -*- coding: utf-8 -*- -# Description: nginx_plus netdata python.d module -# Author: Ilya Mashchenko (ilyam8) -# SPDX-License-Identifier: GPL-3.0-or-later - -import re - -from collections import defaultdict -from copy import deepcopy -from json import loads - -try: - from collections import OrderedDict -except ImportError: - from third_party.ordereddict import OrderedDict - -from bases.FrameworkServices.UrlService import UrlService - -ORDER = [ - 'requests_total', - 'requests_current', - 'connections_statistics', - 'connections_workers', - 'ssl_handshakes', - 'ssl_session_reuses', - 'ssl_memory_usage', - 'processes' -] - -CHARTS = { - 'requests_total': { - 'options': [None, 'Requests Total', 'requests/s', 'requests', 'nginx_plus.requests_total', 'line'], - 'lines': [ - ['requests_total', 'total', 'incremental'] - ] - }, - 'requests_current': { - 'options': [None, 'Requests Current', 'requests', 'requests', 'nginx_plus.requests_current', 'line'], - 'lines': [ - ['requests_current', 'current'] - ] - }, - 'connections_statistics': { - 'options': [None, 'Connections Statistics', 'connections/s', - 'connections', 'nginx_plus.connections_statistics', 'stacked'], - 'lines': [ - ['connections_accepted', 'accepted', 'incremental'], - ['connections_dropped', 'dropped', 'incremental'] - ] - }, - 'connections_workers': { - 'options': [None, 'Workers Statistics', 'workers', - 'connections', 'nginx_plus.connections_workers', 'stacked'], - 'lines': [ - ['connections_idle', 'idle'], - ['connections_active', 'active'] - ] - }, - 'ssl_handshakes': { - 'options': [None, 'SSL Handshakes', 'handshakes/s', 'ssl', 'nginx_plus.ssl_handshakes', 'stacked'], - 'lines': [ - ['ssl_handshakes', 'successful', 'incremental'], - ['ssl_handshakes_failed', 'failed', 'incremental'] - ] - }, - 'ssl_session_reuses': { - 'options': [None, 'Session Reuses', 'sessions/s', 'ssl', 'nginx_plus.ssl_session_reuses', 'line'], - 'lines': [ - ['ssl_session_reuses', 'reused', 'incremental'] - ] - }, - 'ssl_memory_usage': { - 'options': [None, 'Memory Usage', 'percentage', 'ssl', 'nginx_plus.ssl_memory_usage', 'area'], - 'lines': [ - ['ssl_memory_usage', 'usage', 'absolute', 1, 100] - ] - }, - 'processes': { - 'options': [None, 'Processes', 'processes', 'processes', 'nginx_plus.processes', 'line'], - 'lines': [ - ['processes_respawned', 'respawned'] - ] - } -} - - -def cache_charts(cache): - family = 'cache {0}'.format(cache.real_name) - charts = OrderedDict() - - charts['{0}_traffic'.format(cache.name)] = { - 'options': [None, 'Traffic', 'KiB', family, 'nginx_plus.cache_traffic', 'stacked'], - 'lines': [ - ['_'.join([cache.name, 'hit_bytes']), 'served', 'absolute', 1, 1024], - ['_'.join([cache.name, 'miss_bytes_written']), 'written', 'absolute', 1, 1024], - ['_'.join([cache.name, 'miss_bytes']), 'bypass', 'absolute', 1, 1024] - ] - } - charts['{0}_memory_usage'.format(cache.name)] = { - 'options': [None, 'Memory Usage', 'percentage', family, 'nginx_plus.cache_memory_usage', 'area'], - 'lines': [ - ['_'.join([cache.name, 'memory_usage']), 'usage', 'absolute', 1, 100], - ] - } - return charts - - -def web_zone_charts(wz): - charts = OrderedDict() - family = 'web zone {name}'.format(name=wz.real_name) - - # Processing - charts['zone_{name}_processing'.format(name=wz.name)] = { - 'options': [None, 'Zone "{name}" Processing'.format(name=wz.name), 'requests', family, - 'nginx_plus.web_zone_processing', 'line'], - 'lines': [ - ['_'.join([wz.name, 'processing']), 'processing'] - ] - } - # Requests - charts['zone_{name}_requests'.format(name=wz.name)] = { - 'options': [None, 'Zone "{name}" Requests'.format(name=wz.name), 'requests/s', family, - 'nginx_plus.web_zone_requests', 'line'], - 'lines': [ - ['_'.join([wz.name, 'requests']), 'requests', 'incremental'] - ] - } - # Response Codes - charts['zone_{name}_responses'.format(name=wz.name)] = { - 'options': [None, 'Zone "{name}" Responses'.format(name=wz.name), 'requests/s', family, - 'nginx_plus.web_zone_responses', 'stacked'], - 'lines': [ - ['_'.join([wz.name, 'responses_2xx']), '2xx', 'incremental'], - ['_'.join([wz.name, 'responses_5xx']), '5xx', 'incremental'], - ['_'.join([wz.name, 'responses_3xx']), '3xx', 'incremental'], - ['_'.join([wz.name, 'responses_4xx']), '4xx', 'incremental'], - ['_'.join([wz.name, 'responses_1xx']), '1xx', 'incremental'] - ] - } - # Traffic - charts['zone_{name}_net'.format(name=wz.name)] = { - 'options': [None, 'Zone "{name}" Traffic'.format(name=wz.name), 'kilobits/s', family, - 'nginx_plus.zone_net', 'area'], - 'lines': [ - ['_'.join([wz.name, 'received']), 'received', 'incremental', 1, 1000], - ['_'.join([wz.name, 'sent']), 'sent', 'incremental', -1, 1000] - ] - } - return charts - - -def web_upstream_charts(wu): - def dimensions(value, a='absolute', m=1, d=1): - dims = list() - for p in wu: - dims.append(['_'.join([wu.name, p.server, value]), p.real_server, a, m, d]) - return dims - - charts = OrderedDict() - family = 'web upstream {name}'.format(name=wu.real_name) - - # Requests - charts['web_upstream_{name}_requests'.format(name=wu.name)] = { - 'options': [None, 'Peers Requests', 'requests/s', family, 'nginx_plus.web_upstream_requests', 'line'], - 'lines': dimensions('requests', 'incremental') - } - # Responses Codes - charts['web_upstream_{name}_all_responses'.format(name=wu.name)] = { - 'options': [None, 'All Peers Responses', 'responses/s', family, - 'nginx_plus.web_upstream_all_responses', 'stacked'], - 'lines': [ - ['_'.join([wu.name, 'responses_2xx']), '2xx', 'incremental'], - ['_'.join([wu.name, 'responses_5xx']), '5xx', 'incremental'], - ['_'.join([wu.name, 'responses_3xx']), '3xx', 'incremental'], - ['_'.join([wu.name, 'responses_4xx']), '4xx', 'incremental'], - ['_'.join([wu.name, 'responses_1xx']), '1xx', 'incremental'], - ] - } - for peer in wu: - charts['web_upstream_{0}_{1}_responses'.format(wu.name, peer.server)] = { - 'options': [None, 'Peer "{0}" Responses'.format(peer.real_server), 'responses/s', family, - 'nginx_plus.web_upstream_peer_responses', 'stacked'], - 'lines': [ - ['_'.join([wu.name, peer.server, 'responses_2xx']), '2xx', 'incremental'], - ['_'.join([wu.name, peer.server, 'responses_5xx']), '5xx', 'incremental'], - ['_'.join([wu.name, peer.server, 'responses_3xx']), '3xx', 'incremental'], - ['_'.join([wu.name, peer.server, 'responses_4xx']), '4xx', 'incremental'], - ['_'.join([wu.name, peer.server, 'responses_1xx']), '1xx', 'incremental'] - ] - } - # Connections - charts['web_upstream_{name}_connections'.format(name=wu.name)] = { - 'options': [None, 'Peers Connections', 'active', family, 'nginx_plus.web_upstream_connections', 'line'], - 'lines': dimensions('active') - } - charts['web_upstream_{name}_connections_usage'.format(name=wu.name)] = { - 'options': [None, 'Peers Connections Usage', 'percentage', family, - 'nginx_plus.web_upstream_connections_usage', 'line'], - 'lines': dimensions('connections_usage', d=100) - } - # Traffic - charts['web_upstream_{0}_all_net'.format(wu.name)] = { - 'options': [None, 'All Peers Traffic', 'kilobits/s', family, 'nginx_plus.web_upstream_all_net', 'area'], - 'lines': [ - ['{0}_received'.format(wu.name), 'received', 'incremental', 1, 1000], - ['{0}_sent'.format(wu.name), 'sent', 'incremental', -1, 1000] - ] - } - for peer in wu: - charts['web_upstream_{0}_{1}_net'.format(wu.name, peer.server)] = { - 'options': [None, 'Peer "{0}" Traffic'.format(peer.real_server), 'kilobits/s', family, - 'nginx_plus.web_upstream_peer_traffic', 'area'], - 'lines': [ - ['{0}_{1}_received'.format(wu.name, peer.server), 'received', 'incremental', 1, 1000], - ['{0}_{1}_sent'.format(wu.name, peer.server), 'sent', 'incremental', -1, 1000] - ] - } - # Response Time - for peer in wu: - charts['web_upstream_{0}_{1}_timings'.format(wu.name, peer.server)] = { - 'options': [None, 'Peer "{0}" Timings'.format(peer.real_server), 'milliseconds', family, - 'nginx_plus.web_upstream_peer_timings', 'line'], - 'lines': [ - ['_'.join([wu.name, peer.server, 'header_time']), 'header'], - ['_'.join([wu.name, peer.server, 'response_time']), 'response'] - ] - } - # Memory Usage - charts['web_upstream_{name}_memory_usage'.format(name=wu.name)] = { - 'options': [None, 'Memory Usage', 'percentage', family, 'nginx_plus.web_upstream_memory_usage', 'area'], - 'lines': [ - ['_'.join([wu.name, 'memory_usage']), 'usage', 'absolute', 1, 100] - ] - } - # State - charts['web_upstream_{name}_status'.format(name=wu.name)] = { - 'options': [None, 'Peers Status', 'state', family, 'nginx_plus.web_upstream_status', 'line'], - 'lines': dimensions('state') - } - # Downtime - charts['web_upstream_{name}_downtime'.format(name=wu.name)] = { - 'options': [None, 'Peers Downtime', 'seconds', family, 'nginx_plus.web_upstream_peer_downtime', 'line'], - 'lines': dimensions('downtime', d=1000) - } - - return charts - - -METRICS = { - 'SERVER': [ - 'processes.respawned', - 'connections.accepted', - 'connections.dropped', - 'connections.active', - 'connections.idle', - 'ssl.handshakes', - 'ssl.handshakes_failed', - 'ssl.session_reuses', - 'requests.total', - 'requests.current', - 'slabs.SSL.pages.free', - 'slabs.SSL.pages.used' - ], - 'WEB_ZONE': [ - 'processing', - 'requests', - 'responses.1xx', - 'responses.2xx', - 'responses.3xx', - 'responses.4xx', - 'responses.5xx', - 'discarded', - 'received', - 'sent' - ], - 'WEB_UPSTREAM_PEER': [ - 'id', - 'server', - 'name', - 'state', - 'active', - 'max_conns', - 'requests', - 'header_time', # alive only - 'response_time', # alive only - 'responses.1xx', - 'responses.2xx', - 'responses.3xx', - 'responses.4xx', - 'responses.5xx', - 'sent', - 'received', - 'downtime' - ], - 'WEB_UPSTREAM_SUMMARY': [ - 'responses.1xx', - 'responses.2xx', - 'responses.3xx', - 'responses.4xx', - 'responses.5xx', - 'sent', - 'received' - ], - 'CACHE': [ - 'hit.bytes', # served - 'miss.bytes_written', # written - 'miss.bytes' # bypass - - ] -} - -BAD_SYMBOLS = re.compile(r'[:/.-]+') - - -class Cache: - key = 'caches' - charts = cache_charts - - def __init__(self, **kw): - self.real_name = kw['name'] - self.name = BAD_SYMBOLS.sub('_', self.real_name) - - def memory_usage(self, data): - used = data['slabs'][self.real_name]['pages']['used'] - free = data['slabs'][self.real_name]['pages']['free'] - return used / float(free + used) * 1e4 - - def get_data(self, raw_data): - zone_data = raw_data['caches'][self.real_name] - data = parse_json(zone_data, METRICS['CACHE']) - data['memory_usage'] = self.memory_usage(raw_data) - return dict(('_'.join([self.name, k]), v) for k, v in data.items()) - - -class WebZone: - key = 'server_zones' - charts = web_zone_charts - - def __init__(self, **kw): - self.real_name = kw['name'] - self.name = BAD_SYMBOLS.sub('_', self.real_name) - - def get_data(self, raw_data): - zone_data = raw_data['server_zones'][self.real_name] - data = parse_json(zone_data, METRICS['WEB_ZONE']) - return dict(('_'.join([self.name, k]), v) for k, v in data.items()) - - -class WebUpstream: - key = 'upstreams' - charts = web_upstream_charts - - def __init__(self, **kw): - self.real_name = kw['name'] - self.name = BAD_SYMBOLS.sub('_', self.real_name) - self.peers = OrderedDict() - - peers = kw['response']['upstreams'][self.real_name]['peers'] - for peer in peers: - self.add_peer(peer['id'], peer['server']) - - def __iter__(self): - return iter(self.peers.values()) - - def add_peer(self, idx, server): - peer = WebUpstreamPeer(idx, server) - self.peers[peer.real_server] = peer - return peer - - def peers_stats(self, peers): - peers = {int(peer['id']): peer for peer in peers} - data = dict() - for peer in self.peers.values(): - if not peer.active: - continue - try: - data.update(peer.get_data(peers[peer.id])) - except KeyError: - peer.active = False - return data - - def memory_usage(self, data): - used = data['slabs'][self.real_name]['pages']['used'] - free = data['slabs'][self.real_name]['pages']['free'] - return used / float(free + used) * 1e4 - - def summary_stats(self, data): - rv = defaultdict(int) - for metric in METRICS['WEB_UPSTREAM_SUMMARY']: - for peer in self.peers.values(): - if peer.active: - metric = '_'.join(metric.split('.')) - rv[metric] += data['_'.join([peer.server, metric])] - return rv - - def get_data(self, raw_data): - data = dict() - peers = raw_data['upstreams'][self.real_name]['peers'] - data.update(self.peers_stats(peers)) - data.update(self.summary_stats(data)) - data['memory_usage'] = self.memory_usage(raw_data) - return dict(('_'.join([self.name, k]), v) for k, v in data.items()) - - -class WebUpstreamPeer: - def __init__(self, idx, server): - self.id = idx - self.real_server = server - self.server = BAD_SYMBOLS.sub('_', self.real_server) - self.active = True - - def get_data(self, raw): - data = dict(header_time=0, response_time=0, max_conns=0) - data.update(parse_json(raw, METRICS['WEB_UPSTREAM_PEER'])) - data['connections_usage'] = 0 if not data['max_conns'] else data['active'] / float(data['max_conns']) * 1e4 - data['state'] = int(data['state'] == 'up') - return dict(('_'.join([self.server, k]), v) for k, v in data.items()) - - -class Service(UrlService): - def __init__(self, configuration=None, name=None): - UrlService.__init__(self, configuration=configuration, name=name) - self.order = list(ORDER) - self.definitions = deepcopy(CHARTS) - self.objects = dict() - - def check(self): - if not self.url: - self.error('URL is not defined') - return None - - self._manager = self._build_manager() - if not self._manager: - return None - - raw_data = self._get_raw_data() - if not raw_data: - return None - - try: - response = loads(raw_data) - except ValueError: - return None - - for obj_cls in [WebZone, WebUpstream, Cache]: - for obj_name in response.get(obj_cls.key, list()): - obj = obj_cls(name=obj_name, response=response) - self.objects[obj.real_name] = obj - charts = obj_cls.charts(obj) - for chart in charts: - self.order.append(chart) - self.definitions[chart] = charts[chart] - - return bool(self.objects) - - def _get_data(self): - """ - Format data received from http request - :return: dict - """ - raw_data = self._get_raw_data() - if not raw_data: - return None - response = loads(raw_data) - - data = parse_json(response, METRICS['SERVER']) - data['ssl_memory_usage'] = data['slabs_SSL_pages_used'] / float(data['slabs_SSL_pages_free']) * 1e4 - - for obj in self.objects.values(): - if obj.real_name in response[obj.key]: - data.update(obj.get_data(response)) - - return data - - -def parse_json(raw_data, metrics): - data = dict() - for metric in metrics: - value = raw_data - metrics_list = metric.split('.') - try: - for m in metrics_list: - value = value[m] - except KeyError: - continue - data['_'.join(metrics_list)] = value - return data diff --git a/collectors/python.d.plugin/nginx_plus/nginx_plus.conf b/collectors/python.d.plugin/nginx_plus/nginx_plus.conf deleted file mode 100644 index 201eb0eb7..000000000 --- a/collectors/python.d.plugin/nginx_plus/nginx_plus.conf +++ /dev/null @@ -1,85 +0,0 @@ -# netdata python.d.plugin configuration for nginx_plus -# -# This file is in YaML format. Generally the format is: -# -# name: value -# -# There are 2 sections: -# - global variables -# - one or more JOBS -# -# JOBS allow you to collect values from multiple sources. -# Each source will have its own set of charts. -# -# JOB parameters have to be indented (using spaces only, example below). - -# ---------------------------------------------------------------------- -# Global Variables -# These variables set the defaults for all JOBs, however each JOB -# may define its own, overriding the defaults. - -# update_every sets the default data collection frequency. -# If unset, the python.d.plugin default is used. -# update_every: 1 - -# priority controls the order of charts at the netdata dashboard. -# Lower numbers move the charts towards the top of the page. -# If unset, the default for python.d.plugin is used. -# priority: 60000 - -# penalty indicates whether to apply penalty to update_every in case of failures. -# Penalty will increase every 5 failed updates in a row. Maximum penalty is 10 minutes. -# penalty: yes - -# autodetection_retry sets the job re-check interval in seconds. -# The job is not deleted if check fails. -# Attempts to start the job are made once every autodetection_retry. -# This feature is disabled by default. -# autodetection_retry: 0 - -# ---------------------------------------------------------------------- -# JOBS (data collection sources) -# -# The default JOBS share the same *name*. JOBS with the same name -# are mutually exclusive. Only one of them will be allowed running at -# any time. This allows autodetection to try several alternatives and -# pick the one that works. -# -# Any number of jobs is supported. -# -# All python.d.plugin JOBS (for all its modules) support a set of -# predefined parameters. These are: -# -# job_name: -# name: myname # the JOB's name as it will appear at the -# # dashboard (by default is the job_name) -# # JOBs sharing a name are mutually exclusive -# update_every: 1 # the JOB's data collection frequency -# priority: 60000 # the JOB's order on the dashboard -# penalty: yes # the JOB's penalty -# autodetection_retry: 0 # the JOB's re-check interval in seconds -# -# Additionally to the above, nginx_plus also supports the following: -# -# url: 'URL' # the URL to fetch nginx_plus's stats -# -# if the URL is password protected, the following are supported: -# -# user: 'username' -# pass: 'password' - -# ---------------------------------------------------------------------- -# AUTO-DETECTION JOBS -# only one of them will run (they have the same name) - -localhost: - name : 'local' - url : 'http://localhost/status' - -localipv4: - name : 'local' - url : 'http://127.0.0.1/status' - -localipv6: - name : 'local' - url : 'http://[::1]/status' diff --git a/collectors/python.d.plugin/nvidia_smi/README.md b/collectors/python.d.plugin/nvidia_smi/README.md index fb613064c..bb4169441 100644 --- a/collectors/python.d.plugin/nvidia_smi/README.md +++ b/collectors/python.d.plugin/nvidia_smi/README.md @@ -8,6 +8,8 @@ sidebar_label: "Nvidia GPUs" Monitors performance metrics (memory usage, fan speed, pcie bandwidth utilization, temperature, etc.) using `nvidia-smi` cli tool. +> **Warning**: this collector does not work when the Netdata Agent is [running in a container](https://learn.netdata.cloud/docs/agent/packaging/docker). + ## Requirements and Notes diff --git a/collectors/python.d.plugin/nvidia_smi/nvidia_smi.chart.py b/collectors/python.d.plugin/nvidia_smi/nvidia_smi.chart.py index 1913e94e4..23e90e658 100644 --- a/collectors/python.d.plugin/nvidia_smi/nvidia_smi.chart.py +++ b/collectors/python.d.plugin/nvidia_smi/nvidia_smi.chart.py @@ -4,11 +4,10 @@ # Author: Ilya Mashchenko (ilyam8) # User Memory Stat Author: Guido Scatena (scatenag) -import subprocess -import threading import os import pwd - +import subprocess +import threading import xml.etree.ElementTree as et from bases.FrameworkServices.SimpleService import SimpleService @@ -32,6 +31,7 @@ BAR_USAGE = 'bar1_mem_usage' TEMPERATURE = 'temperature' CLOCKS = 'clocks' POWER = 'power' +POWER_STATE = 'power_state' PROCESSES_MEM = 'processes_mem' USER_MEM = 'user_mem' USER_NUM = 'user_num' @@ -47,11 +47,15 @@ ORDER = [ TEMPERATURE, CLOCKS, POWER, + POWER_STATE, PROCESSES_MEM, USER_MEM, USER_NUM, ] +# https://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/group__gpupstate.html +POWER_STATES = ['P' + str(i) for i in range(0, 16)] + def gpu_charts(gpu): fam = gpu.full_name() @@ -125,6 +129,10 @@ def gpu_charts(gpu): ['power_draw', 'power', 'absolute', 1, 100], ] }, + POWER_STATE: { + 'options': [None, 'Power State', 'state', fam, 'nvidia_smi.power_state', 'line'], + 'lines': [['power_state_' + v.lower(), v, 'absolute'] for v in POWER_STATES] + }, PROCESSES_MEM: { 'options': [None, 'Memory Used by Each Process', 'MiB', fam, 'nvidia_smi.processes_mem', 'stacked'], 'lines': [] @@ -382,6 +390,10 @@ class GPU: def mem_clock(self): return self.root.find('clocks').find('mem_clock').text.split()[0] + @handle_attr_error + def power_state(self): + return str(self.root.find('power_readings').find('power_state').text.split()[0]) + @handle_value_error @handle_attr_error def power_draw(self): @@ -426,6 +438,13 @@ class GPU: 'mem_clock': self.mem_clock(), 'power_draw': self.power_draw(), } + + for v in POWER_STATES: + data['power_state_' + v.lower()] = 0 + p_state = self.power_state() + if p_state: + data['power_state_' + p_state.lower()] = 1 + processes = self.processes() or [] users = set() for p in processes: @@ -450,7 +469,7 @@ class Service(SimpleService): self.order = list() self.definitions = dict() self.loop_mode = configuration.get('loop_mode', True) - poll = int(configuration.get('poll_seconds', 1)) + poll = int(configuration.get('poll_seconds', self.get_update_every())) self.exclude_zero_memory_users = configuration.get('exclude_zero_memory_users', False) self.poller = NvidiaSMIPoller(poll) diff --git a/collectors/python.d.plugin/postgres/Makefile.inc b/collectors/python.d.plugin/pandas/Makefile.inc index 91a185cb9..9f4f9b34b 100644 --- a/collectors/python.d.plugin/postgres/Makefile.inc +++ b/collectors/python.d.plugin/pandas/Makefile.inc @@ -5,9 +5,9 @@ # IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT # install these files -dist_python_DATA += postgres/postgres.chart.py -dist_pythonconfig_DATA += postgres/postgres.conf +dist_python_DATA += pandas/pandas.chart.py +dist_pythonconfig_DATA += pandas/pandas.conf # do not install these files, but include them in the distribution -dist_noinst_DATA += postgres/README.md postgres/Makefile.inc +dist_noinst_DATA += pandas/README.md pandas/Makefile.inc diff --git a/collectors/python.d.plugin/pandas/README.md b/collectors/python.d.plugin/pandas/README.md new file mode 100644 index 000000000..141549478 --- /dev/null +++ b/collectors/python.d.plugin/pandas/README.md @@ -0,0 +1,92 @@ +<!-- +title: "Pandas" +custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/python.d.plugin/pandas/README.md +--> + +# Pandas Netdata Collector + +<a href="https://pandas.pydata.org/" target="_blank"> + <img src="https://pandas.pydata.org/docs/_static/pandas.svg" alt="Pandas" width="100px" height="50px" /> + </a> + +A python collector using [pandas](https://pandas.pydata.org/) to pull data and do pandas based +preprocessing before feeding to Netdata. + +## Requirements + +This collector depends on some Python (Python 3 only) packages that can usually be installed via `pip` or `pip3`. + +```bash +sudo pip install pandas requests +``` + +## Configuration + +Below is an example configuration to query some json weather data from [Open-Meteo](https://open-meteo.com), +do some data wrangling on it and save in format as expected by Netdata. + +```yaml +# example pulling some hourly temperature data +temperature: + name: "temperature" + update_every: 3 + chart_configs: + - name: "temperature_by_city" + title: "Temperature By City" + family: "temperature.today" + context: "pandas.temperature" + type: "line" + units: "Celsius" + df_steps: > + pd.DataFrame.from_dict( + {city: requests.get( + f'https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lng}&hourly=temperature_2m' + ).json()['hourly']['temperature_2m'] + for (city,lat,lng) + in [ + ('dublin', 53.3441, -6.2675), + ('athens', 37.9792, 23.7166), + ('london', 51.5002, -0.1262), + ('berlin', 52.5235, 13.4115), + ('paris', 48.8567, 2.3510), + ] + } + ); # use dictionary comprehension to make multiple requests; + df.describe(); # get aggregate stats for each city; + df.transpose()[['mean', 'max', 'min']].reset_index(); # just take mean, min, max; + df.rename(columns={'index':'city'}); # some column renaming; + df.pivot(columns='city').mean().to_frame().reset_index(); # force to be one row per city; + df.rename(columns={0:'degrees'}); # some column renaming; + pd.concat([df, df['city']+'_'+df['level_0']], axis=1); # add new column combining city and summary measurement label; + df.rename(columns={0:'measurement'}); # some column renaming; + df[['measurement', 'degrees']].set_index('measurement'); # just take two columns we want; + df.sort_index(); # sort by city name; + df.transpose(); # transpose so its just one wide row; +``` + +`chart_configs` is a list of dictionary objects where each one defines the sequence of `df_steps` to be run using [`pandas`](https://pandas.pydata.org/), +and the `name`, `title` etc to define the +[CHART variables](https://learn.netdata.cloud/docs/agent/collectors/python.d.plugin#global-variables-order-and-chart) +that will control how the results will look in netdata. + +The example configuration above would result in a `data` dictionary like the below being collected by Netdata +at each time step. They keys in this dictionary will be the +[dimension](https://learn.netdata.cloud/docs/agent/web#dimensions) names on the chart. + +```javascript +{'athens_max': 26.2, 'athens_mean': 19.45952380952381, 'athens_min': 12.2, 'berlin_max': 17.4, 'berlin_mean': 10.764285714285714, 'berlin_min': 5.7, 'dublin_max': 15.3, 'dublin_mean': 12.008928571428571, 'dublin_min': 6.6, 'london_max': 18.9, 'london_mean': 12.510714285714286, 'london_min': 5.2, 'paris_max': 19.4, 'paris_mean': 12.054166666666665, 'paris_min': 4.8} +``` + +Which, given the above configuration would end up as a chart like below in Netdata. + +![pandas collector temperature example chart](https://user-images.githubusercontent.com/2178292/195075312-8ce8cf68-5172-48e3-af09-104ffecfcdd6.png) + +## Notes +- Each line in `df_steps` must return a pandas +[DataFrame](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html) object (`df`) at each step. +- You can use +[this colab notebook](https://colab.research.google.com/drive/1VYrddSegZqGtkWGFuiUbMbUk5f3rW6Hi?usp=sharing) +to mock up and work on your `df_steps` iteratively before adding them to your config. +- This collector is expecting one row in the final pandas DataFrame. It is that first row that will be taken +as the most recent values for each dimension on each chart using (`df.to_dict(orient='records')[0]`). +See [pd.to_dict()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_dict.html). diff --git a/collectors/python.d.plugin/pandas/pandas.chart.py b/collectors/python.d.plugin/pandas/pandas.chart.py new file mode 100644 index 000000000..8eb4452fb --- /dev/null +++ b/collectors/python.d.plugin/pandas/pandas.chart.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Description: pandas netdata python.d module +# Author: Andrew Maguire (andrewm4894) +# SPDX-License-Identifier: GPL-3.0-or-later + +import pandas as pd + +try: + import requests + HAS_REQUESTS = True +except ImportError: + HAS_REQUESTS = False + +from bases.FrameworkServices.SimpleService import SimpleService + +ORDER = [] + +CHARTS = {} + + +class Service(SimpleService): + def __init__(self, configuration=None, name=None): + SimpleService.__init__(self, configuration=configuration, name=name) + self.order = ORDER + self.definitions = CHARTS + self.chart_configs = self.configuration.get('chart_configs', None) + self.line_sep = self.configuration.get('line_sep', ';') + + def run_code(self, df_steps): + """eval() each line of code and ensure the result is a pandas dataframe""" + + # process each line of code + lines = df_steps.split(self.line_sep) + for line in lines: + line_clean = line.strip('\n').strip(' ') + if line_clean != '' and line_clean[0] != '#': + df = eval(line_clean) + assert isinstance(df, pd.DataFrame), 'The result of each evaluated line of `df_steps` must be of type `pd.DataFrame`' + + # take top row of final df as data to be collected by netdata + data = df.to_dict(orient='records')[0] + + return data + + def check(self): + """ensure charts and dims all configured and that we can get data""" + + if not HAS_REQUESTS: + self.warn('requests library could not be imported') + + if not self.chart_configs: + self.error('chart_configs must be defined') + + data = dict() + + # add each chart as defined by the config + for chart_config in self.chart_configs: + if chart_config['name'] not in self.charts: + chart_template = { + 'options': [ + chart_config['name'], + chart_config['title'], + chart_config['units'], + chart_config['family'], + chart_config['context'], + chart_config['type'] + ], + 'lines': [] + } + self.charts.add_chart([chart_config['name']] + chart_template['options']) + + data_tmp = self.run_code(chart_config['df_steps']) + data.update(data_tmp) + + for dim in data_tmp: + self.charts[chart_config['name']].add_dimension([dim, dim, 'absolute', 1, 1]) + + return True + + def get_data(self): + """get data for each chart config""" + + data = dict() + + for chart_config in self.chart_configs: + data_tmp = self.run_code(chart_config['df_steps']) + data.update(data_tmp) + + return data diff --git a/collectors/python.d.plugin/pandas/pandas.conf b/collectors/python.d.plugin/pandas/pandas.conf new file mode 100644 index 000000000..6684af9d5 --- /dev/null +++ b/collectors/python.d.plugin/pandas/pandas.conf @@ -0,0 +1,191 @@ +# netdata python.d.plugin configuration for pandas +# +# This file is in YaML format. Generally the format is: +# +# name: value +# +# There are 2 sections: +# - global variables +# - one or more JOBS +# +# JOBS allow you to collect values from multiple sources. +# Each source will have its own set of charts. +# +# JOB parameters have to be indented (using spaces only, example below). + +# ---------------------------------------------------------------------- +# Global Variables +# These variables set the defaults for all JOBs, however each JOB +# may define its own, overriding the defaults. + +# update_every sets the default data collection frequency. +# If unset, the python.d.plugin default is used. +update_every: 5 + +# priority controls the order of charts at the netdata dashboard. +# Lower numbers move the charts towards the top of the page. +# If unset, the default for python.d.plugin is used. +# priority: 60000 + +# penalty indicates whether to apply penalty to update_every in case of failures. +# Penalty will increase every 5 failed updates in a row. Maximum penalty is 10 minutes. +# penalty: yes + +# autodetection_retry sets the job re-check interval in seconds. +# The job is not deleted if check fails. +# Attempts to start the job are made once every autodetection_retry. +# This feature is disabled by default. +# autodetection_retry: 0 + +# ---------------------------------------------------------------------- +# JOBS (data collection sources) +# +# The default JOBS share the same *name*. JOBS with the same name +# are mutually exclusive. Only one of them will be allowed running at +# any time. This allows autodetection to try several alternatives and +# pick the one that works. +# +# Any number of jobs is supported. +# +# All python.d.plugin JOBS (for all its modules) support a set of +# predefined parameters. These are: +# +# job_name: +# name: myname # the JOB's name as it will appear on the dashboard +# # dashboard (by default is the job_name) +# # JOBs sharing a name are mutually exclusive +# update_every: 1 # the JOB's data collection frequency +# priority: 60000 # the JOB's order on the dashboard +# penalty: yes # the JOB's penalty +# autodetection_retry: 0 # the JOB's re-check interval in seconds +# +# Additionally to the above, example also supports the following: +# +# num_lines: 4 # the number of lines to create +# lower: 0 # the lower bound of numbers to randomly sample from +# upper: 100 # the upper bound of numbers to randomly sample from +# +# ---------------------------------------------------------------------- +# AUTO-DETECTION JOBS + +# Some example configurations, enable this collector, uncomment and example below and restart netdata to enable. + +# example pulling some hourly temperature data, a chart for today forecast (mean,min,max) and another chart for current. +# temperature: +# name: "temperature" +# update_every: 5 +# chart_configs: +# - name: "temperature_forecast_by_city" +# title: "Temperature By City - Today Forecast" +# family: "temperature.today" +# context: "pandas.temperature" +# type: "line" +# units: "Celsius" +# df_steps: > +# pd.DataFrame.from_dict( +# {city: requests.get(f'https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lng}&hourly=temperature_2m').json()['hourly']['temperature_2m'] +# for (city,lat,lng) +# in [ +# ('dublin', 53.3441, -6.2675), +# ('athens', 37.9792, 23.7166), +# ('london', 51.5002, -0.1262), +# ('berlin', 52.5235, 13.4115), +# ('paris', 48.8567, 2.3510), +# ('madrid', 40.4167, -3.7033), +# ('new_york', 40.71, -74.01), +# ('los_angeles', 34.05, -118.24), +# ] +# } +# ); +# df.describe(); # get aggregate stats for each city; +# df.transpose()[['mean', 'max', 'min']].reset_index(); # just take mean, min, max; +# df.rename(columns={'index':'city'}); # some column renaming; +# df.pivot(columns='city').mean().to_frame().reset_index(); # force to be one row per city; +# df.rename(columns={0:'degrees'}); # some column renaming; +# pd.concat([df, df['city']+'_'+df['level_0']], axis=1); # add new column combining city and summary measurement label; +# df.rename(columns={0:'measurement'}); # some column renaming; +# df[['measurement', 'degrees']].set_index('measurement'); # just take two columns we want; +# df.sort_index(); # sort by city name; +# df.transpose(); # transpose so its just one wide row; +# - name: "temperature_current_by_city" +# title: "Temperature By City - Current" +# family: "temperature.current" +# context: "pandas.temperature" +# type: "line" +# units: "Celsius" +# df_steps: > +# pd.DataFrame.from_dict( +# {city: requests.get(f'https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lng}¤t_weather=true').json()['current_weather'] +# for (city,lat,lng) +# in [ +# ('dublin', 53.3441, -6.2675), +# ('athens', 37.9792, 23.7166), +# ('london', 51.5002, -0.1262), +# ('berlin', 52.5235, 13.4115), +# ('paris', 48.8567, 2.3510), +# ('madrid', 40.4167, -3.7033), +# ('new_york', 40.71, -74.01), +# ('los_angeles', 34.05, -118.24), +# ] +# } +# ); +# df.transpose(); +# df[['temperature']]; +# df.transpose(); + +# example showing a read_csv from a url and some light pandas data wrangling. +# pull data in csv format from london demo server and then ratio of user cpus over system cpu averaged over last 60 seconds. +# example_csv: +# name: "example_csv" +# update_every: 2 +# chart_configs: +# - name: "london_system_cpu" +# title: "London System CPU - Ratios" +# family: "london_system_cpu" +# context: "pandas" +# type: "line" +# units: "n" +# df_steps: > +# pd.read_csv('https://london.my-netdata.io/api/v1/data?chart=system.cpu&format=csv&after=-60', storage_options={'User-Agent': 'netdata'}); +# df.drop('time', axis=1); +# df.mean().to_frame().transpose(); +# df.apply(lambda row: (row.user / row.system), axis = 1).to_frame(); +# df.rename(columns={0:'average_user_system_ratio'}); +# df*100; + +# example showing a read_json from a url and some light pandas data wrangling. +# pull data in json format (using requests.get() if json data is too complex for pd.read_json() ) from london demo server and work out 'total_bandwidth'. +# example_json: +# name: "example_json" +# update_every: 2 +# chart_configs: +# - name: "london_system_net" +# title: "London System Net - Total Bandwidth" +# family: "london_system_net" +# context: "pandas" +# type: "area" +# units: "kilobits/s" +# df_steps: > +# pd.DataFrame(requests.get('https://london.my-netdata.io/api/v1/data?chart=system.net&format=json&after=-1').json()['data'], columns=requests.get('https://london.my-netdata.io/api/v1/data?chart=system.net&format=json&after=-1').json()['labels']); +# df.drop('time', axis=1); +# abs(df); +# df.sum(axis=1).to_frame(); +# df.rename(columns={0:'total_bandwidth'}); + +# example showing a read_xml from a url and some light pandas data wrangling. +# pull weather forecast data in xml format, use xpath to pull out temperature forecast. +# example_xml: +# name: "example_xml" +# update_every: 2 +# line_sep: "|" +# chart_configs: +# - name: "temperature_forcast" +# title: "Temperature Forecast" +# family: "temp" +# context: "pandas.temp" +# type: "line" +# units: "celsius" +# df_steps: > +# pd.read_xml('http://metwdb-openaccess.ichec.ie/metno-wdb2ts/locationforecast?lat=54.7210798611;long=-8.7237392806', xpath='./product/time[1]/location/temperature', parser='etree')| +# df.rename(columns={'value': 'dublin'})| +# df[['dublin']]|
\ No newline at end of file diff --git a/collectors/python.d.plugin/postfix/README.md b/collectors/python.d.plugin/postfix/README.md index ac16962a5..1a546c614 100644 --- a/collectors/python.d.plugin/postfix/README.md +++ b/collectors/python.d.plugin/postfix/README.md @@ -6,22 +6,31 @@ sidebar_label: "Postfix" # Postfix monitoring with Netdata -Monitors MTA email queue statistics using postqueue tool. +Monitors MTA email queue statistics using [postqueue](http://www.postfix.org/postqueue.1.html) tool. -Execute `postqueue -p` to grab postfix queue. +The collector executes `postqueue -p` to get Postfix queue statistics. -It produces only two charts: +## Requirements -1. **Postfix Queue Emails** +Postfix has internal access controls that limit activities on the mail queue. By default, all users are allowed to view +the queue. If your system is configured with stricter access controls, you need to grant the `netdata` user access to +view the mail queue. In order to do it, add `netdata` to `authorized_mailq_users` in the `/etc/postfix/main.cf` file. - - emails +See the `authorized_mailq_users` setting in +the [Postfix documentation](https://www.postfix.org/postconf.5.html) for more details. -2. **Postfix Queue Emails Size** in KB +## Charts - - size +It produces only two charts: -Configuration is not needed. +1. **Postfix Queue Emails** ---- + - emails +2. **Postfix Queue Emails Size** in KB + - size + +## Configuration + +Configuration is not needed. diff --git a/collectors/python.d.plugin/postgres/README.md b/collectors/python.d.plugin/postgres/README.md deleted file mode 100644 index 7acb9a7a9..000000000 --- a/collectors/python.d.plugin/postgres/README.md +++ /dev/null @@ -1,145 +0,0 @@ -<!-- -title: "PostgreSQL monitoring with Netdata" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/python.d.plugin/postgres/README.md -sidebar_label: "PostgreSQL" ---> - -# PostgreSQL monitoring with Netdata - -> **Warning**: This module is deprecated and will be deleted in v1.37.0. -> Use [go.d/postgres](https://learn.netdata.cloud/docs/agent/collectors/go.d.plugin/modules/postgres). - -Collects database health and performance metrics. - -## Requirements - -- `python-psycopg2` package. You have to install it manually and make sure that it is available to the `netdata` user, either using `pip`, the package manager of your Linux distribution, or any other method you prefer. - -- PostgreSQL v9.4+ - -Following charts are drawn: - -1. **Database size** MB - - - size - -2. **Current Backend Processes** processes - - - active - -3. **Current Backend Process Usage** percentage - - - used - - available - -4. **Write-Ahead Logging Statistics** files/s - - - total - - ready - - done - -5. **Checkpoints** writes/s - - - scheduled - - requested - -6. **Current connections to db** count - - - connections - -7. **Tuples returned from db** tuples/s - - - sequential - - bitmap - -8. **Tuple reads from db** reads/s - - - disk - - cache - -9. **Transactions on db** transactions/s - - - committed - - rolled back - -10. **Tuples written to db** writes/s - - - inserted - - updated - - deleted - - conflicts - -11. **Locks on db** count per type - - - locks - -12. **Standby delta** KB - - - sent delta - - write delta - - flush delta - - replay delta - -13. **Standby lag** seconds - - - write lag - - flush lag - - replay lag - -14. **Average number of blocking transactions in db** processes - - - blocking - -## Configuration - -Edit the `python.d/postgres.conf` configuration file using `edit-config` from the Netdata [config -directory](/docs/configure/nodes.md), which is typically at `/etc/netdata`. - -```bash -cd /etc/netdata # Replace this path with your Netdata config directory, if different -sudo ./edit-config python.d/postgres.conf -``` - -When no configuration file is found, the module tries to connect to TCP/IP socket: `localhost:5432` with the -following collection jobs. - -```yaml -socket: - name : 'socket' - user : 'postgres' - database : 'postgres' - -tcp: - name : 'tcp' - user : 'postgres' - database : 'postgres' - host : 'localhost' - port : 5432 -``` - -**Note**: Every job collection must have a unique identifier. In cases that you monitor multiple DBs, every -job must have it's own name. Use a mnemonic of your preference (e.g us_east_db, us_east_tcp) - -## Troubleshooting - -To troubleshoot issues with the `postgres` collector, run the `python.d.plugin` with the debug option enabled. The output -should give you clues as to why the collector isn't working. - -First, navigate to your plugins directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on your -system, open `netdata.conf` and look for the setting `plugins directory`. Once you're in the plugin's directory, switch -to the `netdata` user. - -```bash -cd /usr/libexec/netdata/plugins.d/ -sudo su -s /bin/bash netdata -``` - -You can now run the `python.d.plugin` to debug the collector: - -```bash -./python.d.plugin postgres debug trace -``` - ---- - - diff --git a/collectors/python.d.plugin/postgres/postgres.chart.py b/collectors/python.d.plugin/postgres/postgres.chart.py deleted file mode 100644 index bd8f71a66..000000000 --- a/collectors/python.d.plugin/postgres/postgres.chart.py +++ /dev/null @@ -1,1436 +0,0 @@ -# -*- coding: utf-8 -*- -# Description: example netdata python.d module -# Authors: facetoe, dangtranhoang -# SPDX-License-Identifier: GPL-3.0-or-later - -from copy import deepcopy - -try: - import psycopg2 - from psycopg2 import extensions - from psycopg2.extras import DictCursor - from psycopg2 import OperationalError - - PSYCOPG2 = True -except ImportError: - PSYCOPG2 = False - -from bases.FrameworkServices.SimpleService import SimpleService - -DEFAULT_PORT = 5432 -DEFAULT_USER = 'postgres' -DEFAULT_CONNECT_TIMEOUT = 2 # seconds -DEFAULT_STATEMENT_TIMEOUT = 5000 # ms - -CONN_PARAM_DSN = 'dsn' -CONN_PARAM_HOST = 'host' -CONN_PARAM_PORT = 'port' -CONN_PARAM_DATABASE = 'database' -CONN_PARAM_USER = 'user' -CONN_PARAM_PASSWORD = 'password' -CONN_PARAM_CONN_TIMEOUT = 'connect_timeout' -CONN_PARAM_STATEMENT_TIMEOUT = 'statement_timeout' -CONN_PARAM_SSL_MODE = 'sslmode' -CONN_PARAM_SSL_ROOT_CERT = 'sslrootcert' -CONN_PARAM_SSL_CRL = 'sslcrl' -CONN_PARAM_SSL_CERT = 'sslcert' -CONN_PARAM_SSL_KEY = 'sslkey' - -QUERY_NAME_WAL = 'WAL' -QUERY_NAME_ARCHIVE = 'ARCHIVE' -QUERY_NAME_BACKENDS = 'BACKENDS' -QUERY_NAME_BACKEND_USAGE = 'BACKEND_USAGE' -QUERY_NAME_TABLE_STATS = 'TABLE_STATS' -QUERY_NAME_INDEX_STATS = 'INDEX_STATS' -QUERY_NAME_DATABASE = 'DATABASE' -QUERY_NAME_BGWRITER = 'BGWRITER' -QUERY_NAME_LOCKS = 'LOCKS' -QUERY_NAME_BLOCKERS = 'BLOCKERS' -QUERY_NAME_DATABASES = 'DATABASES' -QUERY_NAME_STANDBY = 'STANDBY' -QUERY_NAME_REPLICATION_SLOT = 'REPLICATION_SLOT' -QUERY_NAME_STANDBY_DELTA = 'STANDBY_DELTA' -QUERY_NAME_STANDBY_LAG = 'STANDBY_LAG' -QUERY_NAME_REPSLOT_FILES = 'REPSLOT_FILES' -QUERY_NAME_IF_SUPERUSER = 'IF_SUPERUSER' -QUERY_NAME_SERVER_VERSION = 'SERVER_VERSION' -QUERY_NAME_AUTOVACUUM = 'AUTOVACUUM' -QUERY_NAME_FORCED_AUTOVACUUM = 'FORCED_AUTOVACUUM' -QUERY_NAME_TX_WRAPAROUND = 'TX_WRAPAROUND' -QUERY_NAME_DIFF_LSN = 'DIFF_LSN' -QUERY_NAME_WAL_WRITES = 'WAL_WRITES' - -METRICS = { - QUERY_NAME_DATABASE: [ - 'connections', - 'xact_commit', - 'xact_rollback', - 'blks_read', - 'blks_hit', - 'tup_returned', - 'tup_fetched', - 'tup_inserted', - 'tup_updated', - 'tup_deleted', - 'conflicts', - 'temp_files', - 'temp_bytes', - 'size' - ], - QUERY_NAME_BACKENDS: [ - 'backends_active', - 'backends_idle' - ], - QUERY_NAME_BACKEND_USAGE: [ - 'available', - 'used' - ], - QUERY_NAME_INDEX_STATS: [ - 'index_count', - 'index_size' - ], - QUERY_NAME_TABLE_STATS: [ - 'table_size', - 'table_count' - ], - QUERY_NAME_WAL: [ - 'written_wal', - 'recycled_wal', - 'total_wal' - ], - QUERY_NAME_WAL_WRITES: [ - 'wal_writes' - ], - QUERY_NAME_ARCHIVE: [ - 'ready_count', - 'done_count', - 'file_count' - ], - QUERY_NAME_BGWRITER: [ - 'checkpoint_scheduled', - 'checkpoint_requested', - 'buffers_checkpoint', - 'buffers_clean', - 'maxwritten_clean', - 'buffers_backend', - 'buffers_alloc', - 'buffers_backend_fsync' - ], - QUERY_NAME_LOCKS: [ - 'ExclusiveLock', - 'RowShareLock', - 'SIReadLock', - 'ShareUpdateExclusiveLock', - 'AccessExclusiveLock', - 'AccessShareLock', - 'ShareRowExclusiveLock', - 'ShareLock', - 'RowExclusiveLock' - ], - QUERY_NAME_BLOCKERS: [ - 'blocking_pids_avg' - ], - QUERY_NAME_AUTOVACUUM: [ - 'analyze', - 'vacuum_analyze', - 'vacuum', - 'vacuum_freeze', - 'brin_summarize' - ], - QUERY_NAME_FORCED_AUTOVACUUM: [ - 'percent_towards_forced_vacuum' - ], - QUERY_NAME_TX_WRAPAROUND: [ - 'oldest_current_xid', - 'percent_towards_wraparound' - ], - QUERY_NAME_STANDBY_DELTA: [ - 'sent_delta', - 'write_delta', - 'flush_delta', - 'replay_delta' - ], - QUERY_NAME_STANDBY_LAG: [ - 'write_lag', - 'flush_lag', - 'replay_lag' - ], - QUERY_NAME_REPSLOT_FILES: [ - 'replslot_wal_keep', - 'replslot_files' - ] -} - -NO_VERSION = 0 -DEFAULT = 'DEFAULT' -V72 = 'V72' -V82 = 'V82' -V91 = 'V91' -V92 = 'V92' -V96 = 'V96' -V10 = 'V10' -V11 = 'V11' - -QUERY_WAL = { - DEFAULT: """ -SELECT - count(*) as total_wal, - count(*) FILTER (WHERE type = 'recycled') AS recycled_wal, - count(*) FILTER (WHERE type = 'written') AS written_wal -FROM - (SELECT - wal.name, - pg_walfile_name( - CASE pg_is_in_recovery() - WHEN true THEN NULL - ELSE pg_current_wal_lsn() - END ), - CASE - WHEN wal.name > pg_walfile_name( - CASE pg_is_in_recovery() - WHEN true THEN NULL - ELSE pg_current_wal_lsn() - END ) THEN 'recycled' - ELSE 'written' - END AS type - FROM pg_catalog.pg_ls_dir('pg_wal') AS wal(name) - WHERE name ~ '^[0-9A-F]{24}$' - ORDER BY - (pg_stat_file('pg_wal/'||name, true)).modification, - wal.name DESC) sub; -""", - V96: """ -SELECT - count(*) as total_wal, - count(*) FILTER (WHERE type = 'recycled') AS recycled_wal, - count(*) FILTER (WHERE type = 'written') AS written_wal -FROM - (SELECT - wal.name, - pg_xlogfile_name( - CASE pg_is_in_recovery() - WHEN true THEN NULL - ELSE pg_current_xlog_location() - END ), - CASE - WHEN wal.name > pg_xlogfile_name( - CASE pg_is_in_recovery() - WHEN true THEN NULL - ELSE pg_current_xlog_location() - END ) THEN 'recycled' - ELSE 'written' - END AS type - FROM pg_catalog.pg_ls_dir('pg_xlog') AS wal(name) - WHERE name ~ '^[0-9A-F]{24}$' - ORDER BY - (pg_stat_file('pg_xlog/'||name, true)).modification, - wal.name DESC) sub; -""", -} - -QUERY_ARCHIVE = { - DEFAULT: """ -SELECT - CAST(COUNT(*) AS INT) AS file_count, - CAST(COALESCE(SUM(CAST(archive_file ~ $r$\.ready$$r$ as INT)),0) AS INT) AS ready_count, - CAST(COALESCE(SUM(CAST(archive_file ~ $r$\.done$$r$ AS INT)),0) AS INT) AS done_count -FROM - pg_catalog.pg_ls_dir('pg_wal/archive_status') AS archive_files (archive_file); -""", - V96: """ -SELECT - CAST(COUNT(*) AS INT) AS file_count, - CAST(COALESCE(SUM(CAST(archive_file ~ $r$\.ready$$r$ as INT)),0) AS INT) AS ready_count, - CAST(COALESCE(SUM(CAST(archive_file ~ $r$\.done$$r$ AS INT)),0) AS INT) AS done_count -FROM - pg_catalog.pg_ls_dir('pg_xlog/archive_status') AS archive_files (archive_file); - -""", -} - -QUERY_BACKEND = { - DEFAULT: """ -SELECT - count(*) - (SELECT count(*) - FROM pg_stat_activity - WHERE state = 'idle') - AS backends_active, - (SELECT count(*) - FROM pg_stat_activity - WHERE state = 'idle') - AS backends_idle -FROM pg_stat_activity; -""", -} - -QUERY_BACKEND_USAGE = { - DEFAULT: """ -SELECT - COUNT(1) as used, - current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int - - COUNT(1) AS available -FROM pg_catalog.pg_stat_activity -WHERE backend_type IN ('client backend', 'background worker'); -""", - V10: """ -SELECT - SUM(s.conn) as used, - current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int - - SUM(s.conn) AS available -FROM ( - SELECT 's' as type, COUNT(1) as conn - FROM pg_catalog.pg_stat_activity - WHERE backend_type IN ('client backend', 'background worker') - UNION ALL - SELECT 'r', COUNT(1) - FROM pg_catalog.pg_stat_replication -) as s; -""", - V92: """ -SELECT - SUM(s.conn) as used, - current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int - - SUM(s.conn) AS available -FROM ( - SELECT 's' as type, COUNT(1) as conn - FROM pg_catalog.pg_stat_activity - WHERE query NOT LIKE 'autovacuum: %%' - UNION ALL - SELECT 'r', COUNT(1) - FROM pg_catalog.pg_stat_replication -) as s; -""", - V91: """ -SELECT - SUM(s.conn) as used, - current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int - - SUM(s.conn) AS available -FROM ( - SELECT 's' as type, COUNT(1) as conn - FROM pg_catalog.pg_stat_activity - WHERE current_query NOT LIKE 'autovacuum: %%' - UNION ALL - SELECT 'r', COUNT(1) - FROM pg_catalog.pg_stat_replication -) as s; -""", - V82: """ -SELECT - COUNT(1) as used, - current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int - - COUNT(1) AS available -FROM pg_catalog.pg_stat_activity -WHERE current_query NOT LIKE 'autovacuum: %%'; -""", - V72: """ -SELECT - COUNT(1) as used, - current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int - - COUNT(1) AS available -FROM pg_catalog.pg_stat_activity s -JOIN pg_catalog.pg_database d ON d.oid = s.datid -WHERE d.datallowconn; -""", -} - -QUERY_TABLE_STATS = { - DEFAULT: """ -SELECT - sum(relpages) * current_setting('block_size')::numeric AS table_size, - count(1) AS table_count -FROM pg_class -WHERE relkind IN ('r', 't', 'm'); -""", -} - -QUERY_INDEX_STATS = { - DEFAULT: """ -SELECT - sum(relpages) * current_setting('block_size')::numeric AS index_size, - count(1) AS index_count -FROM pg_class -WHERE relkind = 'i'; -""", -} - -QUERY_DATABASE = { - DEFAULT: """ -SELECT - datname AS database_name, - numbackends AS connections, - xact_commit AS xact_commit, - xact_rollback AS xact_rollback, - blks_read AS blks_read, - blks_hit AS blks_hit, - tup_returned AS tup_returned, - tup_fetched AS tup_fetched, - tup_inserted AS tup_inserted, - tup_updated AS tup_updated, - tup_deleted AS tup_deleted, - conflicts AS conflicts, - pg_database_size(datname) AS size, - temp_files AS temp_files, - temp_bytes AS temp_bytes -FROM pg_stat_database -WHERE datname IN %(databases)s ; -""", -} - -QUERY_BGWRITER = { - DEFAULT: """ -SELECT - checkpoints_timed AS checkpoint_scheduled, - checkpoints_req AS checkpoint_requested, - buffers_checkpoint * current_setting('block_size')::numeric buffers_checkpoint, - buffers_clean * current_setting('block_size')::numeric buffers_clean, - maxwritten_clean, - buffers_backend * current_setting('block_size')::numeric buffers_backend, - buffers_alloc * current_setting('block_size')::numeric buffers_alloc, - buffers_backend_fsync -FROM pg_stat_bgwriter; -""", -} - -QUERY_LOCKS = { - DEFAULT: """ -SELECT - pg_database.datname as database_name, - mode, - count(mode) AS locks_count -FROM pg_locks -INNER JOIN pg_database - ON pg_database.oid = pg_locks.database -GROUP BY datname, mode -ORDER BY datname, mode; -""", -} - -QUERY_BLOCKERS = { - DEFAULT: """ -WITH B AS ( -SELECT DISTINCT - pg_database.datname as database_name, - pg_locks.pid, - cardinality(pg_blocking_pids(pg_locks.pid)) AS blocking_pids -FROM pg_locks -INNER JOIN pg_database ON pg_database.oid = pg_locks.database -WHERE NOT pg_locks.granted) -SELECT database_name, AVG(blocking_pids) AS blocking_pids_avg -FROM B -GROUP BY database_name -""", - V96: """ -WITH B AS ( -SELECT DISTINCT - pg_database.datname as database_name, - blocked_locks.pid AS blocked_pid, - COUNT(blocking_locks.pid) AS blocking_pids -FROM pg_catalog.pg_locks blocked_locks -INNER JOIN pg_database ON pg_database.oid = blocked_locks.database -JOIN pg_catalog.pg_locks blocking_locks - ON blocking_locks.locktype = blocked_locks.locktype - AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database - AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation - AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page - AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple - AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid - AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid - AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid - AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid - AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid - AND blocking_locks.pid != blocked_locks.pid -WHERE NOT blocked_locks.GRANTED -GROUP BY database_name, blocked_pid) -SELECT database_name, AVG(blocking_pids) AS blocking_pids_avg -FROM B -GROUP BY database_name -""" -} - -QUERY_DATABASES = { - DEFAULT: """ -SELECT - datname -FROM pg_stat_database -WHERE - has_database_privilege( - (SELECT current_user), datname, 'connect') - AND NOT datname ~* '^template\d' -ORDER BY datname; -""", -} - -QUERY_STANDBY = { - DEFAULT: """ -SELECT - COALESCE(prs.slot_name, psr.application_name) application_name -FROM pg_stat_replication psr -LEFT OUTER JOIN pg_replication_slots prs on psr.pid = prs.active_pid -WHERE application_name IS NOT NULL; -""", -} - -QUERY_REPLICATION_SLOT = { - DEFAULT: """ -SELECT slot_name -FROM pg_replication_slots; -""" -} - -QUERY_STANDBY_DELTA = { - DEFAULT: """ -SELECT - COALESCE(prs.slot_name, psr.application_name) application_name, - pg_wal_lsn_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_wal_receive_lsn() - ELSE pg_current_wal_lsn() - END, - sent_lsn) AS sent_delta, - pg_wal_lsn_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_wal_receive_lsn() - ELSE pg_current_wal_lsn() - END, - write_lsn) AS write_delta, - pg_wal_lsn_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_wal_receive_lsn() - ELSE pg_current_wal_lsn() - END, - flush_lsn) AS flush_delta, - pg_wal_lsn_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_wal_receive_lsn() - ELSE pg_current_wal_lsn() - END, - replay_lsn) AS replay_delta -FROM pg_stat_replication psr -LEFT OUTER JOIN pg_replication_slots prs on psr.pid = prs.active_pid -WHERE application_name IS NOT NULL; -""", - V96: """ -SELECT - COALESCE(prs.slot_name, psr.application_name) application_name, - pg_xlog_location_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_xlog_receive_location() - ELSE pg_current_xlog_location() - END, - sent_location) AS sent_delta, - pg_xlog_location_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_xlog_receive_location() - ELSE pg_current_xlog_location() - END, - write_location) AS write_delta, - pg_xlog_location_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_xlog_receive_location() - ELSE pg_current_xlog_location() - END, - flush_location) AS flush_delta, - pg_xlog_location_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_xlog_receive_location() - ELSE pg_current_xlog_location() - END, - replay_location) AS replay_delta -FROM pg_stat_replication psr -LEFT OUTER JOIN pg_replication_slots prs on psr.pid = prs.active_pid -WHERE application_name IS NOT NULL; -""", -} - -QUERY_STANDBY_LAG = { - DEFAULT: """ -SELECT - COALESCE(prs.slot_name, psr.application_name) application_name, - COALESCE(EXTRACT(EPOCH FROM write_lag)::bigint, 0) AS write_lag, - COALESCE(EXTRACT(EPOCH FROM flush_lag)::bigint, 0) AS flush_lag, - COALESCE(EXTRACT(EPOCH FROM replay_lag)::bigint, 0) AS replay_lag -FROM pg_stat_replication psr -LEFT OUTER JOIN pg_replication_slots prs on psr.pid = prs.active_pid -WHERE application_name IS NOT NULL; -""" -} - -QUERY_REPSLOT_FILES = { - DEFAULT: """ -WITH wal_size AS ( - SELECT - setting::int AS val - FROM pg_settings - WHERE name = 'wal_segment_size' - ) -SELECT - slot_name, - slot_type, - replslot_wal_keep, - count(slot_file) AS replslot_files -FROM - (SELECT - slot.slot_name, - CASE - WHEN slot_file <> 'state' THEN 1 - END AS slot_file , - slot_type, - COALESCE ( - floor( - CASE WHEN pg_is_in_recovery() - THEN ( - pg_wal_lsn_diff(pg_last_wal_receive_lsn(), slot.restart_lsn) - -- this is needed to account for whole WAL retention and - -- not only size retention - + (pg_wal_lsn_diff(restart_lsn, '0/0') %% s.val) - ) / s.val - ELSE ( - pg_wal_lsn_diff(pg_current_wal_lsn(), slot.restart_lsn) - -- this is needed to account for whole WAL retention and - -- not only size retention - + (pg_walfile_name_offset(restart_lsn)).file_offset - ) / s.val - END - ),0) AS replslot_wal_keep - FROM pg_replication_slots slot - LEFT JOIN ( - SELECT - slot2.slot_name, - pg_ls_dir('pg_replslot/' || slot2.slot_name) AS slot_file - FROM pg_replication_slots slot2 - ) files (slot_name, slot_file) - ON slot.slot_name = files.slot_name - CROSS JOIN wal_size s - ) AS d -GROUP BY - slot_name, - slot_type, - replslot_wal_keep; -""", - V10: """ -WITH wal_size AS ( - SELECT - current_setting('wal_block_size')::INT * setting::INT AS val - FROM pg_settings - WHERE name = 'wal_segment_size' - ) -SELECT - slot_name, - slot_type, - replslot_wal_keep, - count(slot_file) AS replslot_files -FROM - (SELECT - slot.slot_name, - CASE - WHEN slot_file <> 'state' THEN 1 - END AS slot_file , - slot_type, - COALESCE ( - floor( - CASE WHEN pg_is_in_recovery() - THEN ( - pg_wal_lsn_diff(pg_last_wal_receive_lsn(), slot.restart_lsn) - -- this is needed to account for whole WAL retention and - -- not only size retention - + (pg_wal_lsn_diff(restart_lsn, '0/0') %% s.val) - ) / s.val - ELSE ( - pg_wal_lsn_diff(pg_current_wal_lsn(), slot.restart_lsn) - -- this is needed to account for whole WAL retention and - -- not only size retention - + (pg_walfile_name_offset(restart_lsn)).file_offset - ) / s.val - END - ),0) AS replslot_wal_keep - FROM pg_replication_slots slot - LEFT JOIN ( - SELECT - slot2.slot_name, - pg_ls_dir('pg_replslot/' || slot2.slot_name) AS slot_file - FROM pg_replication_slots slot2 - ) files (slot_name, slot_file) - ON slot.slot_name = files.slot_name - CROSS JOIN wal_size s - ) AS d -GROUP BY - slot_name, - slot_type, - replslot_wal_keep; -""", -} - -QUERY_SUPERUSER = { - DEFAULT: """ -SELECT current_setting('is_superuser') = 'on' AS is_superuser; -""", -} - -QUERY_SHOW_VERSION = { - DEFAULT: """ -SHOW server_version_num; -""", -} - -QUERY_AUTOVACUUM = { - DEFAULT: """ -SELECT - count(*) FILTER (WHERE query LIKE 'autovacuum: ANALYZE%%') AS analyze, - count(*) FILTER (WHERE query LIKE 'autovacuum: VACUUM ANALYZE%%') AS vacuum_analyze, - count(*) FILTER (WHERE query LIKE 'autovacuum: VACUUM%%' - AND query NOT LIKE 'autovacuum: VACUUM ANALYZE%%' - AND query NOT LIKE '%%to prevent wraparound%%') AS vacuum, - count(*) FILTER (WHERE query LIKE '%%to prevent wraparound%%') AS vacuum_freeze, - count(*) FILTER (WHERE query LIKE 'autovacuum: BRIN summarize%%') AS brin_summarize -FROM pg_stat_activity -WHERE query NOT LIKE '%%pg_stat_activity%%'; -""", -} - -QUERY_FORCED_AUTOVACUUM = { - DEFAULT: """ -WITH max_age AS ( - SELECT setting AS autovacuum_freeze_max_age - FROM pg_catalog.pg_settings - WHERE name = 'autovacuum_freeze_max_age' ) -, per_database_stats AS ( - SELECT datname - , m.autovacuum_freeze_max_age::int - , age(d.datfrozenxid) AS oldest_current_xid - FROM pg_catalog.pg_database d - JOIN max_age m ON (true) - WHERE d.datallowconn ) -SELECT max(ROUND(100*(oldest_current_xid/autovacuum_freeze_max_age::float))) AS percent_towards_forced_autovacuum -FROM per_database_stats; -""", -} - -QUERY_TX_WRAPAROUND = { - DEFAULT: """ -WITH max_age AS ( - SELECT 2000000000 as max_old_xid - FROM pg_catalog.pg_settings - WHERE name = 'autovacuum_freeze_max_age' ) -, per_database_stats AS ( - SELECT datname - , m.max_old_xid::int - , age(d.datfrozenxid) AS oldest_current_xid - FROM pg_catalog.pg_database d - JOIN max_age m ON (true) - WHERE d.datallowconn ) -SELECT max(oldest_current_xid) AS oldest_current_xid - , max(ROUND(100*(oldest_current_xid/max_old_xid::float))) AS percent_towards_wraparound -FROM per_database_stats; -""", -} - -QUERY_DIFF_LSN = { - DEFAULT: """ -SELECT - pg_wal_lsn_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_wal_receive_lsn() - ELSE pg_current_wal_lsn() - END, - '0/0') as wal_writes ; -""", - V96: """ -SELECT - pg_xlog_location_diff( - CASE pg_is_in_recovery() - WHEN true THEN pg_last_xlog_receive_location() - ELSE pg_current_xlog_location() - END, - '0/0') as wal_writes ; -""", -} - -def query_factory(name, version=NO_VERSION): - if name == QUERY_NAME_BACKENDS: - return QUERY_BACKEND[DEFAULT] - elif name == QUERY_NAME_BACKEND_USAGE: - if version < 80200: - return QUERY_BACKEND_USAGE[V72] - if version < 90100: - return QUERY_BACKEND_USAGE[V82] - if version < 90200: - return QUERY_BACKEND_USAGE[V91] - if version < 100000: - return QUERY_BACKEND_USAGE[V92] - elif version < 120000: - return QUERY_BACKEND_USAGE[V10] - return QUERY_BACKEND_USAGE[DEFAULT] - elif name == QUERY_NAME_TABLE_STATS: - return QUERY_TABLE_STATS[DEFAULT] - elif name == QUERY_NAME_INDEX_STATS: - return QUERY_INDEX_STATS[DEFAULT] - elif name == QUERY_NAME_DATABASE: - return QUERY_DATABASE[DEFAULT] - elif name == QUERY_NAME_BGWRITER: - return QUERY_BGWRITER[DEFAULT] - elif name == QUERY_NAME_LOCKS: - return QUERY_LOCKS[DEFAULT] - elif name == QUERY_NAME_BLOCKERS: - if version < 90600: - return QUERY_BLOCKERS[V96] - return QUERY_BLOCKERS[DEFAULT] - elif name == QUERY_NAME_DATABASES: - return QUERY_DATABASES[DEFAULT] - elif name == QUERY_NAME_STANDBY: - return QUERY_STANDBY[DEFAULT] - elif name == QUERY_NAME_REPLICATION_SLOT: - return QUERY_REPLICATION_SLOT[DEFAULT] - elif name == QUERY_NAME_IF_SUPERUSER: - return QUERY_SUPERUSER[DEFAULT] - elif name == QUERY_NAME_SERVER_VERSION: - return QUERY_SHOW_VERSION[DEFAULT] - elif name == QUERY_NAME_AUTOVACUUM: - return QUERY_AUTOVACUUM[DEFAULT] - elif name == QUERY_NAME_FORCED_AUTOVACUUM: - return QUERY_FORCED_AUTOVACUUM[DEFAULT] - elif name == QUERY_NAME_TX_WRAPAROUND: - return QUERY_TX_WRAPAROUND[DEFAULT] - elif name == QUERY_NAME_WAL: - if version < 100000: - return QUERY_WAL[V96] - return QUERY_WAL[DEFAULT] - elif name == QUERY_NAME_ARCHIVE: - if version < 100000: - return QUERY_ARCHIVE[V96] - return QUERY_ARCHIVE[DEFAULT] - elif name == QUERY_NAME_STANDBY_DELTA: - if version < 100000: - return QUERY_STANDBY_DELTA[V96] - return QUERY_STANDBY_DELTA[DEFAULT] - elif name == QUERY_NAME_STANDBY_LAG: - return QUERY_STANDBY_LAG[DEFAULT] - elif name == QUERY_NAME_REPSLOT_FILES: - if version < 110000: - return QUERY_REPSLOT_FILES[V10] - return QUERY_REPSLOT_FILES[DEFAULT] - elif name == QUERY_NAME_DIFF_LSN: - if version < 100000: - return QUERY_DIFF_LSN[V96] - return QUERY_DIFF_LSN[DEFAULT] - - raise ValueError('unknown query') - - -ORDER = [ - 'db_stat_temp_files', - 'db_stat_temp_bytes', - 'db_stat_blks', - 'db_stat_tuple_returned', - 'db_stat_tuple_write', - 'db_stat_transactions', - 'db_stat_connections', - 'db_stat_blocking_pids_avg', - 'database_size', - 'backend_process', - 'backend_usage', - 'index_count', - 'index_size', - 'table_count', - 'table_size', - 'wal', - 'wal_writes', - 'archive_wal', - 'checkpointer', - 'stat_bgwriter_alloc', - 'stat_bgwriter_checkpoint', - 'stat_bgwriter_backend', - 'stat_bgwriter_backend_fsync', - 'stat_bgwriter_bgwriter', - 'stat_bgwriter_maxwritten', - 'replication_slot', - 'standby_delta', - 'standby_lag', - 'autovacuum', - 'forced_autovacuum', - 'tx_wraparound_oldest_current_xid', - 'tx_wraparound_percent_towards_wraparound' -] - -CHARTS = { - 'db_stat_transactions': { - 'options': [None, 'Transactions on db', 'transactions/s', 'db statistics', 'postgres.db_stat_transactions', - 'line'], - 'lines': [ - ['xact_commit', 'committed', 'incremental'], - ['xact_rollback', 'rolled back', 'incremental'] - ] - }, - 'db_stat_connections': { - 'options': [None, 'Current connections to db', 'count', 'db statistics', 'postgres.db_stat_connections', - 'line'], - 'lines': [ - ['connections', 'connections', 'absolute'] - ] - }, - 'db_stat_blks': { - 'options': [None, 'Disk blocks reads from db', 'reads/s', 'db statistics', 'postgres.db_stat_blks', 'line'], - 'lines': [ - ['blks_read', 'disk', 'incremental'], - ['blks_hit', 'cache', 'incremental'] - ] - }, - 'db_stat_tuple_returned': { - 'options': [None, 'Tuples returned from db', 'tuples/s', 'db statistics', 'postgres.db_stat_tuple_returned', - 'line'], - 'lines': [ - ['tup_returned', 'sequential', 'incremental'], - ['tup_fetched', 'bitmap', 'incremental'] - ] - }, - 'db_stat_tuple_write': { - 'options': [None, 'Tuples written to db', 'writes/s', 'db statistics', 'postgres.db_stat_tuple_write', 'line'], - 'lines': [ - ['tup_inserted', 'inserted', 'incremental'], - ['tup_updated', 'updated', 'incremental'], - ['tup_deleted', 'deleted', 'incremental'], - ['conflicts', 'conflicts', 'incremental'] - ] - }, - 'db_stat_temp_bytes': { - 'options': [None, 'Temp files written to disk', 'KiB/s', 'db statistics', 'postgres.db_stat_temp_bytes', - 'line'], - 'lines': [ - ['temp_bytes', 'size', 'incremental', 1, 1024] - ] - }, - 'db_stat_temp_files': { - 'options': [None, 'Temp files written to disk', 'files', 'db statistics', 'postgres.db_stat_temp_files', - 'line'], - 'lines': [ - ['temp_files', 'files', 'incremental'] - ] - }, - 'db_stat_blocking_pids_avg': { - 'options': [None, 'Average number of blocking transactions in db', 'processes', 'db statistics', - 'postgres.db_stat_blocking_pids_avg', 'line'], - 'lines': [ - ['blocking_pids_avg', 'blocking', 'absolute'] - ] - }, - 'database_size': { - 'options': [None, 'Database size', 'MiB', 'database size', 'postgres.db_size', 'stacked'], - 'lines': [ - ] - }, - 'backend_process': { - 'options': [None, 'Current Backend Processes', 'processes', 'backend processes', 'postgres.backend_process', - 'line'], - 'lines': [ - ['backends_active', 'active', 'absolute'], - ['backends_idle', 'idle', 'absolute'] - ] - }, - 'backend_usage': { - 'options': [None, '% of Connections in use', 'percentage', 'backend processes', 'postgres.backend_usage', 'stacked'], - 'lines': [ - ['available', 'available', 'percentage-of-absolute-row'], - ['used', 'used', 'percentage-of-absolute-row'] - ] - }, - 'index_count': { - 'options': [None, 'Total indexes', 'index', 'indexes', 'postgres.index_count', 'line'], - 'lines': [ - ['index_count', 'total', 'absolute'] - ] - }, - 'index_size': { - 'options': [None, 'Indexes size', 'MiB', 'indexes', 'postgres.index_size', 'line'], - 'lines': [ - ['index_size', 'size', 'absolute', 1, 1024 * 1024] - ] - }, - 'table_count': { - 'options': [None, 'Total Tables', 'tables', 'tables', 'postgres.table_count', 'line'], - 'lines': [ - ['table_count', 'total', 'absolute'] - ] - }, - 'table_size': { - 'options': [None, 'Tables size', 'MiB', 'tables', 'postgres.table_size', 'line'], - 'lines': [ - ['table_size', 'size', 'absolute', 1, 1024 * 1024] - ] - }, - 'wal': { - 'options': [None, 'Write-Ahead Logs', 'files', 'wal', 'postgres.wal', 'line'], - 'lines': [ - ['written_wal', 'written', 'absolute'], - ['recycled_wal', 'recycled', 'absolute'], - ['total_wal', 'total', 'absolute'] - ] - }, - 'wal_writes': { - 'options': [None, 'Write-Ahead Logs', 'KiB/s', 'wal_writes', 'postgres.wal_writes', 'line'], - 'lines': [ - ['wal_writes', 'writes', 'incremental', 1, 1024] - ] - }, - 'archive_wal': { - 'options': [None, 'Archive Write-Ahead Logs', 'files/s', 'archive wal', 'postgres.archive_wal', 'line'], - 'lines': [ - ['file_count', 'total', 'incremental'], - ['ready_count', 'ready', 'incremental'], - ['done_count', 'done', 'incremental'] - ] - }, - 'checkpointer': { - 'options': [None, 'Checkpoints', 'writes', 'checkpointer', 'postgres.checkpointer', 'line'], - 'lines': [ - ['checkpoint_scheduled', 'scheduled', 'incremental'], - ['checkpoint_requested', 'requested', 'incremental'] - ] - }, - 'stat_bgwriter_alloc': { - 'options': [None, 'Buffers allocated', 'KiB/s', 'bgwriter', 'postgres.stat_bgwriter_alloc', 'line'], - 'lines': [ - ['buffers_alloc', 'alloc', 'incremental', 1, 1024] - ] - }, - 'stat_bgwriter_checkpoint': { - 'options': [None, 'Buffers written during checkpoints', 'KiB/s', 'bgwriter', - 'postgres.stat_bgwriter_checkpoint', 'line'], - 'lines': [ - ['buffers_checkpoint', 'checkpoint', 'incremental', 1, 1024] - ] - }, - 'stat_bgwriter_backend': { - 'options': [None, 'Buffers written directly by a backend', 'KiB/s', 'bgwriter', - 'postgres.stat_bgwriter_backend', 'line'], - 'lines': [ - ['buffers_backend', 'backend', 'incremental', 1, 1024] - ] - }, - 'stat_bgwriter_backend_fsync': { - 'options': [None, 'Fsync by backend', 'times', 'bgwriter', 'postgres.stat_bgwriter_backend_fsync', 'line'], - 'lines': [ - ['buffers_backend_fsync', 'backend fsync', 'incremental'] - ] - }, - 'stat_bgwriter_bgwriter': { - 'options': [None, 'Buffers written by the background writer', 'KiB/s', 'bgwriter', - 'postgres.bgwriter_bgwriter', 'line'], - 'lines': [ - ['buffers_clean', 'clean', 'incremental', 1, 1024] - ] - }, - 'stat_bgwriter_maxwritten': { - 'options': [None, 'Too many buffers written', 'times', 'bgwriter', 'postgres.stat_bgwriter_maxwritten', - 'line'], - 'lines': [ - ['maxwritten_clean', 'maxwritten', 'incremental'] - ] - }, - 'autovacuum': { - 'options': [None, 'Autovacuum workers', 'workers', 'autovacuum', 'postgres.autovacuum', 'line'], - 'lines': [ - ['analyze', 'analyze', 'absolute'], - ['vacuum', 'vacuum', 'absolute'], - ['vacuum_analyze', 'vacuum analyze', 'absolute'], - ['vacuum_freeze', 'vacuum freeze', 'absolute'], - ['brin_summarize', 'brin summarize', 'absolute'] - ] - }, - 'forced_autovacuum': { - 'options': [None, 'Percent towards forced autovacuum', 'percent', 'autovacuum', 'postgres.forced_autovacuum', 'line'], - 'lines': [ - ['percent_towards_forced_autovacuum', 'percent', 'absolute'] - ] - }, - 'tx_wraparound_oldest_current_xid': { - 'options': [None, 'Oldest current XID', 'xid', 'tx_wraparound', 'postgres.tx_wraparound_oldest_current_xid', 'line'], - 'lines': [ - ['oldest_current_xid', 'xid', 'absolute'] - ] - }, - 'tx_wraparound_percent_towards_wraparound': { - 'options': [None, 'Percent towards wraparound', 'percent', 'tx_wraparound', 'postgres.percent_towards_wraparound', 'line'], - 'lines': [ - ['percent_towards_wraparound', 'percent', 'absolute'] - ] - }, - 'standby_delta': { - 'options': [None, 'Standby delta', 'KiB', 'replication delta', 'postgres.standby_delta', 'line'], - 'lines': [ - ['sent_delta', 'sent delta', 'absolute', 1, 1024], - ['write_delta', 'write delta', 'absolute', 1, 1024], - ['flush_delta', 'flush delta', 'absolute', 1, 1024], - ['replay_delta', 'replay delta', 'absolute', 1, 1024] - ] - }, - 'standby_lag': { - 'options': [None, 'Standby lag', 'seconds', 'replication lag', 'postgres.standby_lag', 'line'], - 'lines': [ - ['write_lag', 'write lag', 'absolute'], - ['flush_lag', 'flush lag', 'absolute'], - ['replay_lag', 'replay lag', 'absolute'] - ] - }, - 'replication_slot': { - 'options': [None, 'Replication slot files', 'files', 'replication slot', 'postgres.replication_slot', 'line'], - 'lines': [ - ['replslot_wal_keep', 'wal keeped', 'absolute'], - ['replslot_files', 'pg_replslot files', 'absolute'] - ] - } -} - - -class Service(SimpleService): - def __init__(self, configuration=None, name=None): - SimpleService.__init__(self, configuration=configuration, name=name) - self.order = list(ORDER) - self.definitions = deepcopy(CHARTS) - self.do_table_stats = configuration.pop('table_stats', False) - self.do_index_stats = configuration.pop('index_stats', False) - self.databases_to_poll = configuration.pop('database_poll', None) - self.configuration = configuration - self.conn = None - self.conn_params = dict() - self.server_version = None - self.is_superuser = False - self.alive = False - self.databases = list() - self.secondaries = list() - self.replication_slots = list() - self.queries = dict() - self.data = dict() - - def reconnect(self): - return self.connect() - - def build_conn_params(self): - conf = self.configuration - - # connection URIs: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING - if conf.get(CONN_PARAM_DSN): - return {'dsn': conf[CONN_PARAM_DSN]} - - params = { - CONN_PARAM_HOST: conf.get(CONN_PARAM_HOST), - CONN_PARAM_PORT: conf.get(CONN_PARAM_PORT, DEFAULT_PORT), - CONN_PARAM_DATABASE: conf.get(CONN_PARAM_DATABASE), - CONN_PARAM_USER: conf.get(CONN_PARAM_USER, DEFAULT_USER), - CONN_PARAM_PASSWORD: conf.get(CONN_PARAM_PASSWORD), - CONN_PARAM_CONN_TIMEOUT: conf.get(CONN_PARAM_CONN_TIMEOUT, DEFAULT_CONNECT_TIMEOUT), - 'options': '-c statement_timeout={0}'.format( - conf.get(CONN_PARAM_STATEMENT_TIMEOUT, DEFAULT_STATEMENT_TIMEOUT)), - } - - # https://www.postgresql.org/docs/current/libpq-ssl.html - ssl_params = dict( - (k, v) for k, v in { - CONN_PARAM_SSL_MODE: conf.get(CONN_PARAM_SSL_MODE), - CONN_PARAM_SSL_ROOT_CERT: conf.get(CONN_PARAM_SSL_ROOT_CERT), - CONN_PARAM_SSL_CRL: conf.get(CONN_PARAM_SSL_CRL), - CONN_PARAM_SSL_CERT: conf.get(CONN_PARAM_SSL_CERT), - CONN_PARAM_SSL_KEY: conf.get(CONN_PARAM_SSL_KEY), - }.items() if v) - - if CONN_PARAM_SSL_MODE not in ssl_params and len(ssl_params) > 0: - raise ValueError("mandatory 'sslmode' param is missing, please set") - - params.update(ssl_params) - - return params - - def connect(self): - if self.conn: - self.conn.close() - self.conn = None - - try: - self.conn = psycopg2.connect(**self.conn_params) - self.conn.set_isolation_level(extensions.ISOLATION_LEVEL_AUTOCOMMIT) - self.conn.set_session(readonly=True) - except OperationalError as error: - self.error(error) - self.alive = False - else: - self.alive = True - - return self.alive - - def check(self): - if not PSYCOPG2: - self.error("'python-psycopg2' package is needed to use postgres module") - return False - - try: - self.conn_params = self.build_conn_params() - except ValueError as error: - self.error('error on creating connection params : {0}', error) - return False - - if not self.connect(): - self.error('failed to connect to {0}'.format(hide_password(self.conn_params))) - return False - - try: - self.check_queries() - except Exception as error: - self.error(error) - return False - - self.populate_queries() - self.create_dynamic_charts() - - return True - - def get_data(self): - if not self.alive and not self.reconnect(): - return None - - self.data = dict() - try: - cursor = self.conn.cursor(cursor_factory=DictCursor) - - self.data.update(zero_lock_types(self.databases)) - - for query, metrics in self.queries.items(): - self.query_stats(cursor, query, metrics) - - except OperationalError: - self.alive = False - return None - - cursor.close() - - return self.data - - def query_stats(self, cursor, query, metrics): - cursor.execute(query, dict(databases=tuple(self.databases))) - - for row in cursor: - for metric in metrics: - # databases - if 'database_name' in row: - dimension_id = '_'.join([row['database_name'], metric]) - # secondaries - elif 'application_name' in row: - dimension_id = '_'.join([row['application_name'], metric]) - # replication slots - elif 'slot_name' in row: - dimension_id = '_'.join([row['slot_name'], metric]) - # other - else: - dimension_id = metric - - if metric in row: - if row[metric] is not None: - self.data[dimension_id] = int(row[metric]) - elif 'locks_count' in row: - if metric == row['mode']: - self.data[dimension_id] = row['locks_count'] - - def check_queries(self): - cursor = self.conn.cursor() - - self.server_version = detect_server_version(cursor, query_factory(QUERY_NAME_SERVER_VERSION)) - self.debug('server version: {0}'.format(self.server_version)) - - self.is_superuser = check_if_superuser(cursor, query_factory(QUERY_NAME_IF_SUPERUSER)) - self.debug('superuser: {0}'.format(self.is_superuser)) - - self.databases = discover(cursor, query_factory(QUERY_NAME_DATABASES)) - self.debug('discovered databases {0}'.format(self.databases)) - if self.databases_to_poll: - to_poll = self.databases_to_poll.split() - self.databases = [db for db in self.databases if db in to_poll] or self.databases - - self.secondaries = discover(cursor, query_factory(QUERY_NAME_STANDBY)) - self.debug('discovered secondaries: {0}'.format(self.secondaries)) - - if self.server_version >= 94000: - self.replication_slots = discover(cursor, query_factory(QUERY_NAME_REPLICATION_SLOT)) - self.debug('discovered replication slots: {0}'.format(self.replication_slots)) - - cursor.close() - - def populate_queries(self): - self.queries[query_factory(QUERY_NAME_DATABASE)] = METRICS[QUERY_NAME_DATABASE] - self.queries[query_factory(QUERY_NAME_BACKENDS)] = METRICS[QUERY_NAME_BACKENDS] - self.queries[query_factory(QUERY_NAME_BACKEND_USAGE, self.server_version)] = METRICS[QUERY_NAME_BACKEND_USAGE] - self.queries[query_factory(QUERY_NAME_LOCKS)] = METRICS[QUERY_NAME_LOCKS] - self.queries[query_factory(QUERY_NAME_BGWRITER)] = METRICS[QUERY_NAME_BGWRITER] - self.queries[query_factory(QUERY_NAME_DIFF_LSN, self.server_version)] = METRICS[QUERY_NAME_WAL_WRITES] - self.queries[query_factory(QUERY_NAME_STANDBY_DELTA, self.server_version)] = METRICS[QUERY_NAME_STANDBY_DELTA] - self.queries[query_factory(QUERY_NAME_BLOCKERS, self.server_version)] = METRICS[QUERY_NAME_BLOCKERS] - - if self.do_index_stats: - self.queries[query_factory(QUERY_NAME_INDEX_STATS)] = METRICS[QUERY_NAME_INDEX_STATS] - if self.do_table_stats: - self.queries[query_factory(QUERY_NAME_TABLE_STATS)] = METRICS[QUERY_NAME_TABLE_STATS] - - if self.is_superuser: - self.queries[query_factory(QUERY_NAME_ARCHIVE, self.server_version)] = METRICS[QUERY_NAME_ARCHIVE] - - if self.server_version >= 90400: - self.queries[query_factory(QUERY_NAME_WAL, self.server_version)] = METRICS[QUERY_NAME_WAL] - - if self.server_version >= 100000: - v = METRICS[QUERY_NAME_REPSLOT_FILES] - self.queries[query_factory(QUERY_NAME_REPSLOT_FILES, self.server_version)] = v - - if self.server_version >= 90400: - self.queries[query_factory(QUERY_NAME_AUTOVACUUM)] = METRICS[QUERY_NAME_AUTOVACUUM] - - self.queries[query_factory(QUERY_NAME_FORCED_AUTOVACUUM)] = METRICS[QUERY_NAME_FORCED_AUTOVACUUM] - self.queries[query_factory(QUERY_NAME_TX_WRAPAROUND)] = METRICS[QUERY_NAME_TX_WRAPAROUND] - - if self.server_version >= 100000: - self.queries[query_factory(QUERY_NAME_STANDBY_LAG)] = METRICS[QUERY_NAME_STANDBY_LAG] - - def create_dynamic_charts(self): - for database_name in self.databases[::-1]: - dim = [ - database_name + '_size', - database_name, - 'absolute', - 1, - 1024 * 1024, - ] - self.definitions['database_size']['lines'].append(dim) - for chart_name in [name for name in self.order if name.startswith('db_stat')]: - add_database_stat_chart( - order=self.order, - definitions=self.definitions, - name=chart_name, - database_name=database_name, - ) - add_database_lock_chart( - order=self.order, - definitions=self.definitions, - database_name=database_name, - ) - - for application_name in self.secondaries[::-1]: - add_replication_standby_chart( - order=self.order, - definitions=self.definitions, - name='standby_delta', - application_name=application_name, - chart_family='replication delta', - ) - add_replication_standby_chart( - order=self.order, - definitions=self.definitions, - name='standby_lag', - application_name=application_name, - chart_family='replication lag', - ) - - for slot_name in self.replication_slots[::-1]: - add_replication_slot_chart( - order=self.order, - definitions=self.definitions, - name='replication_slot', - slot_name=slot_name, - ) - - -def discover(cursor, query): - cursor.execute(query) - result = list() - for v in [value[0] for value in cursor]: - if v not in result: - result.append(v) - return result - - -def check_if_superuser(cursor, query): - cursor.execute(query) - return cursor.fetchone()[0] - - -def detect_server_version(cursor, query): - cursor.execute(query) - return int(cursor.fetchone()[0]) - - -def zero_lock_types(databases): - result = dict() - for database in databases: - for lock_type in METRICS['LOCKS']: - key = '_'.join([database, lock_type]) - result[key] = 0 - - return result - - -def hide_password(config): - return dict((k, v if k != 'password' or not v else '*****') for k, v in config.items()) - - -def add_database_lock_chart(order, definitions, database_name): - def create_lines(database): - result = list() - for lock_type in METRICS['LOCKS']: - dimension_id = '_'.join([database, lock_type]) - result.append([dimension_id, lock_type, 'absolute']) - return result - - chart_name = database_name + '_locks' - order.insert(-1, chart_name) - definitions[chart_name] = { - 'options': - [None, 'Locks on db: ' + database_name, 'locks', 'db ' + database_name, 'postgres.db_locks', 'line'], - 'lines': create_lines(database_name) - } - - -def add_database_stat_chart(order, definitions, name, database_name): - def create_lines(database, lines): - result = list() - for line in lines: - new_line = ['_'.join([database, line[0]])] + line[1:] - result.append(new_line) - return result - - chart_template = CHARTS[name] - chart_name = '_'.join([database_name, name]) - order.insert(0, chart_name) - name, title, units, _, context, chart_type = chart_template['options'] - definitions[chart_name] = { - 'options': [name, title + ': ' + database_name, units, 'db ' + database_name, context, chart_type], - 'lines': create_lines(database_name, chart_template['lines'])} - - -def add_replication_standby_chart(order, definitions, name, application_name, chart_family): - def create_lines(standby, lines): - result = list() - for line in lines: - new_line = ['_'.join([standby, line[0]])] + line[1:] - result.append(new_line) - return result - - chart_template = CHARTS[name] - chart_name = '_'.join([application_name, name]) - position = order.index('database_size') - order.insert(position, chart_name) - name, title, units, _, context, chart_type = chart_template['options'] - definitions[chart_name] = { - 'options': [name, title + ': ' + application_name, units, chart_family, context, chart_type], - 'lines': create_lines(application_name, chart_template['lines'])} - - -def add_replication_slot_chart(order, definitions, name, slot_name): - def create_lines(slot, lines): - result = list() - for line in lines: - new_line = ['_'.join([slot, line[0]])] + line[1:] - result.append(new_line) - return result - - chart_template = CHARTS[name] - chart_name = '_'.join([slot_name, name]) - position = order.index('database_size') - order.insert(position, chart_name) - name, title, units, _, context, chart_type = chart_template['options'] - definitions[chart_name] = { - 'options': [name, title + ': ' + slot_name, units, 'replication slot files', context, chart_type], - 'lines': create_lines(slot_name, chart_template['lines'])} diff --git a/collectors/python.d.plugin/postgres/postgres.conf b/collectors/python.d.plugin/postgres/postgres.conf deleted file mode 100644 index 7e354d99b..000000000 --- a/collectors/python.d.plugin/postgres/postgres.conf +++ /dev/null @@ -1,134 +0,0 @@ -# netdata python.d.plugin configuration for postgresql -# -# This file is in YaML format. Generally the format is: -# -# name: value -# -# There are 2 sections: -# - global variables -# - one or more JOBS -# -# JOBS allow you to collect values from multiple sources. -# Each source will have its own set of charts. -# -# JOB parameters have to be indented (using spaces only, example below). - -# ---------------------------------------------------------------------- -# Global Variables -# These variables set the defaults for all JOBs, however each JOB -# may define its own, overriding the defaults. - -# update_every sets the default data collection frequency. -# If unset, the python.d.plugin default is used. -# update_every: 1 - -# priority controls the order of charts at the netdata dashboard. -# Lower numbers move the charts towards the top of the page. -# If unset, the default for python.d.plugin is used. -# priority: 60000 - -# penalty indicates whether to apply penalty to update_every in case of failures. -# Penalty will increase every 5 failed updates in a row. Maximum penalty is 10 minutes. -# penalty: yes - -# autodetection_retry sets the job re-check interval in seconds. -# The job is not deleted if check fails. -# Attempts to start the job are made once every autodetection_retry. -# This feature is disabled by default. -# autodetection_retry: 0 - -# ---------------------------------------------------------------------- -# JOBS (data collection sources) -# -# The default JOBS share the same *name*. JOBS with the same name -# are mutually exclusive. Only one of them will be allowed running at -# any time. This allows autodetection to try several alternatives and -# pick the one that works. -# -# Any number of jobs is supported. -# -# All python.d.plugin JOBS (for all its modules) support a set of -# predefined parameters. These are: -# -# job_name: -# name: myname # the JOB's name as it will appear at the -# # dashboard (by default is the job_name) -# # JOBs sharing a name are mutually exclusive -# update_every: 1 # the JOB's data collection frequency -# priority: 60000 # the JOB's order on the dashboard -# penalty: yes # the JOB's penalty -# autodetection_retry: 0 # the JOB's re-check interval in seconds -# -# A single connection is required in order to pull statistics. -# -# Connections can be configured with the following options: -# -# dsn : 'connection URI' # see https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING -# -# OR -# -# database : 'example_db_name' -# user : 'example_user' -# password : 'example_pass' -# host : 'localhost' -# port : 5432 -# connect_timeout : 2 # in seconds, default is 2 -# statement_timeout : 2000 # in ms, default is 2000 -# sslmode : mode # one of [disable, allow, prefer, require, verify-ca, verify-full] -# sslrootcert : path/to/rootcert # the location of the root certificate file -# sslcrl : path/to/crl # the location of the CRL file -# sslcert : path/to/cert # the location of the client certificate file -# sslkey : path/to/key # the location of the client key file -# -# SSL connection parameters description: https://www.postgresql.org/docs/current/libpq-ssl.html -# -# Additionally, the following options allow selective disabling of charts -# -# table_stats : false -# index_stats : false -# database_poll : 'dbase_name1 dbase_name2' # poll only specified databases (all other will be excluded from charts) -# -# Postgres permissions are configured at its pg_hba.conf file. You can -# "trust" local clients to allow netdata to connect, or you can create -# a postgres user for netdata and add its password below to allow -# netdata connect. -# -# Please note that when running Postgres from inside the container, -# the client (Netdata) is not considered local, unless it runs from inside -# the same container. -# -# Superuser access is needed for these charts: -# Write-Ahead Logs -# Archive Write-Ahead Logs -# -# Autovacuum charts is allowed since Postgres 9.4 -# ---------------------------------------------------------------------- - -socket: - name : 'local' - user : 'postgres' - database : 'postgres' - -tcp: - name : 'local' - database : 'postgres' - user : 'postgres' - password : 'postgres' - host : 'localhost' - port : 5432 - -tcpipv4: - name : 'local' - database : 'postgres' - user : 'postgres' - password : 'postgres' - host : '127.0.0.1' - port : 5432 - -tcpipv6: - name : 'local' - database : 'postgres' - user : 'postgres' - password : 'postgres' - host : '::1' - port : 5432 diff --git a/collectors/python.d.plugin/python.d.conf b/collectors/python.d.plugin/python.d.conf index 72e20fcd3..7b43ee205 100644 --- a/collectors/python.d.plugin/python.d.conf +++ b/collectors/python.d.plugin/python.d.conf @@ -56,14 +56,13 @@ logind: no # memcached: yes # mongodb: yes # monit: yes -# nginx_plus: yes # nvidia_smi: yes # nsd: yes # ntpd: yes # openldap: yes # oracledb: yes +# pandas: yes # postfix: yes -# postgres: yes # proxysql: yes # puppet: yes # rabbitmq: yes diff --git a/collectors/python.d.plugin/python.d.plugin.in b/collectors/python.d.plugin/python.d.plugin.in index c04cb3ff0..681ceb403 100644 --- a/collectors/python.d.plugin/python.d.plugin.in +++ b/collectors/python.d.plugin/python.d.plugin.in @@ -131,7 +131,7 @@ def dirs(): DIRS = dirs() -IS_ATTY = sys.stdout.isatty() +IS_ATTY = sys.stdout.isatty() or sys.stderr.isatty() MODULE_SUFFIX = '.chart.py' @@ -496,7 +496,16 @@ class FileLockRegistry: self.path = path self.locks = dict() + @staticmethod + def rename(name): + # go version name is 'docker' + if name.startswith("dockerd"): + name = "docker" + name[7:] + return name + + def register(self, name): + name = self.rename(name) if name in self.locks: return file = os.path.join(self.path, '{0}.collector.lock'.format(name)) @@ -505,6 +514,7 @@ class FileLockRegistry: self.locks[name] = lock def unregister(self, name): + name = self.rename(name) if name not in self.locks: return lock = self.locks[name] @@ -893,6 +903,11 @@ def main(): registry, ) + # cheap attempt to reduce chance of python.d job running before go.d + # TODO: better implementation needed + if not IS_ATTY: + time.sleep(1.5) + try: if not p.setup(): return diff --git a/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SimpleService.py b/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SimpleService.py index ed1b2e669..a7acc23b6 100644 --- a/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SimpleService.py +++ b/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SimpleService.py @@ -4,14 +4,13 @@ # Author: Ilya Mashchenko (ilyam8) # SPDX-License-Identifier: GPL-3.0-or-later - -from time import sleep, time - -from third_party.monotonic import monotonic +import os from bases.charts import Charts, ChartError, create_runtime_chart from bases.collection import safe_print from bases.loggers import PythonDLimitedLogger +from third_party.monotonic import monotonic +from time import sleep, time RUNTIME_CHART_UPDATE = 'BEGIN netdata.runtime_{job_name} {since_last}\n' \ 'SET run_time = {elapsed}\n' \ @@ -20,6 +19,8 @@ RUNTIME_CHART_UPDATE = 'BEGIN netdata.runtime_{job_name} {since_last}\n' \ PENALTY_EVERY = 5 MAX_PENALTY = 10 * 60 # 10 minutes +ND_INTERNAL_MONITORING_DISABLED = os.getenv("NETDATA_INTERNALS_MONITORING") == "NO" + class RuntimeCounters: def __init__(self, configuration): @@ -79,11 +80,13 @@ class SimpleService(PythonDLimitedLogger, object): self.module_name = clean_module_name(self.__module__) self.job_name = configuration.pop('job_name') + self.actual_job_name = self.job_name or self.module_name self.override_name = configuration.pop('override_name') self.fake_name = None self._runtime_counters = RuntimeCounters(configuration=configuration) self.charts = Charts(job_name=self.actual_name, + actual_job_name=self.actual_job_name, priority=configuration.pop('priority'), cleanup=configuration.pop('chart_cleanup'), get_update_every=self.get_update_every, @@ -208,9 +211,10 @@ class SimpleService(PythonDLimitedLogger, object): job.elapsed = int((monotonic() - job.start_mono) * 1e3) job.prev_update = job.start_real job.retries, job.penalty = 0, 0 - safe_print(RUNTIME_CHART_UPDATE.format(job_name=self.name, - since_last=since, - elapsed=job.elapsed)) + if not ND_INTERNAL_MONITORING_DISABLED: + safe_print(RUNTIME_CHART_UPDATE.format(job_name=self.name, + since_last=since, + elapsed=job.elapsed)) self.debug('update => [{status}] (elapsed time: {elapsed}, failed retries in a row: {retries})'.format( status='OK' if updated else 'FAILED', elapsed=job.elapsed if updated else '-', diff --git a/collectors/python.d.plugin/python_modules/bases/charts.py b/collectors/python.d.plugin/python_modules/bases/charts.py index 54986a937..203ad1672 100644 --- a/collectors/python.d.plugin/python_modules/bases/charts.py +++ b/collectors/python.d.plugin/python_modules/bases/charts.py @@ -3,6 +3,8 @@ # Author: Ilya Mashchenko (ilyam8) # SPDX-License-Identifier: GPL-3.0-or-later +import os + from bases.collection import safe_print CHART_PARAMS = ['type', 'id', 'name', 'title', 'units', 'family', 'context', 'chart_type', 'hidden'] @@ -18,15 +20,24 @@ CHART_CREATE = "CHART {type}.{id} '{name}' '{title}' '{units}' '{family}' '{cont CHART_OBSOLETE = "CHART {type}.{id} '{name}' '{title}' '{units}' '{family}' '{context}' " \ "{chart_type} {priority} {update_every} '{hidden} obsolete'\n" +CLABEL_COLLECT_JOB = "CLABEL '_collect_job' '{actual_job_name}' '0'\n" +CLABEL_COMMIT = "CLABEL_COMMIT\n" + DIMENSION_CREATE = "DIMENSION '{id}' '{name}' {algorithm} {multiplier} {divisor} '{hidden} {obsolete}'\n" DIMENSION_SET = "SET '{id}' = {value}\n" CHART_VARIABLE_SET = "VARIABLE CHART '{id}' = {value}\n" +# 1 is label source auto +# https://github.com/netdata/netdata/blob/cc2586de697702f86a3c34e60e23652dd4ddcb42/database/rrd.h#L205 RUNTIME_CHART_CREATE = "CHART netdata.runtime_{job_name} '' 'Execution time' 'ms' 'python.d' " \ "netdata.pythond_runtime line 145000 {update_every} '' 'python.d.plugin' '{module_name}'\n" \ + "CLABEL '_collect_job' '{actual_job_name}' '1'\n" \ + "CLABEL_COMMIT\n" \ "DIMENSION run_time 'run time' absolute 1 1\n" +ND_INTERNAL_MONITORING_DISABLED = os.getenv("NETDATA_INTERNALS_MONITORING") == "NO" + def create_runtime_chart(func): """ @@ -42,12 +53,14 @@ def create_runtime_chart(func): def wrapper(*args, **kwargs): self = args[0] - chart = RUNTIME_CHART_CREATE.format( - job_name=self.name, - update_every=self._runtime_counters.update_every, - module_name=self.module_name, - ) - safe_print(chart) + if not ND_INTERNAL_MONITORING_DISABLED: + chart = RUNTIME_CHART_CREATE.format( + job_name=self.name, + actual_job_name=self.actual_job_name, + update_every=self._runtime_counters.update_every, + module_name=self.module_name, + ) + safe_print(chart) ok = func(*args, **kwargs) return ok @@ -77,13 +90,14 @@ class Charts: Chart is a instance of Chart class. Charts adding must be done using Charts.add_chart() method only""" - def __init__(self, job_name, priority, cleanup, get_update_every, module_name): + def __init__(self, job_name, actual_job_name, priority, cleanup, get_update_every, module_name): """ :param job_name: <bound method> :param priority: <int> :param get_update_every: <bound method> """ self.job_name = job_name + self.actual_job_name = actual_job_name self.priority = priority self.cleanup = cleanup self.get_update_every = get_update_every @@ -131,6 +145,7 @@ class Charts: new_chart.params['update_every'] = self.get_update_every() new_chart.params['priority'] = self.priority new_chart.params['module_name'] = self.module_name + new_chart.params['actual_job_name'] = self.actual_job_name self.priority += 1 self.charts[new_chart.id] = new_chart @@ -230,13 +245,14 @@ class Chart: :return: """ chart = CHART_CREATE.format(**self.params) + labels = CLABEL_COLLECT_JOB.format(**self.params) + CLABEL_COMMIT dimensions = ''.join([dimension.create() for dimension in self.dimensions]) variables = ''.join([var.set(var.value) for var in self.variables if var]) self.flags.push = False self.flags.created = True - safe_print(chart + dimensions + variables) + safe_print(chart + labels + dimensions + variables) def can_be_updated(self, data): for dim in self.dimensions: diff --git a/collectors/python.d.plugin/rabbitmq/README.md b/collectors/python.d.plugin/rabbitmq/README.md index 607e32c7f..927adcc68 100644 --- a/collectors/python.d.plugin/rabbitmq/README.md +++ b/collectors/python.d.plugin/rabbitmq/README.md @@ -113,4 +113,26 @@ socket: --- +### Per-Queue Chart configuration +RabbitMQ users with the "monitoring" tag cannot see all queue data. You'll need a user with read permissions. +To create a dedicated user for netdata: + +```bash +rabbitmqctl add_user netdata ChangeThisSuperSecretPassword +rabbitmqctl set_permissions netdata "^$" "^$" ".*" +``` + +See [set_permissions](https://www.rabbitmq.com/rabbitmqctl.8.html#set_permissions) for details. + +Once the user is set up, add `collect_queues_metrics: yes` to your `rabbitmq.conf`: + +```yaml +local: + name : 'local' + host : '127.0.0.1' + port : 15672 + user : 'netdata' + pass : 'ChangeThisSuperSecretPassword' + collect_queues_metrics : 'yes' +``` diff --git a/collectors/python.d.plugin/sensors/README.md b/collectors/python.d.plugin/sensors/README.md index 149589317..e791195d4 100644 --- a/collectors/python.d.plugin/sensors/README.md +++ b/collectors/python.d.plugin/sensors/README.md @@ -26,6 +26,8 @@ There have been reports from users that on certain servers, ACPI ring buffer err We are tracking such cases in issue [#827](https://github.com/netdata/netdata/issues/827). Please join this discussion for help. +When `lm-sensors` doesn't work on your device (e.g. for RPi temperatures), use [the legacy bash collector](https://learn.netdata.cloud/docs/agent/collectors/charts.d.plugin/sensors) + --- diff --git a/collectors/python.d.plugin/sensors/sensors.chart.py b/collectors/python.d.plugin/sensors/sensors.chart.py index f089e147a..701bf6414 100644 --- a/collectors/python.d.plugin/sensors/sensors.chart.py +++ b/collectors/python.d.plugin/sensors/sensors.chart.py @@ -3,6 +3,8 @@ # Author: Pawel Krupa (paulfantom) # SPDX-License-Identifier: GPL-3.0-or-later +from collections import defaultdict + from bases.FrameworkServices.SimpleService import SimpleService from third_party import lm_sensors as sensors @@ -77,11 +79,11 @@ TYPE_MAP = { 4: 'energy', 5: 'current', 6: 'humidity', - 7: 'max_main', - 16: 'vid', - 17: 'intrusion', - 18: 'max_other', - 24: 'beep_enable' + # 7: 'max_main', + # 16: 'vid', + # 17: 'intrusion', + # 18: 'max_other', + # 24: 'beep_enable' } @@ -91,64 +93,73 @@ class Service(SimpleService): self.order = list() self.definitions = dict() self.chips = configuration.get('chips') + self.priority = 60000 def get_data(self): - data = dict() + seen, data = dict(), dict() try: for chip in sensors.ChipIterator(): - prefix = sensors.chip_snprintf_name(chip) - for feature in sensors.FeatureIterator(chip): - sfi = sensors.SubFeatureIterator(chip, feature) - val = None - for sf in sfi: - try: - val = sensors.get_value(chip, sf.number) - break - except sensors.SensorsError: - continue - if val is None: + chip_name = sensors.chip_snprintf_name(chip) + seen[chip_name] = defaultdict(list) + + for feat in sensors.FeatureIterator(chip): + if feat.type not in TYPE_MAP: + continue + + feat_type = TYPE_MAP[feat.type] + feat_name = str(feat.name.decode()) + feat_label = sensors.get_label(chip, feat) + feat_limits = LIMITS.get(feat_type) + sub_feat = next(sensors.SubFeatureIterator(chip, feat)) # current value + + if not sub_feat: + continue + + try: + v = sensors.get_value(chip, sub_feat.number) + except sensors.SensorsError: + continue + + if v is None: + continue + + seen[chip_name][feat_type].append((feat_name, feat_label)) + + if feat_limits and (v < feat_limits[0] or v > feat_limits[1]): continue - type_name = TYPE_MAP[feature.type] - if type_name in LIMITS: - limit = LIMITS[type_name] - if val < limit[0] or val > limit[1]: - continue - data[prefix + '_' + str(feature.name.decode())] = int(val * 1000) + + data[chip_name + '_' + feat_name] = int(v * 1000) + except sensors.SensorsError as error: self.error(error) return None + self.update_sensors_charts(seen) + return data or None - def create_definitions(self): - for sensor in ORDER: - for chip in sensors.ChipIterator(): - chip_name = sensors.chip_snprintf_name(chip) - if self.chips and not any([chip_name.startswith(ex) for ex in self.chips]): + def update_sensors_charts(self, seen): + for chip_name, feat in seen.items(): + if self.chips and not any([chip_name.startswith(ex) for ex in self.chips]): + continue + + for feat_type, sub_feat in feat.items(): + if feat_type not in ORDER or feat_type not in CHARTS: + continue + + chart_id = '{}_{}'.format(chip_name, feat_type) + if chart_id in self.charts: continue - for feature in sensors.FeatureIterator(chip): - sfi = sensors.SubFeatureIterator(chip, feature) - vals = list() - for sf in sfi: - try: - vals.append(sensors.get_value(chip, sf.number)) - except sensors.SensorsError as error: - self.error('{0}: {1}'.format(sf.name, error)) - continue - if not vals or (vals[0] == 0 and feature.type != 1): - continue - if TYPE_MAP[feature.type] == sensor: - # create chart - name = chip_name + '_' + TYPE_MAP[feature.type] - if name not in self.order: - self.order.append(name) - chart_def = list(CHARTS[sensor]['options']) - self.definitions[name] = {'options': chart_def} - self.definitions[name]['lines'] = [] - line = list(CHARTS[sensor]['lines'][0]) - line[0] = chip_name + '_' + str(feature.name.decode()) - line[1] = sensors.get_label(chip, feature) - self.definitions[name]['lines'].append(line) + + params = [chart_id] + list(CHARTS[feat_type]['options']) + new_chart = self.charts.add_chart(params) + new_chart.params['priority'] = self.get_chart_priority(feat_type) + + for name, label in sub_feat: + lines = list(CHARTS[feat_type]['lines'][0]) + lines[0] = chip_name + '_' + name + lines[1] = label + new_chart.add_dimension(lines) def check(self): try: @@ -157,6 +168,12 @@ class Service(SimpleService): self.error(error) return False - self.create_definitions() + self.priority = self.charts.priority + + return bool(self.get_data() and self.charts) - return bool(self.get_data()) + def get_chart_priority(self, feat_type): + for i, v in enumerate(ORDER): + if v == feat_type: + return self.priority + i + return self.priority diff --git a/collectors/python.d.plugin/tor/README.md b/collectors/python.d.plugin/tor/README.md index 3e7b8997a..b57d77c08 100644 --- a/collectors/python.d.plugin/tor/README.md +++ b/collectors/python.d.plugin/tor/README.md @@ -41,10 +41,12 @@ priority : 60000 local_tcp: name: 'local' control_port: 9051 + password: <password> # if required local_socket: name: 'local' control_port: '/var/run/tor/control' + password: <password> # if required ``` ### prerequisite diff --git a/collectors/python.d.plugin/tor/tor.conf b/collectors/python.d.plugin/tor/tor.conf index 91b517a62..bf09b21fe 100644 --- a/collectors/python.d.plugin/tor/tor.conf +++ b/collectors/python.d.plugin/tor/tor.conf @@ -71,7 +71,9 @@ # local_tcp: # name: 'local' # control_port: 9051 +# password: <password> # # local_socket: # name: 'local' # control_port: '/var/run/tor/control' +# password: <password> diff --git a/collectors/statsd.plugin/statsd.c b/collectors/statsd.plugin/statsd.c index fef4206bc..67d7ed2e2 100644 --- a/collectors/statsd.plugin/statsd.c +++ b/collectors/statsd.plugin/statsd.c @@ -20,15 +20,10 @@ // -------------------------------------------------------------------------------------- -// #define STATSD_MULTITHREADED 1 - -#ifdef STATSD_MULTITHREADED // DO NOT ENABLE MULTITHREADING - IT IS NOT WELL TESTED -#define STATSD_DICTIONARY_OPTIONS DICTIONARY_FLAG_DONT_OVERWRITE_VALUE|DICTIONARY_FLAG_ADD_IN_FRONT -#else -#define STATSD_DICTIONARY_OPTIONS DICTIONARY_FLAG_DONT_OVERWRITE_VALUE|DICTIONARY_FLAG_ADD_IN_FRONT|DICTIONARY_FLAG_SINGLE_THREADED -#endif +// #define STATSD_MULTITHREADED 1 +#define STATSD_DICTIONARY_OPTIONS (DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_ADD_IN_FRONT) #define STATSD_DECIMAL_DETAIL 1000 // floating point values get multiplied by this, with the same divisor // -------------------------------------------------------------------------------------------------------------------- @@ -101,6 +96,7 @@ typedef enum statsd_metric_options { STATSD_METRIC_OPTION_CHECKED = 0x00000040, // set when the charting thread checks this metric for use in charts (its usefulness) STATSD_METRIC_OPTION_USEFUL = 0x00000080, // set when the charting thread finds the metric useful (i.e. used in a chart) STATSD_METRIC_OPTION_COLLECTION_FULL_LOGGED = 0x00000100, // set when the collection is full for this metric + STATSD_METRIC_OPTION_UPDATED_CHART_METADATA = 0x00000200, // set when the private chart metadata have been updated via tags } STATS_METRIC_OPTIONS; typedef enum statsd_metric_type { @@ -192,6 +188,7 @@ typedef struct statsd_app_chart_dimension { collected_number multiplier; // the multiplier of the dimension collected_number divisor; // the divisor of the dimension RRDDIM_FLAGS flags; // the RRDDIM flags for this dimension + RRDDIM_OPTIONS options; // the RRDDIM options for this dimension STATSD_APP_CHART_DIM_VALUE_TYPE value_type; // which value to use of the source metric @@ -371,9 +368,10 @@ static struct statsd { // -------------------------------------------------------------------------------------------------------------------- // statsd index management - add/find metrics -static void dictionary_metric_insert_callback(const char *name, void *value, void *data) { +static void dictionary_metric_insert_callback(const DICTIONARY_ITEM *item, void *value, void *data) { STATSD_INDEX *index = (STATSD_INDEX *)data; STATSD_METRIC *m = (STATSD_METRIC *)value; + const char *name = dictionary_acquired_item_name(item); debug(D_STATSD, "Creating new %s metric '%s'", index->name, name); @@ -390,9 +388,9 @@ static void dictionary_metric_insert_callback(const char *name, void *value, voi __atomic_fetch_add(&index->metrics, 1, __ATOMIC_RELAXED); } -static void dictionary_metric_delete_callback(const char *name, void *value, void *data) { +static void dictionary_metric_delete_callback(const DICTIONARY_ITEM *item, void *value, void *data) { (void)data; // STATSD_INDEX *index = (STATSD_INDEX *)data; - (void)name; + (void)item; STATSD_METRIC *m = (STATSD_METRIC *)value; if(m->type == STATSD_METRIC_TYPE_HISTOGRAM || m->type == STATSD_METRIC_TYPE_TIMER) { @@ -416,7 +414,7 @@ static inline STATSD_METRIC *statsd_find_or_add_metric(STATSD_INDEX *index, cons // no locks here, go faster // this will call the dictionary_metric_insert_callback() if an item // is inserted, otherwise it will return the existing one. - // We used the flag DICTIONARY_FLAG_DONT_OVERWRITE_VALUE to support this. + // We used the flag DICT_OPTION_DONT_OVERWRITE_VALUE to support this. STATSD_METRIC *m = dictionary_set(index->dict, name, NULL, sizeof(STATSD_METRIC)); #endif @@ -572,8 +570,8 @@ static inline void statsd_process_histogram_or_timer(STATSD_METRIC *m, const cha #define statsd_process_timer(m, value, sampling) statsd_process_histogram_or_timer(m, value, sampling, "timer") #define statsd_process_histogram(m, value, sampling) statsd_process_histogram_or_timer(m, value, sampling, "histogram") -static void dictionary_metric_set_value_insert_callback(const char *name, void *value, void *data) { - (void)name; +static void dictionary_metric_set_value_insert_callback(const DICTIONARY_ITEM *item, void *value, void *data) { + (void)item; (void)value; STATSD_METRIC *m = (STATSD_METRIC *)data; m->set.unique++; @@ -617,8 +615,8 @@ static inline void statsd_process_set(STATSD_METRIC *m, const char *value) { } } -static void dictionary_metric_dict_value_insert_callback(const char *name, void *value, void *data) { - (void)name; +static void dictionary_metric_dict_value_insert_callback(const DICTIONARY_ITEM *item, void *value, void *data) { + (void)item; (void)value; STATSD_METRIC *m = (STATSD_METRIC *)data; m->dictionary.unique++; @@ -772,14 +770,20 @@ static void statsd_process_metric(const char *name, const char *value, const cha statsd_parse_field_trim(tagvalue, tagvalue_end); if(tagkey && *tagkey && tagvalue && *tagvalue) { - if (!m->units && strcmp(tagkey, "units") == 0) + if (strcmp(tagkey, "units") == 0 && (!m->units || strcmp(m->units, tagvalue) != 0)) { m->units = strdupz(tagvalue); + m->options |= STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + } - if (!m->dimname && strcmp(tagkey, "name") == 0) + if (strcmp(tagkey, "name") == 0 && (!m->dimname || strcmp(m->dimname, tagvalue) != 0)) { m->dimname = strdupz(tagvalue); + m->options |= STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + } - if (!m->family && strcmp(tagkey, "family") == 0) + if (strcmp(tagkey, "family") == 0 && (!m->family || strcmp(m->family, tagvalue) != 0)) { m->family = strdupz(tagvalue); + m->options |= STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + } } } } @@ -1209,6 +1213,7 @@ static STATSD_APP_CHART_DIM *add_dimension_to_app_chart( , collected_number multiplier , collected_number divisor , RRDDIM_FLAGS flags + , RRDDIM_OPTIONS options , STATSD_APP_CHART_DIM_VALUE_TYPE value_type ) { STATSD_APP_CHART_DIM *dim = callocz(sizeof(STATSD_APP_CHART_DIM), 1); @@ -1221,6 +1226,7 @@ static STATSD_APP_CHART_DIM *add_dimension_to_app_chart( dim->divisor = divisor; dim->value_type = value_type; dim->flags = flags; + dim->options = options; if(!dim->multiplier) dim->multiplier = 1; @@ -1323,7 +1329,7 @@ static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHA else if(app) { if(!strcmp(s, "dictionary")) { if(!app->dict) - app->dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + app->dict = dictionary_create(DICT_OPTION_SINGLE_THREADED); dict = app->dict; } @@ -1417,7 +1423,10 @@ static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHA app->default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED; } else if (!strcmp(name, "memory mode")) { - app->rrd_memory_mode = rrd_memory_mode_id(value); + // this is not supported anymore + // with the implementation of storage engines, all charts have the same storage engine always + // app->rrd_memory_mode = rrd_memory_mode_id(value); + ; } else if (!strcmp(name, "history")) { app->rrd_history_entries = atol(value); @@ -1462,29 +1471,30 @@ static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHA } else if (!strcmp(name, "dimension")) { // metric [name [type [multiplier [divisor]]]] - char *words[10]; - pluginsd_split_words(value, words, 10, NULL, NULL, 0); + char *words[10] = { NULL }; + size_t num_words = pluginsd_split_words(value, words, 10, NULL, NULL, 0); int pattern = 0; size_t i = 0; - char *metric_name = words[i++]; + char *metric_name = get_word(words, num_words, i++); if(strcmp(metric_name, "pattern") == 0) { - metric_name = words[i++]; + metric_name = get_word(words, num_words, i++); pattern = 1; } - char *dim_name = words[i++]; - char *type = words[i++]; - char *multiplier = words[i++]; - char *divisor = words[i++]; - char *options = words[i++]; + char *dim_name = get_word(words, num_words, i++); + char *type = get_word(words, num_words, i++); + char *multiplier = get_word(words, num_words, i++); + char *divisor = get_word(words, num_words, i++); + char *opts = get_word(words, num_words, i++); RRDDIM_FLAGS flags = RRDDIM_FLAG_NONE; - if(options && *options) { - if(strstr(options, "hidden") != NULL) flags |= RRDDIM_FLAG_HIDDEN; - if(strstr(options, "noreset") != NULL) flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS; - if(strstr(options, "nooverflow") != NULL) flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS; + RRDDIM_OPTIONS options = RRDDIM_OPTION_NONE; + if(opts && *opts) { + if(strstr(opts, "hidden") != NULL) options |= RRDDIM_OPTION_HIDDEN; + if(strstr(opts, "noreset") != NULL) options |= RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS; + if(strstr(opts, "nooverflow") != NULL) options |= RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS; } if(!pattern) { @@ -1510,7 +1520,8 @@ static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHA , (multiplier && *multiplier)?str2l(multiplier):1 , (divisor && *divisor)?str2l(divisor):1 , flags - , string2valuetype(type, line, filename) + , + options, string2valuetype(type, line, filename) ); if(pattern) @@ -1600,7 +1611,9 @@ static inline RRDSET *statsd_private_rrdset_create( , int update_every , RRDSET_TYPE chart_type ) { - statsd.private_charts++; + if(!m->st) + statsd.private_charts++; + RRDSET *st = rrdset_create_custom( localhost // host , type // type @@ -1630,7 +1643,9 @@ static inline RRDSET *statsd_private_rrdset_create( static inline void statsd_private_chart_gauge(STATSD_METRIC *m) { debug(D_STATSD, "updating private chart for gauge metric '%s'", m->name); - if(unlikely(!m->st)) { + if(unlikely(!m->st || m->options & STATSD_METRIC_OPTION_UPDATED_CHART_METADATA)) { + m->options &= ~STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; statsd_get_metric_type_and_id(m, type, id, context, "gauge", RRD_ID_LENGTH_MAX); @@ -1656,7 +1671,6 @@ static inline void statsd_private_chart_gauge(STATSD_METRIC *m) { if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT) m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(m->st); rrddim_set_by_pointer(m->st, m->rd_value, m->last); @@ -1669,7 +1683,9 @@ static inline void statsd_private_chart_gauge(STATSD_METRIC *m) { static inline void statsd_private_chart_counter_or_meter(STATSD_METRIC *m, const char *dim, const char *family) { debug(D_STATSD, "updating private chart for %s metric '%s'", dim, m->name); - if(unlikely(!m->st)) { + if(unlikely(!m->st || m->options & STATSD_METRIC_OPTION_UPDATED_CHART_METADATA)) { + m->options &= ~STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; statsd_get_metric_type_and_id(m, type, id, context, dim, RRD_ID_LENGTH_MAX); @@ -1695,7 +1711,6 @@ static inline void statsd_private_chart_counter_or_meter(STATSD_METRIC *m, const if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT) m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(m->st); rrddim_set_by_pointer(m->st, m->rd_value, m->last); @@ -1708,7 +1723,9 @@ static inline void statsd_private_chart_counter_or_meter(STATSD_METRIC *m, const static inline void statsd_private_chart_set(STATSD_METRIC *m) { debug(D_STATSD, "updating private chart for set metric '%s'", m->name); - if(unlikely(!m->st)) { + if(unlikely(!m->st || m->options & STATSD_METRIC_OPTION_UPDATED_CHART_METADATA)) { + m->options &= ~STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; statsd_get_metric_type_and_id(m, type, id, context, "set", RRD_ID_LENGTH_MAX); @@ -1734,7 +1751,6 @@ static inline void statsd_private_chart_set(STATSD_METRIC *m) { if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT) m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(m->st); rrddim_set_by_pointer(m->st, m->rd_value, m->last); @@ -1747,7 +1763,9 @@ static inline void statsd_private_chart_set(STATSD_METRIC *m) { static inline void statsd_private_chart_dictionary(STATSD_METRIC *m) { debug(D_STATSD, "updating private chart for dictionary metric '%s'", m->name); - if(unlikely(!m->st)) { + if(unlikely(!m->st || m->options & STATSD_METRIC_OPTION_UPDATED_CHART_METADATA)) { + m->options &= ~STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; statsd_get_metric_type_and_id(m, type, id, context, "dictionary", RRD_ID_LENGTH_MAX); @@ -1771,11 +1789,10 @@ static inline void statsd_private_chart_dictionary(STATSD_METRIC *m) { if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT) m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(m->st); STATSD_METRIC_DICTIONARY_ITEM *t; dfe_start_read(m->dictionary.dict, t) { - if (!t->rd) t->rd = rrddim_add(m->st, t_name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + if (!t->rd) t->rd = rrddim_add(m->st, t_dfe.name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(m->st, t->rd, (collected_number)t->count); } dfe_done(t); @@ -1789,7 +1806,9 @@ static inline void statsd_private_chart_dictionary(STATSD_METRIC *m) { static inline void statsd_private_chart_timer_or_histogram(STATSD_METRIC *m, const char *dim, const char *family, const char *units) { debug(D_STATSD, "updating private chart for %s metric '%s'", dim, m->name); - if(unlikely(!m->st)) { + if(unlikely(!m->st || m->options & STATSD_METRIC_OPTION_UPDATED_CHART_METADATA)) { + m->options &= ~STATSD_METRIC_OPTION_UPDATED_CHART_METADATA; + char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; statsd_get_metric_type_and_id(m, type, id, context, dim, RRD_ID_LENGTH_MAX); @@ -1821,7 +1840,6 @@ static inline void statsd_private_chart_timer_or_histogram(STATSD_METRIC *m, con if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT) m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } - else rrdset_next(m->st); rrddim_set_by_pointer(m->st, m->histogram.ext->rd_min, m->histogram.ext->last_min); rrddim_set_by_pointer(m->st, m->histogram.ext->rd_max, m->histogram.ext->last_max); @@ -2130,6 +2148,7 @@ static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC , dim->multiplier , dim->divisor , dim->flags + , dim->options , dim->value_type ); @@ -2186,11 +2205,13 @@ static inline RRDDIM *statsd_add_dim_to_app_chart(STATSD_APP *app, STATSD_APP_CH dim->rd = rrddim_add(chart->st, metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm); if(dim->flags != RRDDIM_FLAG_NONE) dim->rd->flags |= dim->flags; + if(dim->options != RRDDIM_OPTION_NONE) dim->rd->options |= dim->options; return dim->rd; } dim->rd = rrddim_add(chart->st, dim->metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm); if(dim->flags != RRDDIM_FLAG_NONE) dim->rd->flags |= dim->flags; + if(dim->options != RRDDIM_OPTION_NONE) dim->rd->options |= dim->options; return dim->rd; } @@ -2219,7 +2240,6 @@ static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *ch rrdset_flag_set(chart->st, RRDSET_FLAG_STORE_FIRST); // rrdset_flag_set(chart->st, RRDSET_FLAG_DEBUG); } - else rrdset_next(chart->st); STATSD_APP_CHART_DIM *dim; for(dim = chart->dimensions; dim ;dim = dim->next) { @@ -2228,7 +2248,7 @@ static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *ch 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); + debug(D_STATSD, "updating dimension '%s' (%s) of chart '%s' (%s) for app '%s' with value " COLLECTED_NUMBER_FORMAT, dim->name, rrddim_id(dim->rd), chart->id, rrdset_id(chart->st), app->name, *dim->value_ptr); rrddim_set_by_pointer(chart->st, dim->rd, *dim->value_ptr); } } @@ -2523,173 +2543,209 @@ void *statsd_main(void *ptr) { // ---------------------------------------------------------------------------------------------------------------- // statsd monitoring charts - RRDSET *st_metrics = rrdset_create_localhost( - "netdata" - , "statsd_metrics" - , NULL - , "statsd" - , NULL - , "Metrics in the netdata statsd database" - , "metrics" - , PLUGIN_STATSD_NAME - , "stats" - , 132010 - , statsd.update_every - , RRDSET_TYPE_STACKED - ); - RRDDIM *rd_metrics_gauge = rrddim_add(st_metrics, "gauges", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_metrics_counter = rrddim_add(st_metrics, "counters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_metrics_timer = rrddim_add(st_metrics, "timers", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_metrics_meter = rrddim_add(st_metrics, "meters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_metrics_histogram = rrddim_add(st_metrics, "histograms", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_metrics_set = rrddim_add(st_metrics, "sets", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_metrics_dictionary= rrddim_add(st_metrics, "dictionaries", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - - RRDSET *st_useful_metrics = rrdset_create_localhost( - "netdata" - , "statsd_useful_metrics" - , NULL - , "statsd" - , NULL - , "Useful metrics in the netdata statsd database" - , "metrics" - , PLUGIN_STATSD_NAME - , "stats" - , 132010 - , statsd.update_every - , RRDSET_TYPE_STACKED - ); - RRDDIM *rd_useful_metrics_gauge = rrddim_add(st_useful_metrics, "gauges", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_useful_metrics_counter = rrddim_add(st_useful_metrics, "counters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_useful_metrics_timer = rrddim_add(st_useful_metrics, "timers", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_useful_metrics_meter = rrddim_add(st_useful_metrics, "meters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_useful_metrics_histogram = rrddim_add(st_useful_metrics, "histograms", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_useful_metrics_set = rrddim_add(st_useful_metrics, "sets", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDDIM *rd_useful_metrics_dictionary= rrddim_add(st_useful_metrics, "dictionaries", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - - RRDSET *st_events = rrdset_create_localhost( - "netdata" - , "statsd_events" - , NULL - , "statsd" - , NULL - , "Events processed by the netdata statsd server" - , "events/s" - , PLUGIN_STATSD_NAME - , "stats" - , 132011 - , statsd.update_every - , RRDSET_TYPE_STACKED - ); - RRDDIM *rd_events_gauge = rrddim_add(st_events, "gauges", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_counter = rrddim_add(st_events, "counters", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_timer = rrddim_add(st_events, "timers", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_meter = rrddim_add(st_events, "meters", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_histogram = rrddim_add(st_events, "histograms", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_set = rrddim_add(st_events, "sets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_dictionary= rrddim_add(st_events, "dictionaries", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_unknown = rrddim_add(st_events, "unknown", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_events_errors = rrddim_add(st_events, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - - RRDSET *st_reads = rrdset_create_localhost( - "netdata" - , "statsd_reads" - , NULL - , "statsd" - , NULL - , "Read operations made by the netdata statsd server" - , "reads/s" - , PLUGIN_STATSD_NAME - , "stats" - , 132012 - , statsd.update_every - , RRDSET_TYPE_STACKED - ); - RRDDIM *rd_reads_tcp = rrddim_add(st_reads, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_reads_udp = rrddim_add(st_reads, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - - RRDSET *st_bytes = rrdset_create_localhost( - "netdata" - , "statsd_bytes" - , NULL - , "statsd" - , NULL - , "Bytes read by the netdata statsd server" - , "kilobits/s" - , PLUGIN_STATSD_NAME - , "stats" - , 132013 - , statsd.update_every - , RRDSET_TYPE_STACKED - ); - RRDDIM *rd_bytes_tcp = rrddim_add(st_bytes, "tcp", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_bytes_udp = rrddim_add(st_bytes, "udp", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - - RRDSET *st_packets = rrdset_create_localhost( - "netdata" - , "statsd_packets" - , NULL - , "statsd" - , NULL - , "Network packets processed by the netdata statsd server" - , "packets/s" - , PLUGIN_STATSD_NAME - , "stats" - , 132014 - , statsd.update_every - , RRDSET_TYPE_STACKED - ); - RRDDIM *rd_packets_tcp = rrddim_add(st_packets, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_packets_udp = rrddim_add(st_packets, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - - RRDSET *st_tcp_connects = rrdset_create_localhost( - "netdata" - , "tcp_connects" - , NULL - , "statsd" - , NULL - , "statsd server TCP connects and disconnects" - , "events" - , PLUGIN_STATSD_NAME - , "stats" - , 132015 - , statsd.update_every - , RRDSET_TYPE_LINE - ); - RRDDIM *rd_tcp_connects = rrddim_add(st_tcp_connects, "connects", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - RRDDIM *rd_tcp_disconnects = rrddim_add(st_tcp_connects, "disconnects", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - - RRDSET *st_tcp_connected = rrdset_create_localhost( - "netdata" - , "tcp_connected" - , NULL - , "statsd" - , NULL - , "statsd server TCP connected sockets" - , "sockets" - , PLUGIN_STATSD_NAME - , "stats" - , 132016 - , statsd.update_every - , RRDSET_TYPE_LINE - ); - RRDDIM *rd_tcp_connected = rrddim_add(st_tcp_connected, "connected", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - - RRDSET *st_pcharts = rrdset_create_localhost( - "netdata" - , "private_charts" - , NULL - , "statsd" - , NULL - , "Private metric charts created by the netdata statsd server" - , "charts" - , PLUGIN_STATSD_NAME - , "stats" - , 132020 - , statsd.update_every - , RRDSET_TYPE_AREA - ); - RRDDIM *rd_pcharts = rrddim_add(st_pcharts, "charts", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + RRDSET *st_metrics = NULL; + RRDDIM *rd_metrics_gauge = NULL; + RRDDIM *rd_metrics_counter = NULL; + RRDDIM *rd_metrics_timer = NULL; + RRDDIM *rd_metrics_meter = NULL; + RRDDIM *rd_metrics_histogram = NULL; + RRDDIM *rd_metrics_set = NULL; + RRDDIM *rd_metrics_dictionary = NULL; + RRDSET *st_useful_metrics = NULL; + RRDDIM *rd_useful_metrics_gauge = NULL; + RRDDIM *rd_useful_metrics_counter = NULL; + RRDDIM *rd_useful_metrics_timer = NULL; + RRDDIM *rd_useful_metrics_meter = NULL; + RRDDIM *rd_useful_metrics_histogram = NULL; + RRDDIM *rd_useful_metrics_set = NULL; + RRDDIM *rd_useful_metrics_dictionary = NULL; + RRDSET *st_events = NULL; + RRDDIM *rd_events_gauge = NULL; + RRDDIM *rd_events_counter = NULL; + RRDDIM *rd_events_timer = NULL; + RRDDIM *rd_events_meter = NULL; + RRDDIM *rd_events_histogram = NULL; + RRDDIM *rd_events_set = NULL; + RRDDIM *rd_events_dictionary = NULL; + RRDDIM *rd_events_unknown = NULL; + RRDDIM *rd_events_errors = NULL; + RRDSET *st_reads = NULL; + RRDDIM *rd_reads_tcp = NULL; + RRDDIM *rd_reads_udp = NULL; + RRDSET *st_bytes = NULL; + RRDDIM *rd_bytes_tcp = NULL; + RRDDIM *rd_bytes_udp = NULL; + RRDSET *st_packets = NULL; + RRDDIM *rd_packets_tcp = NULL; + RRDDIM *rd_packets_udp = NULL; + RRDSET *st_tcp_connects = NULL; + RRDDIM *rd_tcp_connects = NULL; + RRDDIM *rd_tcp_disconnects = NULL; + RRDSET *st_tcp_connected = NULL; + RRDDIM *rd_tcp_connected = NULL; + RRDSET *st_pcharts = NULL; + RRDDIM *rd_pcharts = NULL; + + if(global_statistics_enabled) { + st_metrics = rrdset_create_localhost( + "netdata", + "statsd_metrics", + NULL, + "statsd", + NULL, + "Metrics in the netdata statsd database", + "metrics", + PLUGIN_STATSD_NAME, + "stats", + 132010, + statsd.update_every, + RRDSET_TYPE_STACKED); + rd_metrics_gauge = rrddim_add(st_metrics, "gauges", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_metrics_counter = rrddim_add(st_metrics, "counters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_metrics_timer = rrddim_add(st_metrics, "timers", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_metrics_meter = rrddim_add(st_metrics, "meters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_metrics_histogram = rrddim_add(st_metrics, "histograms", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_metrics_set = rrddim_add(st_metrics, "sets", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_metrics_dictionary = rrddim_add(st_metrics, "dictionaries", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + + st_useful_metrics = rrdset_create_localhost( + "netdata", + "statsd_useful_metrics", + NULL, + "statsd", + NULL, + "Useful metrics in the netdata statsd database", + "metrics", + PLUGIN_STATSD_NAME, + "stats", + 132010, + statsd.update_every, + RRDSET_TYPE_STACKED); + rd_useful_metrics_gauge = rrddim_add(st_useful_metrics, "gauges", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_useful_metrics_counter = rrddim_add(st_useful_metrics, "counters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_useful_metrics_timer = rrddim_add(st_useful_metrics, "timers", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_useful_metrics_meter = rrddim_add(st_useful_metrics, "meters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_useful_metrics_histogram = rrddim_add(st_useful_metrics, "histograms", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_useful_metrics_set = rrddim_add(st_useful_metrics, "sets", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rd_useful_metrics_dictionary = rrddim_add(st_useful_metrics, "dictionaries", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + + st_events = rrdset_create_localhost( + "netdata", + "statsd_events", + NULL, + "statsd", + NULL, + "Events processed by the netdata statsd server", + "events/s", + PLUGIN_STATSD_NAME, + "stats", + 132011, + statsd.update_every, + RRDSET_TYPE_STACKED); + rd_events_gauge = rrddim_add(st_events, "gauges", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_counter = rrddim_add(st_events, "counters", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_timer = rrddim_add(st_events, "timers", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_meter = rrddim_add(st_events, "meters", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_histogram = rrddim_add(st_events, "histograms", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_set = rrddim_add(st_events, "sets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_dictionary = rrddim_add(st_events, "dictionaries", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_unknown = rrddim_add(st_events, "unknown", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_events_errors = rrddim_add(st_events, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + st_reads = rrdset_create_localhost( + "netdata", + "statsd_reads", + NULL, + "statsd", + NULL, + "Read operations made by the netdata statsd server", + "reads/s", + PLUGIN_STATSD_NAME, + "stats", + 132012, + statsd.update_every, + RRDSET_TYPE_STACKED); + rd_reads_tcp = rrddim_add(st_reads, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_reads_udp = rrddim_add(st_reads, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + st_bytes = rrdset_create_localhost( + "netdata", + "statsd_bytes", + NULL, + "statsd", + NULL, + "Bytes read by the netdata statsd server", + "kilobits/s", + PLUGIN_STATSD_NAME, + "stats", + 132013, + statsd.update_every, + RRDSET_TYPE_STACKED); + rd_bytes_tcp = rrddim_add(st_bytes, "tcp", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + rd_bytes_udp = rrddim_add(st_bytes, "udp", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + + st_packets = rrdset_create_localhost( + "netdata", + "statsd_packets", + NULL, + "statsd", + NULL, + "Network packets processed by the netdata statsd server", + "packets/s", + PLUGIN_STATSD_NAME, + "stats", + 132014, + statsd.update_every, + RRDSET_TYPE_STACKED); + rd_packets_tcp = rrddim_add(st_packets, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_packets_udp = rrddim_add(st_packets, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + + st_tcp_connects = rrdset_create_localhost( + "netdata", + "tcp_connects", + NULL, + "statsd", + NULL, + "statsd server TCP connects and disconnects", + "events", + PLUGIN_STATSD_NAME, + "stats", + 132015, + statsd.update_every, + RRDSET_TYPE_LINE); + rd_tcp_connects = rrddim_add(st_tcp_connects, "connects", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_tcp_disconnects = rrddim_add(st_tcp_connects, "disconnects", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + + st_tcp_connected = rrdset_create_localhost( + "netdata", + "tcp_connected", + NULL, + "statsd", + NULL, + "statsd server TCP connected sockets", + "sockets", + PLUGIN_STATSD_NAME, + "stats", + 132016, + statsd.update_every, + RRDSET_TYPE_LINE); + rd_tcp_connected = rrddim_add(st_tcp_connected, "connected", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + + st_pcharts = rrdset_create_localhost( + "netdata", + "private_charts", + NULL, + "statsd", + NULL, + "Private metric charts created by the netdata statsd server", + "charts", + PLUGIN_STATSD_NAME, + "stats", + 132020, + statsd.update_every, + RRDSET_TYPE_AREA); + rd_pcharts = rrddim_add(st_pcharts, "charts", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } // ---------------------------------------------------------------------------------------------------------------- // statsd thread to turn metrics into charts @@ -2699,7 +2755,7 @@ void *statsd_main(void *ptr) { heartbeat_init(&hb); while(!netdata_exit) { worker_is_idle(); - usec_t hb_dt = heartbeat_next(&hb, step); + heartbeat_next(&hb, step); worker_is_busy(WORKER_STATSD_FLUSH_GAUGES); statsd_flush_index_metrics(&statsd.gauges, statsd_flush_gauge); @@ -2728,68 +2784,58 @@ void *statsd_main(void *ptr) { if(unlikely(netdata_exit)) break; - if(likely(hb_dt)) { - rrdset_next(st_metrics); - rrdset_next(st_useful_metrics); - rrdset_next(st_events); - rrdset_next(st_reads); - rrdset_next(st_bytes); - rrdset_next(st_packets); - rrdset_next(st_tcp_connects); - rrdset_next(st_tcp_connected); - rrdset_next(st_pcharts); + if(global_statistics_enabled) { + rrddim_set_by_pointer(st_metrics, rd_metrics_gauge, (collected_number)statsd.gauges.metrics); + rrddim_set_by_pointer(st_metrics, rd_metrics_counter, (collected_number)statsd.counters.metrics); + rrddim_set_by_pointer(st_metrics, rd_metrics_timer, (collected_number)statsd.timers.metrics); + rrddim_set_by_pointer(st_metrics, rd_metrics_meter, (collected_number)statsd.meters.metrics); + rrddim_set_by_pointer(st_metrics, rd_metrics_histogram, (collected_number)statsd.histograms.metrics); + rrddim_set_by_pointer(st_metrics, rd_metrics_set, (collected_number)statsd.sets.metrics); + rrddim_set_by_pointer(st_metrics, rd_metrics_dictionary, (collected_number)statsd.dictionaries.metrics); + rrdset_done(st_metrics); + + rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_gauge, (collected_number)statsd.gauges.useful); + rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_counter, (collected_number)statsd.counters.useful); + rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_timer, (collected_number)statsd.timers.useful); + rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_meter, (collected_number)statsd.meters.useful); + rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_histogram, (collected_number)statsd.histograms.useful); + rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_set, (collected_number)statsd.sets.useful); + rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_dictionary, (collected_number)statsd.dictionaries.useful); + rrdset_done(st_useful_metrics); + + rrddim_set_by_pointer(st_events, rd_events_gauge, (collected_number)statsd.gauges.events); + rrddim_set_by_pointer(st_events, rd_events_counter, (collected_number)statsd.counters.events); + rrddim_set_by_pointer(st_events, rd_events_timer, (collected_number)statsd.timers.events); + rrddim_set_by_pointer(st_events, rd_events_meter, (collected_number)statsd.meters.events); + rrddim_set_by_pointer(st_events, rd_events_histogram, (collected_number)statsd.histograms.events); + rrddim_set_by_pointer(st_events, rd_events_set, (collected_number)statsd.sets.events); + rrddim_set_by_pointer(st_events, rd_events_dictionary, (collected_number)statsd.dictionaries.events); + rrddim_set_by_pointer(st_events, rd_events_unknown, (collected_number)statsd.unknown_types); + rrddim_set_by_pointer(st_events, rd_events_errors, (collected_number)statsd.socket_errors); + rrdset_done(st_events); + + rrddim_set_by_pointer(st_reads, rd_reads_tcp, (collected_number)statsd.tcp_socket_reads); + rrddim_set_by_pointer(st_reads, rd_reads_udp, (collected_number)statsd.udp_socket_reads); + rrdset_done(st_reads); + + rrddim_set_by_pointer(st_bytes, rd_bytes_tcp, (collected_number)statsd.tcp_bytes_read); + rrddim_set_by_pointer(st_bytes, rd_bytes_udp, (collected_number)statsd.udp_bytes_read); + rrdset_done(st_bytes); + + rrddim_set_by_pointer(st_packets, rd_packets_tcp, (collected_number)statsd.tcp_packets_received); + rrddim_set_by_pointer(st_packets, rd_packets_udp, (collected_number)statsd.udp_packets_received); + rrdset_done(st_packets); + + rrddim_set_by_pointer(st_tcp_connects, rd_tcp_connects, (collected_number)statsd.tcp_socket_connects); + rrddim_set_by_pointer(st_tcp_connects, rd_tcp_disconnects, (collected_number)statsd.tcp_socket_disconnects); + rrdset_done(st_tcp_connects); + + rrddim_set_by_pointer(st_tcp_connected, rd_tcp_connected, (collected_number)statsd.tcp_socket_connected); + rrdset_done(st_tcp_connected); + + rrddim_set_by_pointer(st_pcharts, rd_pcharts, (collected_number)statsd.private_charts); + rrdset_done(st_pcharts); } - - rrddim_set_by_pointer(st_metrics, rd_metrics_gauge, (collected_number)statsd.gauges.metrics); - rrddim_set_by_pointer(st_metrics, rd_metrics_counter, (collected_number)statsd.counters.metrics); - rrddim_set_by_pointer(st_metrics, rd_metrics_timer, (collected_number)statsd.timers.metrics); - rrddim_set_by_pointer(st_metrics, rd_metrics_meter, (collected_number)statsd.meters.metrics); - rrddim_set_by_pointer(st_metrics, rd_metrics_histogram, (collected_number)statsd.histograms.metrics); - rrddim_set_by_pointer(st_metrics, rd_metrics_set, (collected_number)statsd.sets.metrics); - rrddim_set_by_pointer(st_metrics, rd_metrics_dictionary, (collected_number)statsd.dictionaries.metrics); - rrdset_done(st_metrics); - - rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_gauge, (collected_number)statsd.gauges.useful); - rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_counter, (collected_number)statsd.counters.useful); - rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_timer, (collected_number)statsd.timers.useful); - rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_meter, (collected_number)statsd.meters.useful); - rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_histogram, (collected_number)statsd.histograms.useful); - rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_set, (collected_number)statsd.sets.useful); - rrddim_set_by_pointer(st_useful_metrics, rd_useful_metrics_dictionary, (collected_number)statsd.dictionaries.useful); - rrdset_done(st_useful_metrics); - - rrddim_set_by_pointer(st_events, rd_events_gauge, (collected_number)statsd.gauges.events); - rrddim_set_by_pointer(st_events, rd_events_counter, (collected_number)statsd.counters.events); - rrddim_set_by_pointer(st_events, rd_events_timer, (collected_number)statsd.timers.events); - rrddim_set_by_pointer(st_events, rd_events_meter, (collected_number)statsd.meters.events); - rrddim_set_by_pointer(st_events, rd_events_histogram, (collected_number)statsd.histograms.events); - rrddim_set_by_pointer(st_events, rd_events_set, (collected_number)statsd.sets.events); - rrddim_set_by_pointer(st_events, rd_events_dictionary, (collected_number)statsd.dictionaries.events); - rrddim_set_by_pointer(st_events, rd_events_unknown, (collected_number)statsd.unknown_types); - rrddim_set_by_pointer(st_events, rd_events_errors, (collected_number)statsd.socket_errors); - rrdset_done(st_events); - - rrddim_set_by_pointer(st_reads, rd_reads_tcp, (collected_number)statsd.tcp_socket_reads); - rrddim_set_by_pointer(st_reads, rd_reads_udp, (collected_number)statsd.udp_socket_reads); - rrdset_done(st_reads); - - rrddim_set_by_pointer(st_bytes, rd_bytes_tcp, (collected_number)statsd.tcp_bytes_read); - rrddim_set_by_pointer(st_bytes, rd_bytes_udp, (collected_number)statsd.udp_bytes_read); - rrdset_done(st_bytes); - - rrddim_set_by_pointer(st_packets, rd_packets_tcp, (collected_number)statsd.tcp_packets_received); - rrddim_set_by_pointer(st_packets, rd_packets_udp, (collected_number)statsd.udp_packets_received); - rrdset_done(st_packets); - - rrddim_set_by_pointer(st_tcp_connects, rd_tcp_connects, (collected_number)statsd.tcp_socket_connects); - rrddim_set_by_pointer(st_tcp_connects, rd_tcp_disconnects, (collected_number)statsd.tcp_socket_disconnects); - rrdset_done(st_tcp_connects); - - rrddim_set_by_pointer(st_tcp_connected, rd_tcp_connected, (collected_number)statsd.tcp_socket_connected); - rrdset_done(st_tcp_connected); - - rrddim_set_by_pointer(st_pcharts, rd_pcharts, (collected_number)statsd.private_charts); - rrdset_done(st_pcharts); } cleanup: ; // added semi-colon to prevent older gcc error: label at end of compound statement diff --git a/collectors/tc.plugin/plugin_tc.c b/collectors/tc.plugin/plugin_tc.c index f012c078d..a2e72ee33 100644 --- a/collectors/tc.plugin/plugin_tc.c +++ b/collectors/tc.plugin/plugin_tc.c @@ -12,60 +12,46 @@ #define TC_LINE_MAX 1024 struct tc_class { - avl_t avl; + STRING *id; + STRING *name; + STRING *leafid; + STRING *parentid; + + bool hasparent; + bool isleaf; + bool isqdisc; + bool render; + bool name_updated; + bool updated; - char *id; - uint32_t hash; - - char *name; - - char *leafid; - uint32_t leaf_hash; - - char *parentid; - uint32_t parent_hash; - - char hasparent; - char isleaf; - char isqdisc; - char render; + int unupdated; // the number of times, this has been found un-updated unsigned long long bytes; unsigned long long packets; unsigned long long dropped; - unsigned long long overlimits; - unsigned long long requeues; - unsigned long long lended; - unsigned long long borrowed; - unsigned long long giants; unsigned long long tokens; unsigned long long ctokens; + //unsigned long long overlimits; + //unsigned long long requeues; + //unsigned long long lended; + //unsigned long long borrowed; + //unsigned long long giants; + RRDDIM *rd_bytes; RRDDIM *rd_packets; RRDDIM *rd_dropped; RRDDIM *rd_tokens; RRDDIM *rd_ctokens; - - char name_updated; - char updated; // updated bytes - int unupdated; // the number of times, this has been found un-updated - - struct tc_class *next; - struct tc_class *prev; }; struct tc_device { - avl_t avl; - - char *id; - uint32_t hash; + STRING *id; + STRING *name; + STRING *family; - char *name; - char *family; - - char name_updated; - char family_updated; + bool name_updated; + bool family_updated; char enabled; char enabled_bytes; @@ -81,94 +67,117 @@ struct tc_device { RRDSET *st_tokens; RRDSET *st_ctokens; - avl_tree_type classes_index; + DICTIONARY *classes; +}; - struct tc_class *classes; - struct tc_class *last_class; - struct tc_device *next; - struct tc_device *prev; -}; +// ---------------------------------------------------------------------------- +// tc_class index + +static void tc_class_free_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) { + // struct tc_device *d = data; + struct tc_class *c = value; + string_freez(c->id); + string_freez(c->name); + string_freez(c->leafid); + string_freez(c->parentid); +} -struct tc_device *tc_device_root = NULL; +static bool tc_class_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) { + struct tc_device *d = data; (void)d; + struct tc_class *c = old_value; (void)c; + struct tc_class *new_c = new_value; (void)new_c; -// ---------------------------------------------------------------------------- -// tc_device index + error("TC: class '%s' is already in device '%s'. Ignoring duplicate.", dictionary_acquired_item_name(item), string2str(d->id)); -static int tc_device_compare(void* a, void* b) { - if(((struct tc_device *)a)->hash < ((struct tc_device *)b)->hash) return -1; - else if(((struct tc_device *)a)->hash > ((struct tc_device *)b)->hash) return 1; - else return strcmp(((struct tc_device *)a)->id, ((struct tc_device *)b)->id); + tc_class_free_callback(item, new_value, data); + + return true; } -avl_tree_type tc_device_root_index = { - NULL, - tc_device_compare -}; +static void tc_class_index_init(struct tc_device *d) { + if(!d->classes) { + d->classes = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_SINGLE_THREADED); + + dictionary_register_delete_callback(d->classes, tc_class_free_callback, d); + dictionary_register_conflict_callback(d->classes, tc_class_conflict_callback, d); + } +} -#define tc_device_index_add(st) (struct tc_device *)avl_insert(&tc_device_root_index, (avl_t *)(st)) -#define tc_device_index_del(st) (struct tc_device *)avl_remove(&tc_device_root_index, (avl_t *)(st)) +static void tc_class_index_destroy(struct tc_device *d) { + dictionary_destroy(d->classes); + d->classes = NULL; +} -static inline struct tc_device *tc_device_index_find(const char *id, uint32_t hash) { - struct tc_device tmp; - tmp.id = (char *)id; - tmp.hash = (hash)?hash:simple_hash(tmp.id); +static struct tc_class *tc_class_index_add(struct tc_device *d, struct tc_class *c) { + return dictionary_set(d->classes, string2str(c->id), c, sizeof(*c)); +} - return (struct tc_device *)avl_search(&(tc_device_root_index), (avl_t *)&tmp); +static void tc_class_index_del(struct tc_device *d, struct tc_class *c) { + dictionary_del(d->classes, string2str(c->id)); } +static inline struct tc_class *tc_class_index_find(struct tc_device *d, const char *id) { + return dictionary_get(d->classes, id); +} // ---------------------------------------------------------------------------- -// tc_class index +// tc_device index -static int tc_class_compare(void* a, void* b) { - if(((struct tc_class *)a)->hash < ((struct tc_class *)b)->hash) return -1; - else if(((struct tc_class *)a)->hash > ((struct tc_class *)b)->hash) return 1; - else return strcmp(((struct tc_class *)a)->id, ((struct tc_class *)b)->id); +static DICTIONARY *tc_device_root_index = NULL; + +static void tc_device_add_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) { + struct tc_device *d = value; + tc_class_index_init(d); } -#define tc_class_index_add(st, rd) (struct tc_class *)avl_insert(&((st)->classes_index), (avl_t *)(rd)) -#define tc_class_index_del(st, rd) (struct tc_class *)avl_remove(&((st)->classes_index), (avl_t *)(rd)) +static void tc_device_free_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) { + struct tc_device *d = value; -static inline struct tc_class *tc_class_index_find(struct tc_device *st, const char *id, uint32_t hash) { - struct tc_class tmp; - tmp.id = (char *)id; - tmp.hash = (hash)?hash:simple_hash(tmp.id); + tc_class_index_destroy(d); - return (struct tc_class *)avl_search(&(st->classes_index), (avl_t *) &tmp); + string_freez(d->id); + string_freez(d->name); + string_freez(d->family); } -// ---------------------------------------------------------------------------- +static void tc_device_index_init() { + if(!tc_device_root_index) { + tc_device_root_index = dictionary_create( + DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_SINGLE_THREADED | DICT_OPTION_ADD_IN_FRONT); -static inline void tc_class_free(struct tc_device *n, struct tc_class *c) { - if(c == n->classes) { - if(likely(c->next)) - n->classes = c->next; - else - n->classes = c->prev; + dictionary_register_insert_callback(tc_device_root_index, tc_device_add_callback, NULL); + dictionary_register_delete_callback(tc_device_root_index, tc_device_free_callback, NULL); } +} - if(c == n->last_class) { - if(unlikely(c->next)) - n->last_class = c->next; - else - n->last_class = c->prev; - } +static void tc_device_index_destroy() { + dictionary_destroy(tc_device_root_index); + tc_device_root_index = NULL; +} - if(c->next) c->next->prev = c->prev; - if(c->prev) c->prev->next = c->next; +static struct tc_device *tc_device_index_add(struct tc_device *d) { + return dictionary_set(tc_device_root_index, string2str(d->id), d, sizeof(*d)); +} - debug(D_TC_LOOP, "Removing from device '%s' class '%s', parentid '%s', leafid '%s', unused=%d", n->id, c->id, c->parentid?c->parentid:"", c->leafid?c->leafid:"", c->unupdated); +//static struct tc_device *tc_device_index_del(struct tc_device *d) { +// dictionary_del(tc_device_root_index, string2str(d->id)); +// return d; +//} - if(unlikely(tc_class_index_del(n, c) != c)) - error("plugin_tc: INTERNAL ERROR: attempt remove class '%s' from device '%s': removed a different calls", c->id, n->id); +static inline struct tc_device *tc_device_index_find(const char *id) { + return dictionary_get(tc_device_root_index, id); +} - freez(c->id); - freez(c->name); - freez(c->leafid); - freez(c->parentid); - freez(c); +// ---------------------------------------------------------------------------- + +static inline void tc_class_free(struct tc_device *n, struct tc_class *c) { + debug(D_TC_LOOP, "Removing from device '%s' class '%s', parentid '%s', leafid '%s', unused=%d", + string2str(n->id), string2str(c->id), string2str(c->parentid), string2str(c->leafid), + c->unupdated); + + tc_class_index_del(n, c); } static inline void tc_device_classes_cleanup(struct tc_device *d) { @@ -179,23 +188,20 @@ static inline void tc_device_classes_cleanup(struct tc_device *d) { if(cleanup_every < 0) cleanup_every = -cleanup_every; } - d->name_updated = 0; - d->family_updated = 0; + d->name_updated = false; + d->family_updated = false; - struct tc_class *c = d->classes; - while(c) { - if(unlikely(cleanup_every && c->unupdated >= cleanup_every)) { - struct tc_class *nc = c->next; + struct tc_class *c; + dfe_start_write(d->classes, c) { + if(unlikely(cleanup_every && c->unupdated >= cleanup_every)) tc_class_free(d, c); - c = nc; - } - else { - c->updated = 0; - c->name_updated = 0; - c = c->next; + else { + c->updated = false; + c->name_updated = false; } } + dfe_done(c); } static inline void tc_device_commit(struct tc_device *d) { @@ -213,26 +219,26 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(d->enabled == (char)-1)) { char var_name[CONFIG_MAX_NAME + 1]; - snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", d->id); + snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", string2str(d->id)); d->enabled = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_new_interfaces); - snprintfz(var_name, CONFIG_MAX_NAME, "traffic chart for %s", d->id); + snprintfz(var_name, CONFIG_MAX_NAME, "traffic chart for %s", string2str(d->id)); d->enabled_bytes = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_bytes); - snprintfz(var_name, CONFIG_MAX_NAME, "packets chart for %s", d->id); + snprintfz(var_name, CONFIG_MAX_NAME, "packets chart for %s", string2str(d->id)); d->enabled_packets = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_packets); - snprintfz(var_name, CONFIG_MAX_NAME, "dropped packets chart for %s", d->id); + snprintfz(var_name, CONFIG_MAX_NAME, "dropped packets chart for %s", string2str(d->id)); d->enabled_dropped = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_dropped); - snprintfz(var_name, CONFIG_MAX_NAME, "tokens chart for %s", d->id); + snprintfz(var_name, CONFIG_MAX_NAME, "tokens chart for %s", string2str(d->id)); d->enabled_tokens = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_tokens); - snprintfz(var_name, CONFIG_MAX_NAME, "ctokens chart for %s", d->id); + snprintfz(var_name, CONFIG_MAX_NAME, "ctokens chart for %s", string2str(d->id)); d->enabled_ctokens = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_ctokens); - snprintfz(var_name, CONFIG_MAX_NAME, "show all classes for %s", d->id); + snprintfz(var_name, CONFIG_MAX_NAME, "show all classes for %s", string2str(d->id)); d->enabled_all_classes_qdiscs = (char)config_get_boolean_ondemand("plugin:tc", var_name, enabled_all_classes_qdiscs); } @@ -244,11 +250,10 @@ static inline void tc_device_commit(struct tc_device *d) { // prepare all classes // we set reasonable defaults for the rest of the code below - for(c = d->classes ; c ; c = c->next) { - c->render = 0; // do not render this class - - c->isleaf = 1; // this is a leaf class - c->hasparent = 0; // without a parent + dfe_start_read(d->classes, c) { + c->render = false; // do not render this class + c->isleaf = true; // this is a leaf class + c->hasparent = false; // without a parent if(unlikely(!c->updated)) c->unupdated++; // increase its unupdated counter @@ -262,21 +267,23 @@ static inline void tc_device_commit(struct tc_device *d) { updated_classes++; } } + dfe_done(c); if(unlikely(!d->enabled || (!updated_classes && !updated_qdiscs))) { - debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. It is not enabled/updated.", d->name?d->name:d->id); + debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. It is not enabled/updated.", string2str(d->name?d->name:d->id)); tc_device_classes_cleanup(d); return; } if(unlikely(updated_classes && updated_qdiscs)) { - error("TC: device '%s' has active both classes (%d) and qdiscs (%d). Will render only qdiscs.", d->id, updated_classes, updated_qdiscs); + error("TC: device '%s' has active both classes (%d) and qdiscs (%d). Will render only qdiscs.", string2str(d->id), updated_classes, updated_qdiscs); // set all classes to !updated - for(c = d->classes ; c ; c = c->next) - if(unlikely(!c->isqdisc && c->updated)) - c->updated = 0; - + dfe_start_read(d->classes, c) { + if (unlikely(!c->isqdisc && c->updated)) + c->updated = false; + } + dfe_done(c); updated_classes = 0; } @@ -296,8 +303,9 @@ static inline void tc_device_commit(struct tc_device *d) { // so, here we remove the isleaf flag from nodes in the middle // and we add the hasparent flag to leaf nodes we found their parent if(likely(!d->enabled_all_classes_qdiscs)) { - for(c = d->classes; c; c = c->next) { - if(unlikely(!c->updated)) continue; + dfe_start_read(d->classes, c) { + if(unlikely(!c->updated)) + continue; //debug(D_TC_LOOP, "TC: In device '%s', %s '%s' has leafid: '%s' and parentid '%s'.", // d->id, @@ -307,30 +315,34 @@ static inline void tc_device_commit(struct tc_device *d) { // c->parentid?c->parentid:"NULL"); // find if c is leaf or not - for(x = d->classes; x; x = x->next) { - if(unlikely(!x->updated || c == x || !x->parentid)) continue; + dfe_start_read(d->classes, x) { + if(unlikely(!x->updated || c == x || !x->parentid)) + continue; // classes have both parentid and leafid // qdiscs have only parentid // the following works for both (it is an OR) - if((c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) || - (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0)) { + if((x->parentid && c->id == x->parentid) || + (c->leafid && x->parentid && c->leafid == x->parentid)) { // debug(D_TC_LOOP, "TC: In device '%s', %s '%s' (leafid: '%s') has as leaf %s '%s' (parentid: '%s').", d->name?d->name:d->id, c->isqdisc?"qdisc":"class", c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->isqdisc?"qdisc":"class", x->name?x->name:x->id, x->parentid?x->parentid:x->id); - c->isleaf = 0; - x->hasparent = 1; + c->isleaf = false; + x->hasparent = true; } } + dfe_done(x); } + dfe_done(c); } - for(c = d->classes ; c ; c = c->next) { - if(unlikely(!c->updated)) continue; + dfe_start_read(d->classes, c) { + if(unlikely(!c->updated)) + continue; // debug(D_TC_LOOP, "TC: device '%s', %s '%s' isleaf=%d, hasparent=%d", d->id, (c->isqdisc)?"qdisc":"class", c->id, c->isleaf, c->hasparent); if(unlikely((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs)) { - c->render = 1; + c->render = true; active_nodes++; bytes_sum += c->bytes; packets_sum += c->packets; @@ -345,26 +357,29 @@ static inline void tc_device_commit(struct tc_device *d) { // debug(D_TC_LOOP, "TC: found root class/qdisc '%s'", root->id); //} } + dfe_done(c); #ifdef NETDATA_INTERNAL_CHECKS // dump all the list to see what we know if(unlikely(debug_flags & D_TC_LOOP)) { - for(c = d->classes ; c ; c = c->next) { - if(c->render) debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, OK", d->name, c->id); - else debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, IGNORE (updated: %d, isleaf: %d, hasparent: %d, parent: %s)", d->name?d->name:d->id, c->id, c->updated, c->isleaf, c->hasparent, c->parentid?c->parentid:"(unset)"); + dfe_start_read(d->classes, c) { + if(c->render) debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, OK", string2str(d->name), string2str(c->id)); + else debug(D_TC_LOOP, "TC: final nodes dump for '%s': class '%s', IGNORE (updated: %d, isleaf: %d, hasparent: %d, parent: '%s')", + string2str(d->name?d->name:d->id), string2str(c->id), c->updated, c->isleaf, c->hasparent, string2str(c->parentid)); } + dfe_done(c); } #endif if(unlikely(!active_nodes)) { - debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No useful classes/qdiscs.", d->name?d->name:d->id); + debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No useful classes/qdiscs.", string2str(d->name?d->name:d->id)); tc_device_classes_cleanup(d); return; } debug(D_TC_LOOP, "TC: evaluating TC device '%s'. enabled = %d/%d (bytes: %d/%d, packets: %d/%d, dropped: %d/%d, tokens: %d/%d, ctokens: %d/%d, all_classes_qdiscs: %d/%d), classes: (bytes = %llu, packets = %llu, dropped = %llu, tokens = %llu, ctokens = %llu).", - d->name?d->name:d->id, + string2str(d->name?d->name:d->id), d->enabled, enable_new_interfaces, d->enabled_bytes, enable_bytes, d->enabled_packets, enable_packets, @@ -383,44 +398,54 @@ static inline void tc_device_commit(struct tc_device *d) { // bytes if(d->enabled_bytes == CONFIG_BOOLEAN_YES || (d->enabled_bytes == CONFIG_BOOLEAN_AUTO && - (bytes_sum || - netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { + (bytes_sum || netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) { d->enabled_bytes = CONFIG_BOOLEAN_YES; - if(unlikely(!d->st_bytes)) + 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" - , PLUGIN_TC_NAME - , NULL - , NETDATA_CHART_PRIO_TC_QOS - , localhost->rrd_update_every - , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED - ); - + RRD_TYPE_TC, + string2str(d->id), + string2str(d->name ? d->name : d->id), + string2str(d->family ? d->family : d->id), + RRD_TYPE_TC ".qos", + "Class Usage", + "kilobits/s", + PLUGIN_TC_NAME, + NULL, + NETDATA_CHART_PRIO_TC_QOS, + localhost->rrd_update_every, + d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED); + + rrdlabels_add(d->st_bytes->rrdlabels, "device", string2str(d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name?d->name:d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family?d->family:d->id), RRDLABEL_SRC_AUTO); + } else { - rrdset_next(d->st_bytes); - if(unlikely(d->name_updated)) rrdset_set_name(d->st_bytes, d->name); + if(unlikely(d->name_updated)) + rrdset_reset_name(d->st_bytes, string2str(d->name)); + + if(d->name && d->name_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name), RRDLABEL_SRC_AUTO); + + if(d->family && d->family_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family), RRDLABEL_SRC_AUTO); // TODO // update the family } - for(c = d->classes ; c ; c = c->next) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_bytes)) - c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + c->rd_bytes = rrddim_add(d->st_bytes, string2str(c->id), string2str(c->name?c->name:c->id), 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_bytes, c->rd_bytes, c->name); + rrddim_reset_name(d->st_bytes, c->rd_bytes, string2str(c->name)); rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes); } + dfe_done(c); + rrdset_done(d->st_bytes); } @@ -435,47 +460,56 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!d->st_packets)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id); - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id); + snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", string2str(d->id)); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", string2str(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" - , PLUGIN_TC_NAME - , NULL - , NETDATA_CHART_PRIO_TC_QOS_PACKETS - , localhost->rrd_update_every - , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED - ); + RRD_TYPE_TC, + id, + name, + string2str(d->family ? d->family : d->id), + RRD_TYPE_TC ".qos_packets", + "Class Packets", + "packets/s", + PLUGIN_TC_NAME, + NULL, + NETDATA_CHART_PRIO_TC_QOS_PACKETS, + localhost->rrd_update_every, + d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED); + + rrdlabels_add(d->st_bytes->rrdlabels, "device", string2str(d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name?d->name:d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family?d->family:d->id), RRDLABEL_SRC_AUTO); } else { - rrdset_next(d->st_packets); - if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id); - rrdset_set_name(d->st_packets, name); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", string2str(d->name?d->name:d->id)); + rrdset_reset_name(d->st_packets, name); } + if(d->name && d->name_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name), RRDLABEL_SRC_AUTO); + + if(d->family && d->family_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family), RRDLABEL_SRC_AUTO); + // TODO // update the family } - for(c = d->classes ; c ; c = c->next) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_packets)) - c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL); + c->rd_packets = rrddim_add(d->st_packets, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_packets, c->rd_packets, c->name); + rrddim_reset_name(d->st_packets, c->rd_packets, string2str(c->name)); rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets); } + dfe_done(c); + rrdset_done(d->st_packets); } @@ -490,47 +524,56 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!d->st_dropped)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id); - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id); + snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", string2str(d->id)); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", string2str(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" - , PLUGIN_TC_NAME - , NULL - , NETDATA_CHART_PRIO_TC_QOS_DROPPED - , localhost->rrd_update_every - , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED - ); + RRD_TYPE_TC, + id, + name, + string2str(d->family ? d->family : d->id), + RRD_TYPE_TC ".qos_dropped", + "Class Dropped Packets", + "packets/s", + PLUGIN_TC_NAME, + NULL, + NETDATA_CHART_PRIO_TC_QOS_DROPPED, + localhost->rrd_update_every, + d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED); + + rrdlabels_add(d->st_bytes->rrdlabels, "device", string2str(d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name?d->name:d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family?d->family:d->id), RRDLABEL_SRC_AUTO); } else { - rrdset_next(d->st_dropped); - if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id); - rrdset_set_name(d->st_dropped, name); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", string2str(d->name?d->name:d->id)); + rrdset_reset_name(d->st_dropped, name); } + if(d->name && d->name_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name), RRDLABEL_SRC_AUTO); + + if(d->family && d->family_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family), RRDLABEL_SRC_AUTO); + // TODO // update the family } - for(c = d->classes ; c ; c = c->next) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_dropped)) - c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL); + c->rd_dropped = rrddim_add(d->st_dropped, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_dropped, c->rd_dropped, c->name); + rrddim_reset_name(d->st_dropped, c->rd_dropped, string2str(c->name)); rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped); } + dfe_done(c); + rrdset_done(d->st_dropped); } @@ -545,48 +588,57 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!d->st_tokens)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(id, RRD_ID_LENGTH_MAX, "%s_tokens", d->id); - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id); + snprintfz(id, RRD_ID_LENGTH_MAX, "%s_tokens", string2str(d->id)); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", string2str(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" - , PLUGIN_TC_NAME - , NULL - , NETDATA_CHART_PRIO_TC_QOS_TOKENS - , localhost->rrd_update_every - , RRDSET_TYPE_LINE - ); + RRD_TYPE_TC, + id, + name, + string2str(d->family ? d->family : d->id), + RRD_TYPE_TC ".qos_tokens", + "Class Tokens", + "tokens", + PLUGIN_TC_NAME, + NULL, + NETDATA_CHART_PRIO_TC_QOS_TOKENS, + localhost->rrd_update_every, + RRDSET_TYPE_LINE); + + rrdlabels_add(d->st_bytes->rrdlabels, "device", string2str(d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name?d->name:d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family?d->family:d->id), RRDLABEL_SRC_AUTO); } else { - rrdset_next(d->st_tokens); - if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id); - rrdset_set_name(d->st_tokens, name); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", string2str(d->name?d->name:d->id)); + rrdset_reset_name(d->st_tokens, name); } + if(d->name && d->name_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name), RRDLABEL_SRC_AUTO); + + if(d->family && d->family_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family), RRDLABEL_SRC_AUTO); + // TODO // update the family } - for(c = d->classes ; c ; c = c->next) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_tokens)) { - c->rd_tokens = rrddim_add(d->st_tokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE); + c->rd_tokens = rrddim_add(d->st_tokens, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_ABSOLUTE); } else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_tokens, c->rd_tokens, c->name); + rrddim_reset_name(d->st_tokens, c->rd_tokens, string2str(c->name)); rrddim_set_by_pointer(d->st_tokens, c->rd_tokens, c->tokens); } + dfe_done(c); + rrdset_done(d->st_tokens); } @@ -601,48 +653,58 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!d->st_ctokens)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(id, RRD_ID_LENGTH_MAX, "%s_ctokens", d->id); - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id); + snprintfz(id, RRD_ID_LENGTH_MAX, "%s_ctokens", string2str(d->id)); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", string2str(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" - , PLUGIN_TC_NAME - , NULL - , NETDATA_CHART_PRIO_TC_QOS_CTOKENS - , localhost->rrd_update_every - , RRDSET_TYPE_LINE - ); + RRD_TYPE_TC, + id, + name, + string2str(d->family ? d->family : d->id), + RRD_TYPE_TC ".qos_ctokens", + "Class cTokens", + "ctokens", + PLUGIN_TC_NAME, + NULL, + NETDATA_CHART_PRIO_TC_QOS_CTOKENS, + localhost->rrd_update_every, + RRDSET_TYPE_LINE); + + rrdlabels_add(d->st_bytes->rrdlabels, "device", string2str(d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name?d->name:d->id), RRDLABEL_SRC_AUTO); + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family?d->family:d->id), RRDLABEL_SRC_AUTO); } else { - debug(D_TC_LOOP, "TC: Updating _ctokens chart for device '%s'", d->name?d->name:d->id); - rrdset_next(d->st_ctokens); + debug(D_TC_LOOP, "TC: Updating _ctokens chart for device '%s'", string2str(d->name?d->name:d->id)); if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id); - rrdset_set_name(d->st_ctokens, name); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", string2str(d->name?d->name:d->id)); + rrdset_reset_name(d->st_ctokens, name); } + if(d->name && d->name_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name), RRDLABEL_SRC_AUTO); + + if(d->family && d->family_updated) + rrdlabels_add(d->st_bytes->rrdlabels, "family", string2str(d->family), RRDLABEL_SRC_AUTO); + // TODO // update the family } - for(c = d->classes ; c ; c = c->next) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_ctokens)) - c->rd_ctokens = rrddim_add(d->st_ctokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE); + c->rd_ctokens = rrddim_add(d->st_ctokens, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_ABSOLUTE); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_ctokens, c->rd_ctokens, c->name); + rrddim_reset_name(d->st_ctokens, c->rd_ctokens, string2str(c->name)); rrddim_set_by_pointer(d->st_ctokens, c->rd_ctokens, c->ctokens); } + dfe_done(c); + rrdset_done(d->st_ctokens); } @@ -652,18 +714,18 @@ static inline void tc_device_commit(struct tc_device *d) { static inline void tc_device_set_class_name(struct tc_device *d, char *id, char *name) { if(unlikely(!name || !*name)) return; - struct tc_class *c = tc_class_index_find(d, id, 0); + struct tc_class *c = tc_class_index_find(d, id); if(likely(c)) { if(likely(c->name)) { - if(!strcmp(c->name, name)) return; - freez(c->name); + if(!strcmp(string2str(c->name), name)) return; + string_freez(c->name); c->name = NULL; } - if(likely(name && *name && strcmp(c->id, name) != 0)) { - debug(D_TC_LOOP, "TC: Setting device '%s', class '%s' name to '%s'", d->id, id, name); - c->name = strdupz(name); - c->name_updated = 1; + if(likely(name && *name && strcmp(string2str(c->id), name) != 0)) { + debug(D_TC_LOOP, "TC: Setting device '%s', class '%s' name to '%s'", string2str(d->id), id, name); + c->name = string_strdupz(name); + c->name_updated = true; } } } @@ -672,126 +734,68 @@ static inline void tc_device_set_device_name(struct tc_device *d, char *name) { if(unlikely(!name || !*name)) return; if(d->name) { - if(!strcmp(d->name, name)) return; - freez(d->name); + if(!strcmp(string2str(d->name), name)) return; + string_freez(d->name); d->name = NULL; } - 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; + if(likely(name && *name && strcmp(string2str(d->id), name) != 0)) { + debug(D_TC_LOOP, "TC: Setting device '%s' name to '%s'", string2str(d->id), name); + d->name = string_strdupz(name); + d->name_updated = true; } } static inline void tc_device_set_device_family(struct tc_device *d, char *family) { - freez(d->family); + string_freez(d->family); d->family = NULL; - if(likely(family && *family && strcmp(d->id, family) != 0)) { - debug(D_TC_LOOP, "TC: Setting device '%s' family to '%s'", d->id, family); - d->family = strdupz(family); - d->family_updated = 1; + if(likely(family && *family && strcmp(string2str(d->id), family) != 0)) { + debug(D_TC_LOOP, "TC: Setting device '%s' family to '%s'", string2str(d->id), family); + d->family = string_strdupz(family); + d->family_updated = true; } // no need for null termination - it is already null } -static inline struct tc_device *tc_device_create(char *id) -{ - struct tc_device *d = tc_device_index_find(id, 0); +static inline struct tc_device *tc_device_create(char *id) { + struct tc_device *d = tc_device_index_find(id); if(!d) { debug(D_TC_LOOP, "TC: Creating device '%s'", id); - d = callocz(1, sizeof(struct tc_device)); - - d->id = strdupz(id); - d->hash = simple_hash(d->id); - d->enabled = (char)-1; - - avl_init(&d->classes_index, tc_class_compare); - if(unlikely(tc_device_index_add(d) != d)) - error("plugin_tc: INTERNAL ERROR: removing device '%s' removed a different device.", d->id); - - if(!tc_device_root) { - tc_device_root = d; - } - else { - d->next = tc_device_root; - tc_device_root->prev = d; - tc_device_root = d; - } + struct tc_device tmp = { + .id = string_strdupz(id), + .enabled = (char)-1, + }; + d = tc_device_index_add(&tmp); } return(d); } -static inline struct tc_class *tc_class_add(struct tc_device *n, char *id, char qdisc, char *parentid, char *leafid) -{ - struct tc_class *c = tc_class_index_find(n, id, 0); +static inline struct tc_class *tc_class_add(struct tc_device *n, char *id, bool qdisc, char *parentid, char *leafid) { + struct tc_class *c = tc_class_index_find(n, id); if(!c) { - debug(D_TC_LOOP, "TC: Creating in device '%s', class id '%s', parentid '%s', leafid '%s'", n->id, id, parentid?parentid:"", leafid?leafid:""); + debug(D_TC_LOOP, "TC: Creating in device '%s', class id '%s', parentid '%s', leafid '%s'", + string2str(n->id), id, parentid?parentid:"", leafid?leafid:""); - c = callocz(1, sizeof(struct tc_class)); + struct tc_class tmp = { + .id = string_strdupz(id), + .isqdisc = qdisc, + .parentid = string_strdupz(parentid), + .leafid = string_strdupz(leafid), + }; - 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); - - c->isqdisc = qdisc; - if(parentid && *parentid) { - c->parentid = strdupz(parentid); - c->parent_hash = simple_hash(c->parentid); - } - - if(leafid && *leafid) { - c->leafid = strdupz(leafid); - c->leaf_hash = simple_hash(c->leafid); - } - - if(unlikely(tc_class_index_add(n, c) != c)) - error("plugin_tc: INTERNAL ERROR: attempt index class '%s' on device '%s': already exists", c->id, n->id); + tc_class_index_add(n, &tmp); } return(c); } -static inline void tc_device_free(struct tc_device *n) -{ - if(n->next) n->next->prev = n->prev; - if(n->prev) n->prev->next = n->next; - if(tc_device_root == n) { - if(n->next) tc_device_root = n->next; - else tc_device_root = n->prev; - } - - if(unlikely(tc_device_index_del(n) != n)) - error("plugin_tc: INTERNAL ERROR: removing device '%s' removed a different device.", n->id); - - while(n->classes) tc_class_free(n, n->classes); - - freez(n->id); - freez(n->name); - freez(n->family); - freez(n); -} - -static inline void tc_device_free_all() -{ - while(tc_device_root) - tc_device_free(tc_device_root); -} - -#define PLUGINSD_MAX_WORDS 20 +//static inline void tc_device_free(struct tc_device *d) { +// tc_device_index_del(d); +//} static inline int tc_space(char c) { switch(c) { @@ -846,6 +850,8 @@ static pid_t tc_child_pid = 0; static void tc_main_cleanup(void *ptr) { worker_unregister(); + tc_device_index_destroy(); + struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; @@ -876,8 +882,11 @@ static void tc_main_cleanup(void *ptr) { #define WORKER_TC_SETDEVICEGROUP 7 #define WORKER_TC_SETCLASSNAME 8 #define WORKER_TC_WORKTIME 9 +#define WORKER_TC_PLUGIN_TIME 10 +#define WORKER_TC_DEVICES 11 +#define WORKER_TC_CLASSES 12 -#if WORKER_UTILIZATION_MAX_JOB_TYPES < 10 +#if WORKER_UTILIZATION_MAX_JOB_TYPES < 13 #error WORKER_UTILIZATION_MAX_JOB_TYPES has to be at least 10 #endif @@ -894,6 +903,11 @@ void *tc_main(void *ptr) { worker_register_job_name(WORKER_TC_SETCLASSNAME, "classname"); worker_register_job_name(WORKER_TC_WORKTIME, "worktime"); + worker_register_job_custom_metric(WORKER_TC_PLUGIN_TIME, "tc script execution time", "milliseconds/run", WORKER_METRIC_ABSOLUTE); + worker_register_job_custom_metric(WORKER_TC_DEVICES, "number of devices", "devices", WORKER_METRIC_ABSOLUTE); + worker_register_job_custom_metric(WORKER_TC_CLASSES, "number of classes", "classes", WORKER_METRIC_ABSOLUTE); + + tc_device_index_init(); netdata_thread_cleanup_push(tc_main_cleanup, ptr); char command[FILENAME_MAX + 1]; @@ -916,21 +930,21 @@ void *tc_main(void *ptr) { char *tc_script = config_get("plugin:tc", "script to run to get tc values", command); while(!netdata_exit) { - FILE *fp; + FILE *fp_child_input, *fp_child_output; struct tc_device *device = NULL; struct tc_class *class = NULL; snprintfz(command, TC_LINE_MAX, "exec %s %d", tc_script, localhost->rrd_update_every); debug(D_TC_LOOP, "executing '%s'", command); - fp = mypopen(command, (pid_t *)&tc_child_pid); - if(unlikely(!fp)) { + fp_child_output = netdata_popen(command, (pid_t *)&tc_child_pid, &fp_child_input); + if(unlikely(!fp_child_output)) { error("TC: Cannot popen(\"%s\", \"r\").", command); goto cleanup; } char buffer[TC_LINE_MAX+1] = ""; - while(fgets(buffer, TC_LINE_MAX, fp) != NULL) { + while(fgets(buffer, TC_LINE_MAX, fp_child_output) != NULL) { if(unlikely(netdata_exit)) break; buffer[TC_LINE_MAX] = '\0'; @@ -969,10 +983,10 @@ void *tc_main(void *ptr) { } if(likely(type && id && (parent_is_root || parent_is_parent))) { - char qdisc = 0; + bool qdisc = false; if(first_hash == QDISC_HASH) { - qdisc = 1; + qdisc = true; if(!strcmp(type, "ingress")) { // we don't want to get the ingress qdisc @@ -1051,10 +1065,10 @@ void *tc_main(void *ptr) { // debug(D_TC_LOOP, "SENT line '%s'", words[1]); if(likely(words[1] && *words[1])) { class->bytes = str2ull(words[1]); - class->updated = 1; + class->updated = true; } else { - class->updated = 0; + class->updated = false; } if(likely(words[3] && *words[3])) @@ -1063,24 +1077,24 @@ void *tc_main(void *ptr) { if(likely(words[6] && *words[6])) class->dropped = str2ull(words[6]); - if(likely(words[8] && *words[8])) - class->overlimits = str2ull(words[8]); + //if(likely(words[8] && *words[8])) + // class->overlimits = str2ull(words[8]); - if(likely(words[10] && *words[10])) - class->requeues = str2ull(words[8]); + //if(likely(words[10] && *words[10])) + // class->requeues = str2ull(words[8]); } else if(unlikely(device && class && class->updated && first_hash == LENDED_HASH && strcmp(words[0], "lended:") == 0)) { worker_is_busy(WORKER_TC_LENDED); // debug(D_TC_LOOP, "LENDED line '%s'", words[1]); - if(likely(words[1] && *words[1])) - class->lended = str2ull(words[1]); + //if(likely(words[1] && *words[1])) + // class->lended = str2ull(words[1]); - if(likely(words[3] && *words[3])) - class->borrowed = str2ull(words[3]); + //if(likely(words[3] && *words[3])) + // class->borrowed = str2ull(words[3]); - if(likely(words[5] && *words[5])) - class->giants = str2ull(words[5]); + //if(likely(words[5] && *words[5])) + // class->giants = str2ull(words[5]); } else if(unlikely(device && class && class->updated && first_hash == TOKENS_HASH && strcmp(words[0], "tokens:") == 0)) { worker_is_busy(WORKER_TC_TOKENS); @@ -1117,33 +1131,19 @@ void *tc_main(void *ptr) { } else if(unlikely(first_hash == WORKTIME_HASH && strcmp(words[0], "WORKTIME") == 0)) { worker_is_busy(WORKER_TC_WORKTIME); + worker_set_metric(WORKER_TC_PLUGIN_TIME, str2ll(words[1], NULL)); - // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]); - static RRDSET *sttime = NULL; - static RRDDIM *rd_run_time = NULL; - - if(unlikely(!sttime)) { - sttime = rrdset_create_localhost( - "netdata" - , "plugin_tc_time" - , NULL - , "workers plugin tc" - , "netdata.workers.tc.script_time" - , "Netdata TC script execution" - , "milliseconds/run" - , PLUGIN_TC_NAME - , NULL - , NETDATA_CHART_PRIO_NETDATA_TC_TIME - , 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); + size_t number_of_devices = dictionary_entries(tc_device_root_index); + size_t number_of_classes = 0; - rrddim_set_by_pointer(sttime, rd_run_time, str2ll(words[1], NULL)); - rrdset_done(sttime); + struct tc_device *d; + dfe_start_read(tc_device_root_index, d) { + number_of_classes += dictionary_entries(d->classes); + } + dfe_done(d); + worker_set_metric(WORKER_TC_DEVICES, number_of_devices); + worker_set_metric(WORKER_TC_CLASSES, number_of_classes); } //else { // debug(D_TC_LOOP, "IGNORED line"); @@ -1153,7 +1153,7 @@ void *tc_main(void *ptr) { } // fgets() failed or loop broke - int code = mypclose(fp, (pid_t)tc_child_pid); + int code = netdata_pclose(fp_child_input, fp_child_output, (pid_t)tc_child_pid); tc_child_pid = 0; if(unlikely(device)) { @@ -1162,17 +1162,13 @@ void *tc_main(void *ptr) { class = NULL; } - if(unlikely(netdata_exit)) { - tc_device_free_all(); + if(unlikely(netdata_exit)) goto cleanup; - } if(code == 1 || code == 127) { // 1 = DISABLE // 127 = cannot even run it error("TC: tc-qos-helper.sh exited with code %d. Disabling it.", code); - - tc_device_free_all(); goto cleanup; } diff --git a/collectors/timex.plugin/plugin_timex.c b/collectors/timex.plugin/plugin_timex.c index 0390b9920..46cfc5796 100644 --- a/collectors/timex.plugin/plugin_timex.c +++ b/collectors/timex.plugin/plugin_timex.c @@ -109,8 +109,6 @@ void *timex_main(void *ptr) RRDSET_TYPE_LINE); rd_sync_state = rrddim_add(st_sync_state, "state", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(st_sync_state); } rrddim_set_by_pointer(st_sync_state, rd_sync_state, sync_state != TIME_ERROR ? 1 : 0); @@ -137,13 +135,11 @@ void *timex_main(void *ptr) sta_codes[i].rd = rrddim_add(st_clock_status, sta_codes[i].name, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - } else { - rrdset_next(st_clock_status); } - for (int i = 0; sta_codes[i].name != NULL; i++) { + for (int i = 0; sta_codes[i].name != NULL; i++) rrddim_set_by_pointer(st_clock_status, sta_codes[i].rd, timex_buf.status & sta_codes[i].code ? 1 : 0); - } + rrdset_done(st_clock_status); } @@ -167,8 +163,6 @@ void *timex_main(void *ptr) RRDSET_TYPE_LINE); rd_offset = rrddim_add(st_offset, "offset", NULL, 1, divisor, RRD_ALGORITHM_ABSOLUTE); - } else { - rrdset_next(st_offset); } rrddim_set_by_pointer(st_offset, rd_offset, timex_buf.offset); diff --git a/collectors/xenstat.plugin/xenstat_plugin.c b/collectors/xenstat.plugin/xenstat_plugin.c index 882f72ce9..ea98b9bb1 100644 --- a/collectors/xenstat.plugin/xenstat_plugin.c +++ b/collectors/xenstat.plugin/xenstat_plugin.c @@ -171,7 +171,7 @@ static struct domain_metrics *domain_metrics_free(struct domain_metrics *d) { struct vbd_metrics *vbd, *vbd_f; struct network_metrics *network, *network_f; - if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: freeing memory for domain '%s' id %d, uuid %s\n", d->name, d->id, d->uuid); + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: freeing memory for domain '%s' id %u, uuid %s\n", d->name, d->id, d->uuid); for(cur = node_metrics.domain_root; cur ; last = cur, cur = cur->next) { if(unlikely(cur->hash == d->hash && !strcmp(cur->uuid, d->uuid))) break; @@ -401,7 +401,7 @@ static int xenstat_collect(xenstat_handle *xhandle, libxl_ctx *ctx, libxl_dominf if(unlikely(!d->name)) { d->name = strdupz(xenstat_domain_name(domain)); netdata_fix_chart_id(d->name); - if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: domain id %d, uuid %s has name '%s'\n", d->id, d->uuid, d->name); + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: domain id %u, uuid %s has name '%s'\n", d->id, d->uuid, d->name); } d->running = xenstat_domain_running(domain); @@ -569,7 +569,7 @@ static void print_domain_vcpu_chart_definition(char *type, struct domain_metrics } static void print_domain_vbd_oo_chart_definition(char *type, unsigned int vbd, int obsolete_flag) { - printf("CHART %s.oo_req_vbd%u '' 'VBD%u \"Out Of\" Requests' 'requests/s' 'vbd' 'xendomain.oo_req_vbd' line %d %d %s %s\n" + printf("CHART %s.oo_req_vbd%u '' 'VBD%u \"Out Of\" Requests' 'requests/s' 'vbd' 'xendomain.oo_req_vbd' line %u %d %s %s\n" , type , vbd , vbd @@ -582,7 +582,7 @@ static void print_domain_vbd_oo_chart_definition(char *type, unsigned int vbd, i } static void print_domain_vbd_requests_chart_definition(char *type, unsigned int vbd, int obsolete_flag) { - printf("CHART %s.requests_vbd%u '' 'VBD%u Requests' 'requests/s' 'vbd' 'xendomain.requests_vbd' line %d %d %s %s\n" + printf("CHART %s.requests_vbd%u '' 'VBD%u Requests' 'requests/s' 'vbd' 'xendomain.requests_vbd' line %u %d %s %s\n" , type , vbd , vbd @@ -596,7 +596,7 @@ static void print_domain_vbd_requests_chart_definition(char *type, unsigned int } static void print_domain_vbd_sectors_chart_definition(char *type, unsigned int vbd, int obsolete_flag) { - printf("CHART %s.sectors_vbd%u '' 'VBD%u Read/Written Sectors' 'sectors/s' 'vbd' 'xendomain.sectors_vbd' line %d %d %s %s\n" + printf("CHART %s.sectors_vbd%u '' 'VBD%u Read/Written Sectors' 'sectors/s' 'vbd' 'xendomain.sectors_vbd' line %u %d %s %s\n" , type , vbd , vbd @@ -610,7 +610,7 @@ static void print_domain_vbd_sectors_chart_definition(char *type, unsigned int v } static void print_domain_network_bytes_chart_definition(char *type, unsigned int network, int obsolete_flag) { - printf("CHART %s.bytes_network%u '' 'Network%u Received/Sent Bytes' 'kilobits/s' 'network' 'xendomain.bytes_network' line %d %d %s %s\n" + printf("CHART %s.bytes_network%u '' 'Network%u Received/Sent Bytes' 'kilobits/s' 'network' 'xendomain.bytes_network' line %u %d %s %s\n" , type , network , network @@ -624,7 +624,7 @@ static void print_domain_network_bytes_chart_definition(char *type, unsigned int } static void print_domain_network_packets_chart_definition(char *type, unsigned int network, int obsolete_flag) { - printf("CHART %s.packets_network%u '' 'Network%u Received/Sent Packets' 'packets/s' 'network' 'xendomain.packets_network' line %d %d %s %s\n" + printf("CHART %s.packets_network%u '' 'Network%u Received/Sent Packets' 'packets/s' 'network' 'xendomain.packets_network' line %u %d %s %s\n" , type , network , network @@ -638,7 +638,7 @@ static void print_domain_network_packets_chart_definition(char *type, unsigned i } static void print_domain_network_errors_chart_definition(char *type, unsigned int network, int obsolete_flag) { - printf("CHART %s.errors_network%u '' 'Network%u Receive/Transmit Errors' 'errors/s' 'network' 'xendomain.errors_network' line %d %d %s %s\n" + printf("CHART %s.errors_network%u '' 'Network%u Receive/Transmit Errors' 'errors/s' 'network' 'xendomain.errors_network' line %u %d %s %s\n" , type , network , network @@ -652,7 +652,7 @@ static void print_domain_network_errors_chart_definition(char *type, unsigned in } static void print_domain_network_drops_chart_definition(char *type, unsigned int network, int obsolete_flag) { - printf("CHART %s.drops_network%u '' 'Network%u Receive/Transmit Drops' 'drops/s' 'network' 'xendomain.drops_network' line %d %d %s %s\n" + printf("CHART %s.drops_network%u '' 'Network%u Receive/Transmit Drops' 'drops/s' 'network' 'xendomain.drops_network' line %u %d %s %s\n" , type , network , network @@ -808,7 +808,7 @@ static void xenstat_send_domain_metrics() { if(unlikely(vbd_m->oo_req_chart_generated || vbd_m->requests_chart_generated || vbd_m->sectors_chart_generated)) { - if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: mark charts as obsolete for vbd %d, domain '%s', id %d, uuid %s\n", vbd_m->id, d->name, d->id, d->uuid); + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: mark charts as obsolete for vbd %u, domain '%s', id %u, uuid %s\n", vbd_m->id, d->name, d->id, d->uuid); print_domain_vbd_oo_chart_definition(type, vbd_m->id, CHART_IS_OBSOLETE); print_domain_vbd_requests_chart_definition(type, vbd_m->id, CHART_IS_OBSOLETE); print_domain_vbd_sectors_chart_definition(type, vbd_m->id, CHART_IS_OBSOLETE); @@ -895,7 +895,7 @@ static void xenstat_send_domain_metrics() { || network_m->packets_chart_generated || network_m->errors_chart_generated || network_m->drops_chart_generated)) - if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: mark charts as obsolete for network %d, domain '%s', id %d, uuid %s\n", network_m->id, d->name, d->id, d->uuid); + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: mark charts as obsolete for network %u, domain '%s', id %u, uuid %s\n", network_m->id, d->name, d->id, d->uuid); print_domain_network_bytes_chart_definition(type, network_m->id, CHART_IS_OBSOLETE); print_domain_network_packets_chart_definition(type, network_m->id, CHART_IS_OBSOLETE); print_domain_network_errors_chart_definition(type, network_m->id, CHART_IS_OBSOLETE); @@ -908,7 +908,7 @@ static void xenstat_send_domain_metrics() { } } else{ - if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: mark charts as obsolete for domain '%s', id %d, uuid %s\n", d->name, d->id, d->uuid); + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: mark charts as obsolete for domain '%s', id %u, uuid %s\n", d->name, d->id, d->uuid); print_domain_states_chart_definition(type, CHART_IS_OBSOLETE); print_domain_cpu_chart_definition(type, CHART_IS_OBSOLETE); print_domain_vcpu_chart_definition(type, d, CHART_IS_OBSOLETE); @@ -1006,12 +1006,16 @@ int main(int argc, char **argv) { if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: calling xenstat_init()\n"); xhandle = xenstat_init(); - if (xhandle == NULL) + if (xhandle == NULL) { error("XENSTAT: failed to initialize xenstat library."); + return 1; + } if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: calling libxl_ctx_alloc()\n"); if (libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, NULL)) { error("XENSTAT: failed to initialize xl context."); + xenstat_uninit(xhandle); + return 1; } libxl_dominfo_init(&info); @@ -1062,4 +1066,6 @@ int main(int argc, char **argv) { libxl_ctx_free(ctx); xenstat_uninit(xhandle); info("XENSTAT process exiting"); + + return 0; } diff --git a/collectors/checks.plugin/Makefile.am b/libnetdata/string/Makefile.am index 161784b8f..161784b8f 100644 --- a/collectors/checks.plugin/Makefile.am +++ b/libnetdata/string/Makefile.am |