diff options
Diffstat (limited to '')
-rw-r--r-- | backends/backends.c (renamed from src/backends.c) | 437 | ||||
-rw-r--r-- | backends/prometheus/backend_prometheus.c (renamed from src/backend_prometheus.c) | 177 | ||||
-rw-r--r-- | collectors/apps.plugin/apps_plugin.c (renamed from src/apps_plugin.c) | 712 | ||||
-rw-r--r-- | collectors/cgroups.plugin/cgroup-network.c (renamed from src/cgroup-network.c) | 97 | ||||
-rw-r--r-- | collectors/cgroups.plugin/sys_fs_cgroup.c (renamed from src/sys_fs_cgroup.c) | 340 | ||||
-rw-r--r-- | collectors/checks.plugin/plugin_checks.c (renamed from src/plugin_checks.c) | 22 | ||||
-rw-r--r-- | collectors/diskspace.plugin/plugin_diskspace.c (renamed from src/plugin_proc_diskspace.c) | 29 | ||||
-rw-r--r-- | collectors/freebsd.plugin/freebsd_devstat.c (renamed from src/freebsd_devstat.c) | 40 | ||||
-rw-r--r-- | collectors/freebsd.plugin/freebsd_getifaddrs.c (renamed from src/freebsd_getifaddrs.c) | 156 | ||||
-rw-r--r-- | collectors/freebsd.plugin/freebsd_getmntinfo.c (renamed from src/freebsd_getmntinfo.c) | 12 | ||||
-rw-r--r-- | collectors/freebsd.plugin/freebsd_ipfw.c (renamed from src/freebsd_ipfw.c) | 24 | ||||
-rw-r--r-- | collectors/freebsd.plugin/freebsd_kstat_zfs.c (renamed from src/freebsd_kstat_zfs.c) | 10 | ||||
-rw-r--r-- | collectors/freebsd.plugin/freebsd_sysctl.c (renamed from src/freebsd_sysctl.c) | 191 | ||||
-rw-r--r-- | collectors/freebsd.plugin/plugin_freebsd.c (renamed from src/plugin_freebsd.c) | 6 | ||||
-rw-r--r-- | collectors/freeipmi.plugin/freeipmi_plugin.c (renamed from src/freeipmi_plugin.c) | 104 | ||||
-rw-r--r-- | collectors/idlejitter.plugin/plugin_idlejitter.c (renamed from src/plugin_idlejitter.c) | 8 | ||||
-rw-r--r-- | collectors/macos.plugin/macos_fw.c (renamed from src/macos_fw.c) | 5 | ||||
-rw-r--r-- | collectors/macos.plugin/macos_mach_smi.c (renamed from src/macos_mach_smi.c) | 5 | ||||
-rw-r--r-- | collectors/macos.plugin/macos_sysctl.c (renamed from src/macos_sysctl.c) | 20 | ||||
-rw-r--r-- | collectors/macos.plugin/plugin_macos.c (renamed from src/plugin_macos.c) | 4 | ||||
-rw-r--r-- | collectors/nfacct.plugin/plugin_nfacct.c (renamed from src/plugin_nfacct.c) | 41 | ||||
-rw-r--r-- | collectors/plugins.d/plugins_d.c (renamed from src/plugins_d.c) | 4 | ||||
-rw-r--r-- | collectors/plugins.d/plugins_d.h (renamed from src/plugins_d.h) | 16 | ||||
-rw-r--r-- | collectors/proc.plugin/ipc.c (renamed from src/ipc.c) | 22 | ||||
-rw-r--r-- | collectors/proc.plugin/plugin_proc.c (renamed from src/plugin_proc.c) | 20 | ||||
-rw-r--r-- | collectors/proc.plugin/plugin_proc.h (renamed from src/plugin_proc.h) | 36 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_diskstats.c (renamed from src/proc_diskstats.c) | 455 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_interrupts.c (renamed from src/proc_interrupts.c) | 77 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_loadavg.c (renamed from src/proc_loadavg.c) | 25 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_meminfo.c (renamed from src/proc_meminfo.c) | 71 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_dev.c (renamed from src/proc_net_dev.c) | 82 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_ip_vs_stats.c (renamed from src/proc_net_ip_vs_stats.c) | 34 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_netstat.c (renamed from src/proc_net_netstat.c) | 421 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_rpc_nfs.c (renamed from src/proc_net_rpc_nfs.c) | 49 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_rpc_nfsd.c (renamed from src/proc_net_rpc_nfsd.c) | 84 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_snmp.c (renamed from src/proc_net_snmp.c) | 253 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_snmp6.c (renamed from src/proc_net_snmp6.c) | 137 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_sockstat.c (renamed from src/proc_net_sockstat.c) | 66 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_sockstat6.c (renamed from src/proc_net_sockstat6.c) | 36 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_softnet_stat.c (renamed from src/proc_net_softnet_stat.c) | 18 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_stat_conntrack.c (renamed from src/proc_net_stat_conntrack.c) | 41 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_net_stat_synproxy.c (renamed from src/proc_net_stat_synproxy.c) | 30 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_self_mountinfo.c (renamed from src/proc_self_mountinfo.c) | 4 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_self_mountinfo.h (renamed from src/proc_self_mountinfo.h) | 2 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_softirqs.c (renamed from src/proc_softirqs.c) | 73 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_spl_kstat_zfs.c (renamed from src/proc_spl_kstat_zfs.c) | 8 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_stat.c (renamed from src/proc_stat.c) | 71 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_sys_kernel_random_entropy_avail.c (renamed from src/proc_sys_kernel_random_entropy_avail.c) | 10 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_uptime.c (renamed from src/proc_uptime.c) | 10 | ||||
-rw-r--r-- | collectors/proc.plugin/proc_vmstat.c (renamed from src/proc_vmstat.c) | 26 | ||||
-rw-r--r-- | collectors/proc.plugin/sys_devices_system_edac_mc.c (renamed from src/sys_devices_system_edac_mc.c) | 12 | ||||
-rw-r--r-- | collectors/proc.plugin/sys_devices_system_node.c (renamed from src/sys_devices_system_node.c) | 8 | ||||
-rw-r--r-- | collectors/proc.plugin/sys_fs_btrfs.c (renamed from src/sys_fs_btrfs.c) | 58 | ||||
-rw-r--r-- | collectors/proc.plugin/sys_kernel_mm_ksm.c (renamed from src/sys_kernel_mm_ksm.c) | 22 | ||||
-rw-r--r-- | collectors/proc.plugin/zfs_common.c (renamed from src/zfs_common.c) | 79 | ||||
-rw-r--r-- | collectors/proc.plugin/zfs_common.h (renamed from src/zfs_common.h) | 10 | ||||
-rw-r--r-- | collectors/python.d.plugin/python_modules/urllib3/contrib/__init__.py (renamed from src/.keep) | 0 | ||||
-rw-r--r-- | collectors/statsd.plugin/statsd.c (renamed from src/statsd.c) | 373 | ||||
-rw-r--r-- | collectors/tc.plugin/plugin_tc.c (renamed from src/plugin_tc.c) | 58 | ||||
-rw-r--r-- | daemon/daemon.c (renamed from src/daemon.c) | 70 | ||||
-rw-r--r-- | daemon/daemon.h (renamed from src/daemon.h) | 2 | ||||
-rw-r--r-- | daemon/global_statistics.c (renamed from src/global_statistics.c) | 147 | ||||
-rw-r--r-- | daemon/global_statistics.h (renamed from src/global_statistics.h) | 25 | ||||
-rw-r--r-- | daemon/main.c (renamed from src/main.c) | 187 | ||||
-rw-r--r-- | daemon/main.h (renamed from src/main.h) | 20 | ||||
-rw-r--r-- | daemon/signals.c (renamed from src/signals.c) | 3 | ||||
-rw-r--r-- | daemon/signals.h (renamed from src/signals.h) | 4 | ||||
-rw-r--r-- | daemon/unit_test.c (renamed from src/unit_test.c) | 44 | ||||
-rw-r--r-- | daemon/unit_test.h (renamed from src/unit_test.h) | 2 | ||||
-rw-r--r-- | database/rrd.c (renamed from src/rrd.c) | 4 | ||||
-rw-r--r-- | database/rrd.h (renamed from src/rrd.h) | 227 | ||||
-rw-r--r-- | database/rrdcalc.c (renamed from src/rrdcalc.c) | 17 | ||||
-rw-r--r-- | database/rrdcalctemplate.c (renamed from src/rrdcalctemplate.c) | 4 | ||||
-rw-r--r-- | database/rrddim.c (renamed from src/rrddim.c) | 20 | ||||
-rw-r--r-- | database/rrddimvar.c (renamed from src/rrddimvar.c) | 27 | ||||
-rw-r--r-- | database/rrdfamily.c (renamed from src/rrdfamily.c) | 6 | ||||
-rw-r--r-- | database/rrdhost.c (renamed from src/rrdhost.c) | 26 | ||||
-rw-r--r-- | database/rrdset.c (renamed from src/rrdset.c) | 111 | ||||
-rw-r--r-- | database/rrdsetvar.c (renamed from src/rrdsetvar.c) | 30 | ||||
-rw-r--r-- | database/rrdvar.c (renamed from src/rrdvar.c) | 28 | ||||
-rw-r--r-- | health/health.c (renamed from src/health.c) | 35 | ||||
-rw-r--r-- | health/health_config.c (renamed from src/health_config.c) | 256 | ||||
-rw-r--r-- | health/health_json.c (renamed from src/health_json.c) | 5 | ||||
-rw-r--r-- | health/health_log.c (renamed from src/health_log.c) | 5 | ||||
-rw-r--r-- | libnetdata/adaptive_resortable_list/adaptive_resortable_list.c (renamed from src/adaptive_resortable_list.c) | 13 | ||||
-rw-r--r-- | libnetdata/adaptive_resortable_list/adaptive_resortable_list.h (renamed from src/adaptive_resortable_list.h) | 45 | ||||
-rw-r--r-- | libnetdata/avl/avl.c (renamed from src/avl.c) | 67 | ||||
-rw-r--r-- | libnetdata/avl/avl.h (renamed from src/avl.h) | 23 | ||||
-rw-r--r-- | libnetdata/buffer/buffer.c (renamed from src/web_buffer.c) | 7 | ||||
-rw-r--r-- | libnetdata/buffer/buffer.h (renamed from src/web_buffer.h) | 4 | ||||
-rw-r--r-- | libnetdata/clocks/clocks.h (renamed from src/clocks.h) | 15 | ||||
-rw-r--r-- | libnetdata/config/appconfig.c (renamed from src/appconfig.c) | 39 | ||||
-rw-r--r-- | libnetdata/dictionary/dictionary.c (renamed from src/dictionary.c) | 4 | ||||
-rw-r--r-- | libnetdata/dictionary/dictionary.h (renamed from src/dictionary.h) | 6 | ||||
-rw-r--r-- | libnetdata/eval/eval.c (renamed from src/eval.c) | 52 | ||||
-rw-r--r-- | libnetdata/eval/eval.h (renamed from src/eval.h) | 20 | ||||
-rw-r--r-- | libnetdata/inlined.h (renamed from src/inlined.h) | 13 | ||||
-rw-r--r-- | libnetdata/libnetdata.c (renamed from src/common.c) | 696 | ||||
-rw-r--r-- | libnetdata/libnetdata.h (renamed from src/common.h) | 252 | ||||
-rw-r--r-- | libnetdata/locks/locks.c (renamed from src/locks.c) | 15 | ||||
-rw-r--r-- | libnetdata/locks/locks.h (renamed from src/locks.h) | 6 | ||||
-rw-r--r-- | libnetdata/log/log.c (renamed from src/log.c) | 67 | ||||
-rw-r--r-- | libnetdata/log/log.h (renamed from src/log.h) | 15 | ||||
-rw-r--r-- | libnetdata/popen/popen.c (renamed from src/popen.c) | 8 | ||||
-rw-r--r-- | libnetdata/popen/popen.h (renamed from src/popen.h) | 7 | ||||
-rw-r--r-- | libnetdata/procfile/procfile.c (renamed from src/procfile.c) | 12 | ||||
-rw-r--r-- | libnetdata/procfile/procfile.h (renamed from src/procfile.h) | 30 | ||||
-rw-r--r-- | libnetdata/simple_pattern/simple_pattern.c (renamed from src/simple_pattern.c) | 4 | ||||
-rw-r--r-- | libnetdata/simple_pattern/simple_pattern.h (renamed from src/simple_pattern.h) | 5 | ||||
-rw-r--r-- | libnetdata/socket/socket.c (renamed from src/socket.c) | 64 | ||||
-rw-r--r-- | libnetdata/socket/socket.h (renamed from src/socket.h) | 9 | ||||
-rw-r--r-- | libnetdata/statistical/statistical.c (renamed from src/statistical.c) | 193 | ||||
-rw-r--r-- | libnetdata/statistical/statistical.h (renamed from src/statistical.h) | 13 | ||||
-rw-r--r-- | libnetdata/storage_number/storage_number.c (renamed from src/storage_number.c) | 4 | ||||
-rw-r--r-- | libnetdata/storage_number/storage_number.h (renamed from src/storage_number.h) | 6 | ||||
-rw-r--r-- | libnetdata/threads/threads.c (renamed from src/threads.c) | 4 | ||||
-rw-r--r-- | libnetdata/threads/threads.h (renamed from src/threads.h) | 6 | ||||
-rw-r--r-- | libnetdata/url/url.c (renamed from src/url.c) | 8 | ||||
-rw-r--r-- | libnetdata/url/url.h (renamed from src/url.h) | 4 | ||||
-rw-r--r-- | registry/registry.c (renamed from src/registry.c) | 3 | ||||
-rw-r--r-- | registry/registry.h (renamed from src/registry.h) | 4 | ||||
-rw-r--r-- | registry/registry_db.c (renamed from src/registry_db.c) | 3 | ||||
-rw-r--r-- | registry/registry_init.c (renamed from src/registry_init.c) | 3 | ||||
-rw-r--r-- | registry/registry_internals.c (renamed from src/registry_internals.c) | 3 | ||||
-rw-r--r-- | registry/registry_internals.h (renamed from src/registry_internals.h) | 6 | ||||
-rw-r--r-- | registry/registry_log.c (renamed from src/registry_log.c) | 3 | ||||
-rw-r--r-- | registry/registry_machine.c (renamed from src/registry_machine.c) | 3 | ||||
-rw-r--r-- | registry/registry_machine.h (renamed from src/registry_machine.h) | 4 | ||||
-rw-r--r-- | registry/registry_person.c (renamed from src/registry_person.c) | 3 | ||||
-rw-r--r-- | registry/registry_person.h (renamed from src/registry_person.h) | 4 | ||||
-rw-r--r-- | registry/registry_url.c (renamed from src/registry_url.c) | 3 | ||||
-rw-r--r-- | registry/registry_url.h (renamed from src/registry_url.h) | 4 | ||||
-rw-r--r-- | src/Makefile.am | 307 | ||||
-rw-r--r-- | src/Makefile.in | 1238 | ||||
-rw-r--r-- | src/appconfig.h | 74 | ||||
-rw-r--r-- | src/backend_prometheus.h | 11 | ||||
-rw-r--r-- | src/backends.h | 30 | ||||
-rw-r--r-- | src/clocks.c | 137 | ||||
-rw-r--r-- | src/health.h | 438 | ||||
-rw-r--r-- | src/ipc.h | 7 | ||||
-rw-r--r-- | src/plugin_checks.h | 8 | ||||
-rw-r--r-- | src/plugin_freebsd.h | 130 | ||||
-rw-r--r-- | src/plugin_idlejitter.h | 6 | ||||
-rw-r--r-- | src/plugin_macos.h | 14 | ||||
-rw-r--r-- | src/plugin_nfacct.h | 7 | ||||
-rw-r--r-- | src/plugin_proc_diskspace.h | 6 | ||||
-rw-r--r-- | src/plugin_tc.h | 7 | ||||
-rw-r--r-- | src/rrd2json.c | 2059 | ||||
-rw-r--r-- | src/rrd2json.h | 82 | ||||
-rw-r--r-- | src/rrd2json_api_old.c | 487 | ||||
-rw-r--r-- | src/rrd2json_api_old.h | 14 | ||||
-rw-r--r-- | src/statsd.h | 9 | ||||
-rw-r--r-- | src/web_api_old.c | 237 | ||||
-rw-r--r-- | src/web_api_old.h | 13 | ||||
-rw-r--r-- | src/web_server.c | 1292 | ||||
-rw-r--r-- | streaming/rrdpush.c (renamed from src/rrdpush.c) | 157 | ||||
-rw-r--r-- | streaming/rrdpush.h (renamed from src/rrdpush.h) | 12 | ||||
-rw-r--r-- | web/api/badges/web_buffer_svg.c (renamed from src/web_buffer_svg.c) | 458 | ||||
-rw-r--r-- | web/api/badges/web_buffer_svg.h (renamed from src/web_buffer_svg.h) | 9 | ||||
-rw-r--r-- | web/api/web_api_v1.c (renamed from src/web_api_v1.c) | 396 | ||||
-rw-r--r-- | web/api/web_api_v1.h (renamed from src/web_api_v1.h) | 11 | ||||
-rw-r--r-- | web/server/web_client.c (renamed from src/web_client.c) | 85 | ||||
-rw-r--r-- | web/server/web_client.h (renamed from src/web_client.h) | 12 | ||||
-rw-r--r-- | web/server/web_server.h (renamed from src/web_server.h) | 28 |
164 files changed, 5485 insertions, 10624 deletions
diff --git a/src/backends.c b/backends/backends.c index 1360638f..53a9a239 100644 --- a/src/backends.c +++ b/backends/backends.c @@ -1,4 +1,7 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#define BACKENDS_INTERNALS +#include "backends.h" // ---------------------------------------------------------------------------- // How backends work in netdata: @@ -22,15 +25,14 @@ // 5. repeats the above forever. // -const char *backend_prefix = "netdata"; -int backend_send_names = 1; -int backend_update_every = 10; -uint32_t backend_options = BACKEND_SOURCE_DATA_AVERAGE; +const char *global_backend_prefix = "netdata"; +int global_backend_update_every = 10; +BACKEND_OPTIONS global_backend_options = BACKEND_SOURCE_DATA_AVERAGE | BACKEND_OPTION_SEND_NAMES; // ---------------------------------------------------------------------------- // helper functions for backends -static inline size_t backend_name_copy(char *d, const char *s, size_t usable) { +size_t backend_name_copy(char *d, const char *s, size_t usable) { size_t n; for(n = 0; *s && n < usable ; d++, s++, n++) { @@ -47,16 +49,17 @@ static inline size_t backend_name_copy(char *d, const char *s, size_t usable) { // calculate the SUM or AVERAGE of a dimension, for any timeframe // may return NAN if the database does not have any value in the give timeframe -inline calculated_number backend_calculate_value_from_stored_data( +calculated_number backend_calculate_value_from_stored_data( RRDSET *st // the chart , RRDDIM *rd // the dimension , time_t after // the start timestamp , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap , time_t *first_timestamp // the first point of the database used in this response , time_t *last_timestamp // the timestamp that should be reported to backend ) { RRDHOST *host = st->rrdhost; + (void)host; // find the edges of the rrd database for this chart time_t first_t = rrdset_first_entry_t(st); @@ -132,7 +135,7 @@ inline calculated_number backend_calculate_value_from_stored_data( return NAN; } - if(unlikely((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM)) + if(unlikely(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_SUM)) return sum; return sum / (calculated_number)counter; @@ -142,7 +145,7 @@ inline calculated_number backend_calculate_value_from_stored_data( // discard a response received by a backend // after logging a simple of it to error.log -static inline int discard_response(BUFFER *b, const char *backend) { +int discard_response(BUFFER *b, const char *backend) { char sample[1024]; const char *s = buffer_tostring(b); char *d = sample, *e = &sample[sizeof(sample) - 1]; @@ -161,328 +164,14 @@ static inline int discard_response(BUFFER *b, const char *backend) { // ---------------------------------------------------------------------------- -// graphite backend - -static inline int format_dimension_collected_graphite_plaintext( - BUFFER *b // the buffer to write data to - , const char *prefix // the prefix to use - , RRDHOST *host // the host this chart comes from - , const char *hostname // the hostname (to override host->hostname) - , RRDSET *st // the chart - , RRDDIM *rd // the dimension - , time_t after // the start timestamp - , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap -) { - (void)host; - (void)after; - (void)before; - (void)options; - - char chart_name[RRD_ID_LENGTH_MAX + 1]; - char dimension_name[RRD_ID_LENGTH_MAX + 1]; - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX); - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX); - - buffer_sprintf( - b - , "%s.%s.%s.%s " COLLECTED_NUMBER_FORMAT " %u\n" - , prefix - , hostname - , chart_name - , dimension_name - , rd->last_collected_value - , (uint32_t)rd->last_collected_time.tv_sec - ); - - return 1; -} - -static inline int format_dimension_stored_graphite_plaintext( - BUFFER *b // the buffer to write data to - , const char *prefix // the prefix to use - , RRDHOST *host // the host this chart comes from - , const char *hostname // the hostname (to override host->hostname) - , RRDSET *st // the chart - , RRDDIM *rd // the dimension - , time_t after // the start timestamp - , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap -) { - (void)host; - - char chart_name[RRD_ID_LENGTH_MAX + 1]; - char dimension_name[RRD_ID_LENGTH_MAX + 1]; - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX); - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX); - - time_t first_t = after, last_t = before; - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t); - - if(!isnan(value)) { - - buffer_sprintf( - b - , "%s.%s.%s.%s " CALCULATED_NUMBER_FORMAT " %u\n" - , prefix - , hostname - , chart_name - , dimension_name - , value - , (uint32_t) last_t - ); - - return 1; - } - return 0; -} - -static inline int process_graphite_response(BUFFER *b) { - return discard_response(b, "graphite"); -} - - -// ---------------------------------------------------------------------------- -// opentsdb backend - -static inline int format_dimension_collected_opentsdb_telnet( - BUFFER *b // the buffer to write data to - , const char *prefix // the prefix to use - , RRDHOST *host // the host this chart comes from - , const char *hostname // the hostname (to override host->hostname) - , RRDSET *st // the chart - , RRDDIM *rd // the dimension - , time_t after // the start timestamp - , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap -) { - (void)host; - (void)after; - (void)before; - (void)options; - - char chart_name[RRD_ID_LENGTH_MAX + 1]; - char dimension_name[RRD_ID_LENGTH_MAX + 1]; - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX); - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX); - - buffer_sprintf( - b - , "put %s.%s.%s %u " COLLECTED_NUMBER_FORMAT " host=%s%s%s\n" - , prefix - , chart_name - , dimension_name - , (uint32_t)rd->last_collected_time.tv_sec - , rd->last_collected_value - , hostname - , (host->tags)?" ":"" - , (host->tags)?host->tags:"" - ); - - return 1; -} - -static inline int format_dimension_stored_opentsdb_telnet( - BUFFER *b // the buffer to write data to - , const char *prefix // the prefix to use - , RRDHOST *host // the host this chart comes from - , const char *hostname // the hostname (to override host->hostname) - , RRDSET *st // the chart - , RRDDIM *rd // the dimension - , time_t after // the start timestamp - , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap -) { - (void)host; - - time_t first_t = after, last_t = before; - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t); - - char chart_name[RRD_ID_LENGTH_MAX + 1]; - char dimension_name[RRD_ID_LENGTH_MAX + 1]; - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX); - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX); - - if(!isnan(value)) { - - buffer_sprintf( - b - , "put %s.%s.%s %u " CALCULATED_NUMBER_FORMAT " host=%s%s%s\n" - , prefix - , chart_name - , dimension_name - , (uint32_t) last_t - , value - , hostname - , (host->tags)?" ":"" - , (host->tags)?host->tags:"" - ); - - return 1; - } - return 0; -} - -static inline int process_opentsdb_response(BUFFER *b) { - return discard_response(b, "opentsdb"); -} - - -// ---------------------------------------------------------------------------- -// json backend - -static inline int format_dimension_collected_json_plaintext( - BUFFER *b // the buffer to write data to - , const char *prefix // the prefix to use - , RRDHOST *host // the host this chart comes from - , const char *hostname // the hostname (to override host->hostname) - , RRDSET *st // the chart - , RRDDIM *rd // the dimension - , time_t after // the start timestamp - , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap -) { - (void)host; - (void)after; - (void)before; - (void)options; - - const char *tags_pre = "", *tags_post = "", *tags = host->tags; - if(!tags) tags = ""; - - if(*tags) { - if(*tags == '{' || *tags == '[' || *tags == '"') { - tags_pre = "\"host_tags\":"; - tags_post = ","; - } - else { - tags_pre = "\"host_tags\":\""; - tags_post = "\","; - } - } - - buffer_sprintf(b, "{" - "\"prefix\":\"%s\"," - "\"hostname\":\"%s\"," - "%s%s%s" - - "\"chart_id\":\"%s\"," - "\"chart_name\":\"%s\"," - "\"chart_family\":\"%s\"," - "\"chart_context\": \"%s\"," - "\"chart_type\":\"%s\"," - "\"units\": \"%s\"," - - "\"id\":\"%s\"," - "\"name\":\"%s\"," - "\"value\":" COLLECTED_NUMBER_FORMAT "," - - "\"timestamp\": %u}\n", - prefix, - hostname, - tags_pre, tags, tags_post, - - st->id, - st->name, - st->family, - st->context, - st->type, - st->units, - - rd->id, - rd->name, - rd->last_collected_value, - - (uint32_t)rd->last_collected_time.tv_sec - ); - - return 1; -} - -static inline int format_dimension_stored_json_plaintext( - BUFFER *b // the buffer to write data to - , const char *prefix // the prefix to use - , RRDHOST *host // the host this chart comes from - , const char *hostname // the hostname (to override host->hostname) - , RRDSET *st // the chart - , RRDDIM *rd // the dimension - , time_t after // the start timestamp - , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap -) { - (void)host; - - time_t first_t = after, last_t = before; - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t); - - if(!isnan(value)) { - const char *tags_pre = "", *tags_post = "", *tags = host->tags; - if(!tags) tags = ""; - - if(*tags) { - if(*tags == '{' || *tags == '[' || *tags == '"') { - tags_pre = "\"host_tags\":"; - tags_post = ","; - } - else { - tags_pre = "\"host_tags\":\""; - tags_post = "\","; - } - } - - buffer_sprintf(b, "{" - "\"prefix\":\"%s\"," - "\"hostname\":\"%s\"," - "%s%s%s" - - "\"chart_id\":\"%s\"," - "\"chart_name\":\"%s\"," - "\"chart_family\":\"%s\"," - "\"chart_context\": \"%s\"," - "\"chart_type\":\"%s\"," - "\"units\": \"%s\"," - - "\"id\":\"%s\"," - "\"name\":\"%s\"," - "\"value\":" CALCULATED_NUMBER_FORMAT "," - - "\"timestamp\": %u}\n", - prefix, - hostname, - tags_pre, tags, tags_post, - - st->id, - st->name, - st->family, - st->context, - st->type, - st->units, - - rd->id, - rd->name, - value, - - (uint32_t) last_t - ); - - return 1; - } - return 0; -} - -static inline int process_json_response(BUFFER *b) { - return discard_response(b, "json"); -} - - -// ---------------------------------------------------------------------------- // the backend thread static SIMPLE_PATTERN *charts_pattern = NULL; static SIMPLE_PATTERN *hosts_pattern = NULL; -inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) { +inline int backends_can_send_rrdset(BACKEND_OPTIONS backend_options, RRDSET *st) { RRDHOST *host = st->rrdhost; + (void)host; if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_BACKEND_IGNORE))) return 0; @@ -503,7 +192,7 @@ inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) { return 0; } - if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE && !((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED))) { + if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE && !(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED))) { debug(D_BACKEND, "BACKEND: not sending chart '%s' of host '%s' because its memory mode is '%s' and the backend requires database access.", st->id, host->hostname, rrd_memory_mode_name(host->rrd_memory_mode)); return 0; } @@ -511,24 +200,24 @@ inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) { return 1; } -inline uint32_t backend_parse_data_source(const char *source, uint32_t mode) { +inline BACKEND_OPTIONS backend_parse_data_source(const char *source, BACKEND_OPTIONS backend_options) { if(!strcmp(source, "raw") || !strcmp(source, "as collected") || !strcmp(source, "as-collected") || !strcmp(source, "as_collected") || !strcmp(source, "ascollected")) { - mode |= BACKEND_SOURCE_DATA_AS_COLLECTED; - mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AS_COLLECTED); + backend_options |= BACKEND_SOURCE_DATA_AS_COLLECTED; + backend_options &= ~(BACKEND_OPTIONS_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AS_COLLECTED); } else if(!strcmp(source, "average")) { - mode |= BACKEND_SOURCE_DATA_AVERAGE; - mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AVERAGE); + backend_options |= BACKEND_SOURCE_DATA_AVERAGE; + backend_options &= ~(BACKEND_OPTIONS_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AVERAGE); } else if(!strcmp(source, "sum") || !strcmp(source, "volume")) { - mode |= BACKEND_SOURCE_DATA_SUM; - mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_SUM); + backend_options |= BACKEND_SOURCE_DATA_SUM; + backend_options &= ~(BACKEND_OPTIONS_SOURCE_BITS ^ BACKEND_SOURCE_DATA_SUM); } else { error("BACKEND: invalid data source method '%s'.", source); } - return mode; + return backend_options; } static void backends_main_cleanup(void *ptr) { @@ -546,7 +235,7 @@ void *backends_main(void *ptr) { int default_port = 0; int sock = -1; BUFFER *b = buffer_create(1), *response = buffer_create(1); - int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, uint32_t) = NULL; + int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, BACKEND_OPTIONS) = NULL; int (*backend_response_checker)(BUFFER *) = NULL; // ------------------------------------------------------------------------ @@ -556,35 +245,39 @@ void *backends_main(void *ptr) { .tv_sec = 0, .tv_usec = 0 }; - int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0); - const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average"); - const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite"); - const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost"); - backend_prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata"); - const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname); - backend_update_every = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", backend_update_every); - int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10); - long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", backend_update_every * 2 * 1000); - backend_send_names = config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", backend_send_names); + int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0); + const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average"); + const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite"); + const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost"); + global_backend_prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata"); + const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname); + global_backend_update_every = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", global_backend_update_every); + int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10); + long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", global_backend_update_every * 2 * 1000); + + if(config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", (global_backend_options & BACKEND_OPTION_SEND_NAMES))) + global_backend_options |= BACKEND_OPTION_SEND_NAMES; + else + global_backend_options &= ~BACKEND_OPTION_SEND_NAMES; charts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send charts matching", "*"), NULL, SIMPLE_PATTERN_EXACT); - hosts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send hosts matching", "localhost *"), NULL, SIMPLE_PATTERN_EXACT); + hosts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send hosts matching", "localhost *"), NULL, SIMPLE_PATTERN_EXACT); // ------------------------------------------------------------------------ // validate configuration options // and prepare for sending data to our backend - backend_options = backend_parse_data_source(source, backend_options); + global_backend_options = backend_parse_data_source(source, global_backend_options); if(timeoutms < 1) { - error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, backend_update_every * 2 * 1000); - timeoutms = backend_update_every * 2 * 1000; + error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, global_backend_update_every * 2 * 1000); + timeoutms = global_backend_update_every * 2 * 1000; } timeout.tv_sec = (timeoutms * 1000) / 1000000; timeout.tv_usec = (timeoutms * 1000) % 1000000; - if(!enabled || backend_update_every < 1) + if(!enabled || global_backend_update_every < 1) goto cleanup; // ------------------------------------------------------------------------ @@ -595,7 +288,7 @@ void *backends_main(void *ptr) { default_port = 2003; backend_response_checker = process_graphite_response; - if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) + if(BACKEND_OPTIONS_DATA_SOURCE(global_backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED) backend_request_formatter = format_dimension_collected_graphite_plaintext; else backend_request_formatter = format_dimension_stored_graphite_plaintext; @@ -606,7 +299,7 @@ void *backends_main(void *ptr) { default_port = 4242; backend_response_checker = process_opentsdb_response; - if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) + if(BACKEND_OPTIONS_DATA_SOURCE(global_backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED) backend_request_formatter = format_dimension_collected_opentsdb_telnet; else backend_request_formatter = format_dimension_stored_opentsdb_telnet; @@ -617,7 +310,7 @@ void *backends_main(void *ptr) { default_port = 5448; backend_response_checker = process_json_response; - if ((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) + if (BACKEND_OPTIONS_DATA_SOURCE(global_backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED) backend_request_formatter = format_dimension_collected_json_plaintext; else backend_request_formatter = format_dimension_stored_json_plaintext; @@ -651,21 +344,21 @@ void *backends_main(void *ptr) { chart_transmission_failures = 0, chart_data_lost_events = 0, chart_lost_bytes = 0, - chart_backend_reconnects = 0, - chart_backend_latency = 0; + chart_backend_reconnects = 0; + // chart_backend_latency = 0; - RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, backend_update_every, RRDSET_TYPE_LINE); + RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, global_backend_update_every, RRDSET_TYPE_LINE); rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, backend_update_every, RRDSET_TYPE_AREA); + RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, global_backend_update_every, RRDSET_TYPE_AREA); rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); - RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_LINE); + RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, global_backend_update_every, RRDSET_TYPE_LINE); rrddim_add(chart_ops, "write", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "discard", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); @@ -679,11 +372,11 @@ void *backends_main(void *ptr) { * * issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html * - RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, backend_update_every, RRDSET_TYPE_AREA); + RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, global_backend_update_every, RRDSET_TYPE_AREA); rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); */ - RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_STACKED); + RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, global_backend_update_every, RRDSET_TYPE_STACKED); rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); @@ -691,9 +384,9 @@ void *backends_main(void *ptr) { // ------------------------------------------------------------------------ // prepare the backend main loop - info("BACKEND: configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, backend_update_every, hostname, backend_prefix); + info("BACKEND: configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, global_backend_update_every, hostname, global_backend_prefix); - usec_t step_ut = backend_update_every * USEC_PER_SEC; + usec_t step_ut = global_backend_update_every * USEC_PER_SEC; time_t after = now_realtime_sec(); int failures = 0; heartbeat_t hb; @@ -746,7 +439,7 @@ void *backends_main(void *ptr) { RRDSET *st; rrdset_foreach_read(st, host) { - if(likely(backends_can_send_rrdset(backend_options, st))) { + if(likely(backends_can_send_rrdset(global_backend_options, st))) { rrdset_rdlock(st); count_charts++; @@ -754,7 +447,7 @@ void *backends_main(void *ptr) { RRDDIM *rd; rrddim_foreach_read(rd, st) { if (likely(rd->last_collected_time.tv_sec >= after)) { - chart_buffered_metrics += backend_request_formatter(b, backend_prefix, host, __hostname, st, rd, after, before, backend_options); + chart_buffered_metrics += backend_request_formatter(b, global_backend_prefix, host, __hostname, st, rd, after, before, global_backend_options); count_dims++; } else { @@ -792,12 +485,12 @@ void *backends_main(void *ptr) { chart_transmission_failures = chart_data_lost_events = chart_lost_bytes = - chart_backend_reconnects = - chart_backend_latency = 0; + chart_backend_reconnects = 0; + // chart_backend_latency = 0; if(unlikely(netdata_exit)) break; - //fprintf(stderr, "\nBACKEND BEGIN:\n%s\nBACKEND END\n", buffer_tostring(b)); // FIXME + //fprintf(stderr, "\nBACKEND BEGIN:\n%s\nBACKEND END\n", buffer_tostring(b)); //fprintf(stderr, "after = %lu, before = %lu\n", after, before); // prepare for the next iteration @@ -843,13 +536,13 @@ void *backends_main(void *ptr) { // if we are not connected, connect to a backend server if(unlikely(sock == -1)) { - usec_t start_ut = now_monotonic_usec(); + // usec_t start_ut = now_monotonic_usec(); size_t reconnects = 0; sock = connect_to_one_of(destination, default_port, &timeout, &reconnects, NULL, 0); chart_backend_reconnects += reconnects; - chart_backend_latency += now_monotonic_usec() - start_ut; + // chart_backend_latency += now_monotonic_usec() - start_ut; } if(unlikely(netdata_exit)) break; @@ -859,14 +552,14 @@ void *backends_main(void *ptr) { if(likely(sock != -1)) { size_t len = buffer_strlen(b); - usec_t start_ut = now_monotonic_usec(); + // usec_t start_ut = now_monotonic_usec(); int flags = 0; #ifdef MSG_NOSIGNAL flags += MSG_NOSIGNAL; #endif ssize_t written = send(sock, buffer_tostring(b), len, flags); - chart_backend_latency += now_monotonic_usec() - start_ut; + // chart_backend_latency += now_monotonic_usec() - start_ut; if(written != -1 && (size_t)written == len) { // we sent the data successfully chart_transmission_successes++; diff --git a/src/backend_prometheus.c b/backends/prometheus/backend_prometheus.c index bfcda929..223b3f9f 100644 --- a/src/backend_prometheus.c +++ b/backends/prometheus/backend_prometheus.c @@ -1,4 +1,7 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#define BACKENDS_INTERNALS +#include "backend_prometheus.h" // ---------------------------------------------------------------------------- // PROMETHEUS @@ -109,8 +112,77 @@ static inline char *prometheus_units_copy(char *d, const char *s, size_t usable) #define PROMETHEUS_ELEMENT_MAX 256 #define PROMETHEUS_LABELS_MAX 1024 +#define PROMETHEUS_VARIABLE_MAX 256 + +struct host_variables_callback_options { + RRDHOST *host; + BUFFER *wb; + BACKEND_OPTIONS backend_options; + PROMETHEUS_OUTPUT_OPTIONS output_options; + const char *prefix; + const char *labels; + time_t now; + int host_header_printed; + char name[PROMETHEUS_VARIABLE_MAX+1]; +}; + +static int print_host_variables(RRDVAR *rv, void *data) { + struct host_variables_callback_options *opts = data; + + if(rv->options & (RRDVAR_OPTION_CUSTOM_HOST_VAR|RRDVAR_OPTION_CUSTOM_CHART_VAR)) { + if(!opts->host_header_printed) { + opts->host_header_printed = 1; + + if(opts->output_options & PROMETHEUS_OUTPUT_HELP) { + buffer_sprintf(opts->wb, "\n# COMMENT global host and chart variables\n"); + } + } + + calculated_number value = rrdvar2number(rv); + if(isnan(value) || isinf(value)) { + if(opts->output_options & PROMETHEUS_OUTPUT_HELP) + buffer_sprintf(opts->wb, "# COMMENT variable \"%s\" is %s. Skipped.\n", rv->name, (isnan(value))?"NAN":"INF"); + + return 0; + } + + char *label_pre = ""; + char *label_post = ""; + if(opts->labels && *opts->labels) { + label_pre = "{"; + label_post = "}"; + } -static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb, const char *prefix, uint32_t options, time_t after, time_t before, int allhosts, int help, int types, int names, int timestamps) { + prometheus_name_copy(opts->name, rv->name, sizeof(opts->name)); + + if(opts->output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) + buffer_sprintf(opts->wb + , "%s_%s%s%s%s " CALCULATED_NUMBER_FORMAT " %llu\n" + , opts->prefix + , opts->name + , label_pre + , opts->labels + , label_post + , value + , ((rv->last_updated) ? rv->last_updated : opts->now) * 1000ULL + ); + else + buffer_sprintf(opts->wb, "%s_%s%s%s%s " CALCULATED_NUMBER_FORMAT "\n" + , opts->prefix + , opts->name + , label_pre + , opts->labels + , label_post + , value + ); + + return 1; + } + + return 0; +} + +static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb, const char *prefix, BACKEND_OPTIONS backend_options, time_t after, time_t before, int allhosts, PROMETHEUS_OUTPUT_OPTIONS output_options) { rrdhost_rdlock(host); char hostname[PROMETHEUS_ELEMENT_MAX + 1]; @@ -118,13 +190,13 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER char labels[PROMETHEUS_LABELS_MAX + 1] = ""; if(allhosts) { - if(timestamps) + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1 %llu\n", hostname, host->program_name, host->program_version, now_realtime_usec() / USEC_PER_MS); else buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1\n", hostname, host->program_name, host->program_version); if(host->tags && *(host->tags)) { - if(timestamps) { + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) { buffer_sprintf(wb, "netdata_host_tags_info{instance=\"%s\",%s} 1 %llu\n", hostname, host->tags, now_realtime_usec() / USEC_PER_MS); // deprecated, exists only for compatibility with older queries @@ -142,13 +214,13 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER snprintfz(labels, PROMETHEUS_LABELS_MAX, ",instance=\"%s\"", hostname); } else { - if(timestamps) + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1 %llu\n", hostname, host->program_name, host->program_version, now_realtime_usec() / USEC_PER_MS); else buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1\n", hostname, host->program_name, host->program_version); if(host->tags && *(host->tags)) { - if(timestamps) { + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) { buffer_sprintf(wb, "netdata_host_tags_info{%s} 1 %llu\n", host->tags, now_realtime_usec() / USEC_PER_MS); // deprecated, exists only for compatibility with older queries @@ -163,6 +235,21 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER } } + // send custom variables set for the host + if(output_options & PROMETHEUS_OUTPUT_VARIABLES){ + struct host_variables_callback_options opts = { + .host = host, + .wb = wb, + .labels = (labels[0] == ',')?&labels[1]:labels, + .backend_options = backend_options, + .output_options = output_options, + .prefix = prefix, + .now = now_realtime_sec(), + .host_header_printed = 0 + }; + foreach_host_variable_callback(host, print_host_variables, &opts); + } + // for each chart RRDSET *st; rrdset_foreach_read(st, host) { @@ -171,14 +258,14 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER char family[PROMETHEUS_ELEMENT_MAX + 1]; char units[PROMETHEUS_ELEMENT_MAX + 1] = ""; - prometheus_label_copy(chart, (names && st->name)?st->name:st->id, PROMETHEUS_ELEMENT_MAX); + prometheus_label_copy(chart, (output_options & PROMETHEUS_OUTPUT_NAMES && st->name)?st->name:st->id, PROMETHEUS_ELEMENT_MAX); prometheus_label_copy(family, st->family, PROMETHEUS_ELEMENT_MAX); prometheus_name_copy(context, st->context, PROMETHEUS_ELEMENT_MAX); - if(likely(backends_can_send_rrdset(options, st))) { + if(likely(backends_can_send_rrdset(backend_options, st))) { rrdset_rdlock(st); - int as_collected = ((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED); + int as_collected = (BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED); int homogeneus = 1; if(as_collected) { if(rrdset_flag_check(st, RRDSET_FLAG_HOMEGENEOUS_CHECK)) @@ -188,14 +275,14 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER homogeneus = 0; } else { - if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE) + if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AVERAGE) prometheus_units_copy(units, st->units, PROMETHEUS_ELEMENT_MAX); } - if(unlikely(help)) + if(unlikely(output_options & PROMETHEUS_OUTPUT_HELP)) buffer_sprintf(wb, "\n# COMMENT %s chart \"%s\", context \"%s\", family \"%s\", units \"%s\"\n" , (homogeneus)?"homogeneus":"heterogeneous" - , (names && st->name) ? st->name : st->id + , (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? st->name : st->id , st->context , st->family , st->units @@ -223,18 +310,18 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER // all the dimensions of the chart, has the same algorithm, multiplier and divisor // we add all dimensions as labels - prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX); + prometheus_label_copy(dimension, (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX); - if(unlikely(help)) + if(unlikely(output_options & PROMETHEUS_OUTPUT_HELP)) buffer_sprintf(wb , "# COMMENT %s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n" , prefix , context , suffix - , (names && st->name) ? st->name : st->id + , (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? st->name : st->id , st->context , st->family - , (names && rd->name) ? rd->name : rd->id + , (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id , rd->multiplier , rd->divisor , h @@ -242,7 +329,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER , t ); - if(unlikely(types)) + if(unlikely(output_options & PROMETHEUS_OUTPUT_TYPES)) buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s %s\n" , prefix , context @@ -250,7 +337,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER , t ); - if(timestamps) + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) buffer_sprintf(wb , "%s_%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n" , prefix @@ -280,19 +367,19 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER // the dimensions of the chart, do not have the same algorithm, multiplier or divisor // we create a metric per dimension - prometheus_name_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX); + prometheus_name_copy(dimension, (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX); - if(unlikely(help)) + if(unlikely(output_options & PROMETHEUS_OUTPUT_HELP)) buffer_sprintf(wb , "# COMMENT %s_%s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n" , prefix , context , dimension , suffix - , (names && st->name) ? st->name : st->id + , (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? st->name : st->id , st->context , st->family - , (names && rd->name) ? rd->name : rd->id + , (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id , rd->multiplier , rd->divisor , h @@ -300,7 +387,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER , t ); - if(unlikely(types)) + if(unlikely(output_options & PROMETHEUS_OUTPUT_TYPES)) buffer_sprintf(wb, "# COMMENT TYPE %s_%s_%s%s %s\n" , prefix , context @@ -309,7 +396,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER , t ); - if(timestamps) + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) buffer_sprintf(wb , "%s_%s_%s%s{chart=\"%s\",family=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n" , prefix @@ -340,30 +427,30 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER // we need average or sum of the data time_t first_t = after, last_t = before; - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t); + calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, backend_options, &first_t, &last_t); if(!isnan(value) && !isinf(value)) { - if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE) + if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AVERAGE) suffix = "_average"; - else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM) + else if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_SUM) suffix = "_sum"; - prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX); + prometheus_label_copy(dimension, (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX); - if (unlikely(help)) + if (unlikely(output_options & PROMETHEUS_OUTPUT_HELP)) buffer_sprintf(wb, "# COMMENT %s_%s%s%s: dimension \"%s\", value is %s, gauge, dt %llu to %llu inclusive\n" , prefix , context , units , suffix - , (names && rd->name) ? rd->name : rd->id + , (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id , st->units , (unsigned long long)first_t , (unsigned long long)last_t ); - if (unlikely(types)) + if (unlikely(output_options & PROMETHEUS_OUTPUT_TYPES)) buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s%s gauge\n" , prefix , context @@ -371,7 +458,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER , suffix ); - if(timestamps) + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) buffer_sprintf(wb, "%s_%s%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " CALCULATED_NUMBER_FORMAT " %llu\n" , prefix , context @@ -408,32 +495,32 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER rrdhost_unlock(host); } -static inline time_t prometheus_preparation(RRDHOST *host, BUFFER *wb, uint32_t options, const char *server, time_t now, int help) { +static inline time_t prometheus_preparation(RRDHOST *host, BUFFER *wb, BACKEND_OPTIONS backend_options, const char *server, time_t now, PROMETHEUS_OUTPUT_OPTIONS output_options) { if(!server || !*server) server = "default"; time_t after = prometheus_server_last_access(server, host, now); int first_seen = 0; if(!after) { - after = now - backend_update_every; + after = now - global_backend_update_every; first_seen = 1; } if(after > now) { // oops! this should never happen - after = now - backend_update_every; + after = now - global_backend_update_every; } - if(help) { + if(output_options & PROMETHEUS_OUTPUT_HELP) { int show_range = 1; char *mode; - if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) { + if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED) { mode = "as collected"; show_range = 0; } - else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE) + else if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AVERAGE) mode = "average"; - else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM) + else if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_SUM) mode = "sum"; else mode = "unknown"; @@ -456,24 +543,24 @@ static inline time_t prometheus_preparation(RRDHOST *host, BUFFER *wb, uint32_t return after; } -void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps) { +void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, BACKEND_OPTIONS backend_options, PROMETHEUS_OUTPUT_OPTIONS output_options) { time_t before = now_realtime_sec(); // we start at the point we had stopped before - time_t after = prometheus_preparation(host, wb, options, server, before, help); + time_t after = prometheus_preparation(host, wb, backend_options, server, before, output_options); - rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, options, after, before, 0, help, types, names, timestamps); + rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, backend_options, after, before, 0, output_options); } -void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps) { +void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, BACKEND_OPTIONS backend_options, PROMETHEUS_OUTPUT_OPTIONS output_options) { time_t before = now_realtime_sec(); // we start at the point we had stopped before - time_t after = prometheus_preparation(host, wb, options, server, before, help); + time_t after = prometheus_preparation(host, wb, backend_options, server, before, output_options); rrd_rdlock(); rrdhost_foreach_read(host) { - rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, options, after, before, 1, help, types, names, timestamps); + rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, backend_options, after, before, 1, output_options); } rrd_unlock(); } diff --git a/src/apps_plugin.c b/collectors/apps.plugin/apps_plugin.c index 8595da6c..f592e9fc 100644 --- a/src/apps_plugin.c +++ b/collectors/apps.plugin/apps_plugin.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0-or-later /* * netdata apps.plugin @@ -5,7 +6,61 @@ * Released under GPL v3+ */ -#include "common.h" +#include "../../libnetdata/libnetdata.h" + +// ---------------------------------------------------------------------------- + +// callback required by fatal() +void netdata_cleanup_and_exit(int ret) { + exit(ret); +} + +// callbacks required by popen() +void signals_block(void) {}; +void signals_unblock(void) {}; +void signals_reset(void) {}; + +// callback required by eval() +int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) { + (void)variable; + (void)hash; + (void)rc; + (void)result; + return 0; +}; + +// required by get_system_cpus() +char *netdata_configured_host_prefix = ""; + + +// ---------------------------------------------------------------------------- +// debugging + +static int debug_enabled = 0; +static inline void debug_log_int(const char *fmt, ... ) { + va_list args; + + fprintf( stderr, "apps.plugin: "); + va_start( args, fmt ); + vfprintf( stderr, fmt, args ); + va_end( args ); + + fputc('\n', stderr); +} + +#ifdef NETDATA_INTERNAL_CHECKS + +#define debug_log(fmt, args...) do { if(unlikely(debug_enabled)) debug_log_int(fmt, ##args); } while(0) + +#else + +static inline void debug_log_dummy(void) {} +#define debug_log(fmt, args...) debug_log_dummy() + +#endif + + +// ---------------------------------------------------------------------------- #ifdef __FreeBSD__ #include <sys/user.h> @@ -57,21 +112,21 @@ // command line options static int - debug = 0, update_every = 1, enable_guest_charts = 0, #ifdef __FreeBSD__ enable_file_charts = 0, #else enable_file_charts = 1, + max_fds_cache_seconds = 60, #endif enable_users_charts = 1, enable_groups_charts = 1, include_exited_childs = 1; - -// will be changed to getenv(NETDATA_CONFIG_DIR) if it exists -static char *config_dir = CONFIG_DIR; +// will be changed to getenv(NETDATA_USER_CONFIG_DIR) if it exists +static char *user_config_dir = CONFIG_DIR; +static char *stock_config_dir = LIBCONFIG_DIR; // ---------------------------------------------------------------------------- // internal flags @@ -90,6 +145,9 @@ static size_t global_iterations_counter = 1, calls_counter = 0, file_counter = 0, + filenames_allocated_counter = 0, + inodes_changed_counter = 0, + links_changed_counter = 0, targets_assignment_counter = 0; @@ -193,7 +251,7 @@ struct target { unsigned int processes; // how many processes have been merged to this int exposed; // if set, we have sent this to netdata int hidden; // if set, we set the hidden flag on the dimension - int debug; + int debug_enabled; int ends_with; int starts_with; // if set, the compare string matches only the // beginning of the command @@ -218,6 +276,18 @@ size_t // structure to store data for each process running // see: man proc for the description of the fields +struct pid_fd { + int fd; + +#ifndef __FreeBSD__ + ino_t inode; + char *filename; + uint32_t link_hash; + size_t cache_iterations_counter; + size_t cache_iterations_reset; +#endif +}; + struct pid_stat { int32_t pid; char comm[MAX_COMPARE_NAME + 1]; @@ -312,15 +382,15 @@ struct pid_stat { kernel_uint_t io_storage_bytes_written; // kernel_uint_t io_cancelled_write_bytes; - int *fds; // array of fds it uses - int fds_size; // the size of the fds array + struct pid_fd *fds; // array of fds it uses + size_t fds_size; // the size of the fds array int children_count; // number of processes directly referencing this - char keep:1; // 1 when we need to keep this process in memory even after it exited + unsigned char keep:1; // 1 when we need to keep this process in memory even after it exited int keeploops; // increases by 1 every time keep is 1 and updated 0 - char updated:1; // 1 when the process is currently running - char merged:1; // 1 when it has been merged to its parent - char read:1; // 1 when we have already read this process for this iteration + unsigned char updated:1; // 1 when the process is currently running + unsigned char merged:1; // 1 when it has been merged to its parent + unsigned char read:1; // 1 when we have already read this process for this iteration int sortlist; // higher numbers = top on the process tree // each process gets a unique number @@ -416,13 +486,6 @@ static int all_files_size = 0; // ---------------------------------------------------------------------------- -// callback required by fatal() - -void netdata_cleanup_and_exit(int ret) { - exit(ret); -} - -// ---------------------------------------------------------------------------- // apps_groups.conf // aggregate all processes in groups, to have a limited number of dimensions @@ -452,8 +515,7 @@ static struct target *get_users_target(uid_t uid) { w->next = users_root_target; users_root_target = w; - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: added uid %u ('%s') target\n", w->uid, w->name); + debug_log("added uid %u ('%s') target", w->uid, w->name); return w; } @@ -485,8 +547,7 @@ struct target *get_groups_target(gid_t gid) w->next = groups_root_target; groups_root_target = w; - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: added gid %u ('%s') target\n", w->gid, w->name); + debug_log("added gid %u ('%s') target", w->gid, w->name); return w; } @@ -527,11 +588,11 @@ static struct target *get_apps_groups_target(const char *id, struct target *targ break; } - if(unlikely(debug)) { + if(unlikely(debug_enabled)) { if(unlikely(target)) - fprintf(stderr, "apps.plugin: REUSING TARGET NAME '%s' on ID '%s'\n", target->name, target->id); + debug_log("REUSING TARGET NAME '%s' on ID '%s'", target->name, target->id); else - fprintf(stderr, "apps.plugin: NEW TARGET NAME '%s' on ID '%s'\n", name, id); + debug_log("NEW TARGET NAME '%s' on ID '%s'", name, id); } } @@ -564,34 +625,37 @@ static struct target *get_apps_groups_target(const char *id, struct target *targ w->comparelen = strlen(w->compare); w->hidden = thidden; - w->debug = tdebug; +#ifdef NETDATA_INTERNAL_CHECKS + w->debug_enabled = tdebug; +#else + if(tdebug) + fprintf(stderr, "apps.plugin has been compiled without debugging\n"); +#endif w->target = target; // append it, to maintain the order in apps_groups.conf if(last) last->next = w; else apps_groups_root_target = w; - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: ADDING TARGET ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s\n" - , w->id - , w->compare, (w->starts_with && w->ends_with)?"substring":((w->starts_with)?"prefix":((w->ends_with)?"suffix":"exact")) - , w->target?w->target->name:w->name - , (w->hidden)?"hidden":"-" - , (w->debug)?"debug":"-" - ); + debug_log("ADDING TARGET ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s" + , w->id + , w->compare, (w->starts_with && w->ends_with)?"substring":((w->starts_with)?"prefix":((w->ends_with)?"suffix":"exact")) + , w->target?w->target->name:w->name + , (w->hidden)?"hidden":"-" + , (w->debug_enabled)?"debug":"-" + ); return w; } // read the apps_groups.conf file -static int read_apps_groups_conf(const char *file) +static int read_apps_groups_conf(const char *path, const char *file) { char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", config_dir, file); + snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", path, file); - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: process groups file: '%s'\n", filename); + debug_log("process groups file: '%s'", filename); // ---------------------------------------- @@ -654,14 +718,16 @@ static int read_apps_groups_conf(const char *file) // ---------------------------------------------------------------------------- // struct pid_stat management +static inline void init_pid_fds(struct pid_stat *p, size_t first, size_t size); static inline struct pid_stat *get_pid_entry(pid_t pid) { if(unlikely(all_pids[pid])) return all_pids[pid]; struct pid_stat *p = callocz(sizeof(struct pid_stat), 1); - p->fds = callocz(sizeof(int), MAX_SPARE_FDS); + 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; @@ -685,8 +751,7 @@ static inline void del_pid_entry(pid_t pid) { return; } - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: process %d %s exited, deleting it.\n", pid, p->comm); + debug_log("process %d %s exited, deleting it.", pid, p->comm); if(root_of_pids == p) root_of_pids = p->next; @@ -694,7 +759,17 @@ static inline void del_pid_entry(pid_t pid) { if(p->next) p->next->prev = p->prev; if(p->prev) p->prev->next = p->next; + // free the filename +#ifndef __FreeBSD__ + { + size_t i; + for(i = 0; i < p->fds_size; i++) + if(p->fds[i].filename) + freez(p->fds[i].filename); + } +#endif freez(p->fds); + freez(p->fds_dirname); freez(p->stat_filename); freez(p->status_filename); @@ -716,8 +791,8 @@ static inline int managed_log(struct pid_stat *p, uint32_t log, int status) { if(unlikely(!status)) { // error("command failed log %u, errno %d", log, errno); - if(unlikely(debug || errno != ENOENT)) { - if(unlikely(debug || !(p->log_thrown & log))) { + if(unlikely(debug_enabled || errno != ENOENT)) { + if(unlikely(debug_enabled || !(p->log_thrown & log))) { p->log_thrown |= log; switch(log) { case PID_LOG_IO: @@ -779,7 +854,7 @@ static inline void assign_target_to_pid(struct pid_stat *p) { struct target *w; for(w = apps_groups_root_target; w ; w = w->next) { - // if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \t\tcomparing '%s' with '%s'\n", w->compare, p->comm); + // if(debug_enabled || (p->target && p->target->debug_enabled)) debug_log_int("\t\tcomparing '%s' with '%s'", w->compare, p->comm); // find it - 4 cases: // 1. the target is not a pattern @@ -796,8 +871,8 @@ static inline void assign_target_to_pid(struct pid_stat *p) { if(w->target) p->target = w->target; else p->target = w; - if(debug || (p->target && p->target->debug)) - fprintf(stderr, "apps.plugin: \t\t%s linked to target %s\n", p->comm, p->target->name); + if(debug_enabled || (p->target && p->target->debug_enabled)) + debug_log_int("%s linked to target %s", p->comm, p->target->name); break; } @@ -828,7 +903,7 @@ static inline int read_proc_pid_cmdline(struct pid_stat *p) { p->cmdline_filename = strdupz(filename); } - int fd = open(p->cmdline_filename, O_RDONLY, 0666); + int fd = open(p->cmdline_filename, procfile_open_flags, 0666); if(unlikely(fd == -1)) goto cleanup; ssize_t i, bytes = read(fd, cmdline, MAX_CMDLINE); @@ -838,18 +913,20 @@ static inline int read_proc_pid_cmdline(struct pid_stat *p) { #endif cmdline[bytes] = '\0'; - for(i = 0; i < bytes ; i++) + for(i = 0; i < bytes ; i++) { if(unlikely(!cmdline[i])) cmdline[i] = ' '; + } + if(p->cmdline) freez(p->cmdline); p->cmdline = strdupz(cmdline); - if(unlikely(debug)) - fprintf(stderr, "Read file '%s' contents: %s\n", p->cmdline_filename, p->cmdline); + debug_log("Read file '%s' contents: %s", p->cmdline_filename, p->cmdline); return 1; cleanup: // copy the command to the command line + if(p->cmdline) freez(p->cmdline); p->cmdline = strdupz(p->comm); return 0; } @@ -963,7 +1040,7 @@ static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) { p->gid = proc_info->ki_groups[0]; p->status_vmsize = proc_info->ki_size / 1024; // in kB p->status_vmrss = proc_info->ki_rssize * pagesize / 1024; // in kB - // FIXME: what about shared and swap memory on FreeBSD? + // TODO: what about shared and swap memory on FreeBSD? return 1; #else (void)ptr; @@ -1004,7 +1081,7 @@ static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) { arl_begin(p->status_arl); for(l = 0; l < lines ;l++) { - // fprintf(stderr, "CHECK: line %zu of %zu, key '%s' = '%s'\n", l, lines, procfile_lineword(ff, l, 0), procfile_lineword(ff, l, 1)); + // debug_log("CHECK: line %zu of %zu, key '%s' = '%s'", l, lines, procfile_lineword(ff, l, 0), procfile_lineword(ff, l, 1)); arl_ptr.line = l; if(unlikely(arl_check(p->status_arl, procfile_lineword(ff, l, 0), @@ -1013,7 +1090,7 @@ static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) { p->status_vmshared = p->status_rssfile + p->status_rssshmem; - // fprintf(stderr, "%s uid %d, gid %d, VmSize %zu, VmRSS %zu, RssFile %zu, RssShmem %zu, shared %zu\n", p->comm, (int)p->uid, (int)p->gid, p->status_vmsize, p->status_vmrss, p->status_rssfile, p->status_rssshmem, p->status_vmshared); + // debug_log("%s uid %d, gid %d, VmSize %zu, VmRSS %zu, RssFile %zu, RssShmem %zu, shared %zu", p->comm, (int)p->uid, (int)p->gid, p->status_vmsize, p->status_vmrss, p->status_rssfile, p->status_rssshmem, p->status_vmshared); return 1; #endif @@ -1072,11 +1149,11 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) { #endif if(strcmp(p->comm, comm) != 0) { - if(unlikely(debug)) { + if(unlikely(debug_enabled)) { if(p->comm[0]) - fprintf(stderr, "apps.plugin: \tpid %d (%s) changed name to '%s'\n", p->pid, p->comm, comm); + debug_log("\tpid %d (%s) changed name to '%s'", p->pid, p->comm, comm); else - fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", p->pid, comm); + debug_log("\tJust added %d (%s)", p->pid, comm); } strncpyz(p->comm, comm, MAX_COMPARE_NAME); @@ -1152,8 +1229,8 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) { } #endif - if(unlikely(debug || (p->target && p->target->debug))) - fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT ", threads=%d\n", netdata_configured_host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads); + if(unlikely(debug_enabled || (p->target && p->target->debug_enabled))) + debug_log_int("READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT ", threads=%d", netdata_configured_host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads); if(unlikely(global_iterations_counter == 1)) { p->minflt = 0; @@ -1332,7 +1409,7 @@ int file_descriptor_compare(void* a, void* b) { return strcmp(((struct file_descriptor *)a)->name, ((struct file_descriptor *)b)->name); } -int file_descriptor_iterator(avl *a) { if(a) {}; return 0; } +// int file_descriptor_iterator(avl *a) { if(a) {}; return 0; } avl_tree all_files_index = { NULL, @@ -1368,15 +1445,13 @@ static inline void file_descriptor_not_used(int id) } #endif /* NETDATA_INTERNAL_CHECKS */ - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: decreasing slot %d (count = %d).\n", id, all_files[id].count); + debug_log("decreasing slot %d (count = %d).", id, all_files[id].count); if(all_files[id].count > 0) { all_files[id].count--; if(!all_files[id].count) { - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> slot %d is empty.\n", id); + debug_log(" >> slot %d is empty.", id); if(unlikely(file_descriptor_remove(&all_files[id]) != (void *)&all_files[id])) error("INTERNAL ERROR: removal of unused fd from index, removed a different fd"); @@ -1398,8 +1473,7 @@ static inline void all_files_grow() { int i; // there is no empty slot - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); + debug_log("extending fd array to %d entries", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); all_files = reallocz(all_files, (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP) * sizeof(struct file_descriptor)); @@ -1407,8 +1481,7 @@ static inline void all_files_grow() { // since all pointers are now invalid if(unlikely(old && old != (void *)all_files)) { - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> re-indexing.\n"); + debug_log(" >> re-indexing."); all_files_index.root = NULL; for(i = 0; i < all_files_size; i++) { @@ -1417,8 +1490,7 @@ static inline void all_files_grow() { error("INTERNAL ERROR: duplicate indexing of fd during realloc."); } - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> re-indexing done.\n"); + debug_log(" >> re-indexing done."); } // initialize the newly added entries @@ -1441,8 +1513,7 @@ static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t h if(!all_files || all_files_len == all_files_size) all_files_grow(); - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> searching for empty slot.\n"); + debug_log(" >> searching for empty slot."); // search for an empty slot @@ -1453,16 +1524,14 @@ static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t h if(c == 0) continue; if(!all_files[c].count) { - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> Examining slot %d.\n", c); + debug_log(" >> Examining slot %d.", c); #ifdef NETDATA_INTERNAL_CHECKS if(all_files[c].magic == 0x0BADCAFE && all_files[c].name && file_descriptor_find(all_files[c].name, all_files[c].hash)) - error("fd on position %d is not cleared properly. It still has %s in it.\n", c, all_files[c].name); + error("fd on position %d is not cleared properly. It still has %s in it.", c, all_files[c].name); #endif /* NETDATA_INTERNAL_CHECKS */ - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> %s fd position %d for %s (last name: %s)\n", all_files[c].name?"re-using":"using", c, name, all_files[c].name); + debug_log(" >> %s fd position %d for %s (last name: %s)", all_files[c].name?"re-using":"using", c, name, all_files[c].name); freez((void *)all_files[c].name); all_files[c].name = NULL; @@ -1479,8 +1548,7 @@ static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t h } // else we have an empty slot in 'c' - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> updating slot %d.\n", c); + debug_log(" >> updating slot %d.", c); all_files[c].name = strdupz(name); all_files[c].hash = hash; @@ -1493,24 +1561,21 @@ static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t h if(unlikely(file_descriptor_add(&all_files[c]) != (void *)&all_files[c])) error("INTERNAL ERROR: duplicate indexing of fd."); - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name); + debug_log("using fd position %d (name: %s)", c, all_files[c].name); return c; } -static inline int file_descriptor_find_or_add(const char *name) -{ - uint32_t hash = simple_hash(name); +static inline int file_descriptor_find_or_add(const char *name, uint32_t hash) { + if(unlikely(!hash)) + hash = simple_hash(name); - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash); + debug_log("adding or finding name '%s' with hash %u", name, hash); struct file_descriptor *fd = file_descriptor_find(name, hash); if(fd) { // found - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos); + debug_log(" >> found on slot %d", fd->pos); fd->count++; return fd->pos; @@ -1530,47 +1595,65 @@ static inline int file_descriptor_find_or_add(const char *name) else if(strcmp(t, "[timerfd]") == 0) type = FILETYPE_TIMERFD; else if(strcmp(t, "[signalfd]") == 0) type = FILETYPE_SIGNALFD; else { - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: FIXME: unknown anonymous inode: %s\n", name); - + debug_log("UNKNOWN anonymous inode: %s", name); type = FILETYPE_OTHER; } } else if(likely(strcmp(name, "inotify") == 0)) type = FILETYPE_INOTIFY; else { - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: FIXME: cannot understand linkname: %s\n", name); - + debug_log("UNKNOWN linkname: %s", name); type = FILETYPE_OTHER; } return file_descriptor_set_on_empty_slot(name, hash, type); } +static inline void clear_pid_fd(struct pid_fd *pfd) { + pfd->fd = 0; + + #ifndef __FreeBSD__ + pfd->link_hash = 0; + pfd->inode = 0; + pfd->cache_iterations_counter = 0; + pfd->cache_iterations_reset = 0; +#endif +} + static inline void make_all_pid_fds_negative(struct pid_stat *p) { - int *fd = p->fds, *end = &p->fds[p->fds_size]; - while(fd < end) { - *fd = -(*fd); - fd++; + struct pid_fd *pfd = p->fds, *pfdend = &p->fds[p->fds_size]; + while(pfd < pfdend) { + pfd->fd = -(pfd->fd); + pfd++; } } static inline void cleanup_negative_pid_fds(struct pid_stat *p) { - int *fd = p->fds, *fdend = &p->fds[p->fds_size]; + struct pid_fd *pfd = p->fds, *pfdend = &p->fds[p->fds_size]; + + while(pfd < pfdend) { + int fd = pfd->fd; - while(fd < fdend) { - if(unlikely(*fd < 0)) { - file_descriptor_not_used(-(*fd)); - *fd++ = 0; + if(unlikely(fd < 0)) { + file_descriptor_not_used(-(fd)); + clear_pid_fd(pfd); } - else - fd++; + + pfd++; } } -static inline void zero_pid_fds(struct pid_stat *p, int first, int size) { - int *fd = &p->fds[first], *end = &p->fds[first + size]; - while(fd < end) *fd++ = 0; +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__ + pfd->filename = NULL; +#endif + clear_pid_fd(pfd); + pfd++; + i++; + } } static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) { @@ -1625,17 +1708,16 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) { if (unlikely(fdid >= p->fds_size)) { // it is small, extend it - if (unlikely(debug)) - fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + MAX_SPARE_FDS); + debug_log("extending fd memory slots for %s from %d to %d", p->comm, p->fds_size, fdid + MAX_SPARE_FDS); - p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int)); + p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(struct pid_fd)); // and initialize it - zero_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size); + init_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size); p->fds_size = fdid + MAX_SPARE_FDS; } - if (unlikely(p->fds[fdid] == 0)) { + if (unlikely(p->fds[fdid].fd == 0)) { // we don't know this fd, get it switch (fds->kf_type) { @@ -1691,15 +1773,14 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) { // if another process already has this, we will get // the same id - p->fds[fdid] = file_descriptor_find_or_add(fdsname); + p->fds[fdid].fd = file_descriptor_find_or_add(fdsname, 0); } // else make it positive again, we need it - // of course, the actual file may have changed, but we don't care so much - // FIXME: we could compare the inode as returned by readdir dirent structure + // of course, the actual file may have changed else - p->fds[fdid] = -p->fds[fdid]; + p->fds[fdid].fd = -p->fds[fdid].fd; bfdsbuf += fds->kf_structsize; } @@ -1714,7 +1795,6 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) { if(unlikely(!fds)) return 0; struct dirent *de; - char fdname[FILENAME_MAX + 1]; char linkname[FILENAME_MAX + 1]; // we make all pid fds negative, so that @@ -1733,53 +1813,103 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) { if(unlikely(fdid < 0)) continue; // check if the fds array is small - if(unlikely(fdid >= p->fds_size)) { + if(unlikely((size_t)fdid >= p->fds_size)) { // it is small, extend it - if(unlikely(debug)) - fprintf(stderr - , "apps.plugin: extending fd memory slots for %s from %d to %d\n" - , p->comm - , p->fds_size - , fdid + MAX_SPARE_FDS - ); + debug_log("extending fd memory slots for %s from %d to %d" + , p->comm + , p->fds_size + , fdid + MAX_SPARE_FDS + ); - p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int)); + p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(struct pid_fd)); // and initialize it - zero_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size); - p->fds_size = fdid + MAX_SPARE_FDS; + init_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size); + p->fds_size = (size_t)fdid + MAX_SPARE_FDS; } - if(unlikely(p->fds[fdid] == 0)) { - // we don't know this fd, get it + if(unlikely(p->fds[fdid].fd < 0 && de->d_ino != p->fds[fdid].inode)) { + // inodes do not match, clear the previous entry + inodes_changed_counter++; + file_descriptor_not_used(-p->fds[fdid].fd); + clear_pid_fd(&p->fds[fdid]); + } - sprintf(fdname, "%s/proc/%d/fd/%s", netdata_configured_host_prefix, p->pid, de->d_name); - ssize_t l = readlink(fdname, linkname, FILENAME_MAX); - if(unlikely(l == -1)) { - if(debug || (p->target && p->target->debug)) { - if(debug || (p->target && p->target->debug)) - error("Cannot read link %s", fdname); - } - continue; + if(p->fds[fdid].fd < 0 && p->fds[fdid].cache_iterations_counter > 0) { + p->fds[fdid].fd = -p->fds[fdid].fd; + p->fds[fdid].cache_iterations_counter--; + continue; + } + + if(unlikely(!p->fds[fdid].filename)) { + filenames_allocated_counter++; + char fdname[FILENAME_MAX + 1]; + snprintfz(fdname, FILENAME_MAX, "%s/proc/%d/fd/%s", netdata_configured_host_prefix, p->pid, de->d_name); + p->fds[fdid].filename = strdupz(fdname); + } + + file_counter++; + ssize_t l = readlink(p->fds[fdid].filename, linkname, FILENAME_MAX); + if(unlikely(l == -1)) { + // cannot read the link + + if(debug_enabled || (p->target && p->target->debug_enabled)) + error("Cannot read link %s", p->fds[fdid].filename); + + if(unlikely(p->fds[fdid].fd < 0)) { + file_descriptor_not_used(-p->fds[fdid].fd); + clear_pid_fd(&p->fds[fdid]); } - else - linkname[l] = '\0'; - file_counter++; + continue; + } + else + linkname[l] = '\0'; + + uint32_t link_hash = simple_hash(linkname); + + if(unlikely(p->fds[fdid].fd < 0 && p->fds[fdid].link_hash != link_hash)) { + // the link changed + links_changed_counter++; + file_descriptor_not_used(-p->fds[fdid].fd); + clear_pid_fd(&p->fds[fdid]); + } + + if(unlikely(p->fds[fdid].fd == 0)) { + // we don't know this fd, get it // if another process already has this, we will get // the same id - p->fds[fdid] = file_descriptor_find_or_add(linkname); + p->fds[fdid].fd = file_descriptor_find_or_add(linkname, link_hash); + p->fds[fdid].inode = de->d_ino; + p->fds[fdid].link_hash = link_hash; } - + else { // else make it positive again, we need it - // of course, the actual file may have changed, but we don't care so much - // FIXME: we could compare the inode as returned by readdir dirent structure - // UPDATE: no we cannot use inodes - under /proc inodes don't change when the link is changed + p->fds[fdid].fd = -p->fds[fdid].fd; + } - else - p->fds[fdid] = -p->fds[fdid]; + // caching control + // without this we read all the files on every iteration + if(max_fds_cache_seconds > 0) { + size_t spread = ((size_t)max_fds_cache_seconds > 10) ? 10 : (size_t)max_fds_cache_seconds; + + // cache it for a few iterations + size_t max = ((size_t) max_fds_cache_seconds + (fdid % spread)) / (size_t) update_every; + p->fds[fdid].cache_iterations_reset++; + + if(unlikely(p->fds[fdid].cache_iterations_reset % spread == (size_t) fdid % spread)) + p->fds[fdid].cache_iterations_reset++; + + if(unlikely((fdid <= 2 && p->fds[fdid].cache_iterations_reset > 5) || + p->fds[fdid].cache_iterations_reset > max)) { + // for stdin, stdout, stderr (fdid <= 2) we have checked a few times, or if it goes above the max, goto max + p->fds[fdid].cache_iterations_reset = max; + } + + p->fds[fdid].cache_iterations_counter = p->fds[fdid].cache_iterations_reset; + } } closedir(fds); @@ -1791,12 +1921,12 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) { // ---------------------------------------------------------------------------- -static inline int print_process_and_parents(struct pid_stat *p, usec_t time) { +static inline int debug_print_process_and_parents(struct pid_stat *p, usec_t time) { char *prefix = "\\_ "; int indent = 0; if(p->parent) - indent = print_process_and_parents(p->parent, p->stat_collected_usec); + indent = debug_print_process_and_parents(p->parent, p->stat_collected_usec); else prefix = " > "; @@ -1830,12 +1960,12 @@ static inline int print_process_and_parents(struct pid_stat *p, usec_t time) { return indent + 1; } -static inline void print_process_tree(struct pid_stat *p, char *msg) { - fprintf(stderr, "%s: process %s (%d, %s) with parents:\n", msg, p->comm, p->pid, p->updated?"running":"exited"); - print_process_and_parents(p, p->stat_collected_usec); +static inline void debug_print_process_tree(struct pid_stat *p, char *msg) { + debug_log("%s: process %s (%d, %s) with parents:", msg, p->comm, p->pid, p->updated?"running":"exited"); + debug_print_process_and_parents(p, p->stat_collected_usec); } -static inline void find_lost_child_debug(struct pid_stat *pe, kernel_uint_t lost, int type) { +static inline void debug_find_lost_child(struct pid_stat *pe, kernel_uint_t lost, int type) { int found = 0; struct pid_stat *p = NULL; @@ -1938,8 +2068,8 @@ static inline void process_exited_processes() { if(utime + stime + gtime + minflt + majflt == 0) continue; - if(unlikely(debug)) { - fprintf(stderr, "Absorb %s (%d %s total resources: utime=" KERNEL_UINT_FORMAT " stime=" KERNEL_UINT_FORMAT " gtime=" KERNEL_UINT_FORMAT " minflt=" KERNEL_UINT_FORMAT " majflt=" KERNEL_UINT_FORMAT ")\n" + if(unlikely(debug_enabled)) { + debug_log("Absorb %s (%d %s total resources: utime=" KERNEL_UINT_FORMAT " stime=" KERNEL_UINT_FORMAT " gtime=" KERNEL_UINT_FORMAT " minflt=" KERNEL_UINT_FORMAT " majflt=" KERNEL_UINT_FORMAT ")" , p->comm , p->pid , p->updated?"running":"exited" @@ -1949,7 +2079,7 @@ static inline void process_exited_processes() { , minflt , majflt ); - print_process_tree(p, "Searching parents"); + debug_print_process_tree(p, "Searching parents"); } struct pid_stat *pp; @@ -1958,59 +2088,57 @@ static inline void process_exited_processes() { kernel_uint_t absorbed; absorbed = remove_exited_child_from_parent(&utime, &pp->cutime); - if(unlikely(debug && absorbed)) - fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " utime (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, utime); + if(unlikely(debug_enabled && absorbed)) + debug_log(" > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " utime (remaining: " KERNEL_UINT_FORMAT ")", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, utime); absorbed = remove_exited_child_from_parent(&stime, &pp->cstime); - if(unlikely(debug && absorbed)) - fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " stime (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, stime); + if(unlikely(debug_enabled && absorbed)) + debug_log(" > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " stime (remaining: " KERNEL_UINT_FORMAT ")", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, stime); absorbed = remove_exited_child_from_parent(>ime, &pp->cgtime); - if(unlikely(debug && absorbed)) - fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " gtime (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, gtime); + if(unlikely(debug_enabled && absorbed)) + debug_log(" > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " gtime (remaining: " KERNEL_UINT_FORMAT ")", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, gtime); absorbed = remove_exited_child_from_parent(&minflt, &pp->cminflt); - if(unlikely(debug && absorbed)) - fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " minflt (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, minflt); + if(unlikely(debug_enabled && absorbed)) + debug_log(" > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " minflt (remaining: " KERNEL_UINT_FORMAT ")", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, minflt); absorbed = remove_exited_child_from_parent(&majflt, &pp->cmajflt); - if(unlikely(debug && absorbed)) - fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " majflt (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, majflt); + if(unlikely(debug_enabled && absorbed)) + debug_log(" > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " majflt (remaining: " KERNEL_UINT_FORMAT ")", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, majflt); } if(unlikely(utime + stime + gtime + minflt + majflt > 0)) { - if(unlikely(debug)) { - if(utime) find_lost_child_debug(p, utime, 3); - if(stime) find_lost_child_debug(p, stime, 4); - if(gtime) find_lost_child_debug(p, gtime, 5); - if(minflt) find_lost_child_debug(p, minflt, 1); - if(majflt) find_lost_child_debug(p, majflt, 2); + if(unlikely(debug_enabled)) { + if(utime) debug_find_lost_child(p, utime, 3); + if(stime) debug_find_lost_child(p, stime, 4); + if(gtime) debug_find_lost_child(p, gtime, 5); + if(minflt) debug_find_lost_child(p, minflt, 1); + if(majflt) debug_find_lost_child(p, majflt, 2); } p->keep = 1; - if(unlikely(debug)) - fprintf(stderr, " > remaining resources - KEEP - for another loop: %s (%d %s total resources: utime=" KERNEL_UINT_FORMAT " stime=" KERNEL_UINT_FORMAT " gtime=" KERNEL_UINT_FORMAT " minflt=" KERNEL_UINT_FORMAT " majflt=" KERNEL_UINT_FORMAT ")\n" - , p->comm - , p->pid - , p->updated?"running":"exited" - , utime - , stime - , gtime - , minflt - , majflt - ); + debug_log(" > remaining resources - KEEP - for another loop: %s (%d %s total resources: utime=" KERNEL_UINT_FORMAT " stime=" KERNEL_UINT_FORMAT " gtime=" KERNEL_UINT_FORMAT " minflt=" KERNEL_UINT_FORMAT " majflt=" KERNEL_UINT_FORMAT ")" + , p->comm + , p->pid + , p->updated?"running":"exited" + , utime + , stime + , gtime + , minflt + , majflt + ); for(pp = p->parent; pp ; pp = pp->parent) { if(pp->updated) break; pp->keep = 1; - if(unlikely(debug)) - fprintf(stderr, " > - KEEP - parent for another loop: %s (%d %s)\n" - , pp->comm - , pp->pid - , pp->updated?"running":"exited" - ); + debug_log(" > - KEEP - parent for another loop: %s (%d %s)" + , pp->comm + , pp->pid + , pp->updated?"running":"exited" + ); } p->utime_raw = utime * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL); @@ -2020,16 +2148,14 @@ static inline void process_exited_processes() { p->majflt_raw = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL); p->cutime_raw = p->cstime_raw = p->cgtime_raw = p->cminflt_raw = p->cmajflt_raw = 0; - if(unlikely(debug)) - fprintf(stderr, "\n"); + debug_log(" "); } - else if(unlikely(debug)) { - fprintf(stderr, " > totally absorbed - DONE - %s (%d %s)\n" + else + debug_log(" > totally absorbed - DONE - %s (%d %s)" , p->comm , p->pid , p->updated?"running":"exited" - ); - } + ); } } @@ -2054,8 +2180,8 @@ static inline void link_all_processes_to_their_parents(void) { p->parent = pp; pp->children_count++; - if(unlikely(debug || (p->target && p->target->debug))) - fprintf(stderr, "apps.plugin: \tchild %d (%s, %s) on target '%s' has parent %d (%s, %s). Parent: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", gtime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", cgtime=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT "\n", p->pid, p->comm, p->updated?"running":"exited", (p->target)?p->target->name:"UNSET", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->gtime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cgtime, pp->cminflt, pp->cmajflt); + if(unlikely(debug_enabled || (p->target && p->target->debug_enabled))) + debug_log_int("child %d (%s, %s) on target '%s' has parent %d (%s, %s). Parent: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", gtime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", cgtime=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT "", p->pid, p->comm, p->updated?"running":"exited", (p->target)?p->target->name:"UNSET", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->gtime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cgtime, pp->cminflt, pp->cmajflt); } else { p->parent = NULL; @@ -2105,7 +2231,7 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) { if(unlikely(!p || p->read)) return 0; p->read = 1; - // fprintf(stderr, "Reading process %d (%s), sortlist %d\n", p->pid, p->comm, p->sortlist); + // debug_log("Reading process %d (%s), sortlist %d", p->pid, p->comm, p->sortlist); // -------------------------------------------------------------------- // /proc/<pid>/stat @@ -2141,8 +2267,8 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) { // -------------------------------------------------------------------- // done! - if(unlikely(debug && include_exited_childs && all_pids_count && p->ppid && all_pids[p->ppid] && !all_pids[p->ppid]->read)) - fprintf(stderr, "Read process %d (%s) sortlisted %d, but its parent %d (%s) sortlisted %d, is not read\n", p->pid, p->comm, p->sortlist, all_pids[p->ppid]->pid, all_pids[p->ppid]->comm, all_pids[p->ppid]->sortlist); + if(unlikely(debug_enabled && include_exited_childs && all_pids_count && p->ppid && all_pids[p->ppid] && !all_pids[p->ppid]->read)) + debug_log("Read process %d (%s) sortlisted %d, but its parent %d (%s) sortlisted %d, is not read", p->pid, p->comm, p->sortlist, all_pids[p->ppid]->pid, all_pids[p->ppid]->comm, all_pids[p->ppid]->sortlist); // mark it as updated p->updated = 1; @@ -2302,18 +2428,18 @@ static int collect_data_for_all_processes(void) { // check: update_apps_groups_statistics() static void cleanup_exited_pids(void) { - int c; + size_t c; struct pid_stat *p = NULL; for(p = root_of_pids; p ;) { if(!p->updated && (!p->keep || p->keeploops > 0)) { - if(unlikely(debug && (p->keep || p->keeploops))) - fprintf(stderr, " > CLEANUP cannot keep exited process %d (%s) anymore - removing it.\n", p->pid, p->comm); + if(unlikely(debug_enabled && (p->keep || p->keeploops))) + debug_log(" > CLEANUP cannot keep exited process %d (%s) anymore - removing it.", p->pid, p->comm); for(c = 0; c < p->fds_size; c++) - if(p->fds[c] > 0) { - file_descriptor_not_used(p->fds[c]); - p->fds[c] = 0; + if(p->fds[c].fd > 0) { + file_descriptor_not_used(p->fds[c].fd); + clear_pid_fd(&p->fds[c]); } pid_t r = p->pid; @@ -2335,7 +2461,7 @@ static void apply_apps_groups_targets_inheritance(void) { // inherit their target from their parent int found = 1, loops = 0; while(found) { - if(unlikely(debug)) loops++; + if(unlikely(debug_enabled)) loops++; found = 0; for(p = root_of_pids; p ; p = p->next) { // if this process does not have a target @@ -2346,8 +2472,8 @@ static void apply_apps_groups_targets_inheritance(void) { p->target = p->parent->target; found++; - if(debug || (p->target && p->target->debug)) - fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s).\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm); + if(debug_enabled || (p->target && p->target->debug_enabled)) + debug_log_int("TARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s).", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm); } } } @@ -2357,7 +2483,7 @@ static void apply_apps_groups_targets_inheritance(void) { int sortlist = 1; found = 1; while(found) { - if(unlikely(debug)) loops++; + if(unlikely(debug_enabled)) loops++; found = 0; for(p = root_of_pids; p ; p = p->next) { @@ -2382,16 +2508,15 @@ static void apply_apps_groups_targets_inheritance(void) { if(unlikely(p->target && !p->parent->target)) { p->parent->target = p->target; - if(debug || (p->target && p->target->debug)) - fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its child %d (%s).\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm); + if(debug_enabled || (p->target && p->target->debug_enabled)) + debug_log_int("TARGET INHERITANCE: %s is inherited by %d (%s) from its child %d (%s).", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm); } found++; } } - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: TARGET INHERITANCE: merged %d processes\n", found); + debug_log("TARGET INHERITANCE: merged %d processes", found); } // init goes always to default target @@ -2403,7 +2528,7 @@ static void apply_apps_groups_targets_inheritance(void) { all_pids[0]->target = apps_groups_default_target; // give a default target on all top level processes - if(unlikely(debug)) loops++; + if(unlikely(debug_enabled)) loops++; for(p = root_of_pids; p ; p = p->next) { // if the process is not merged itself // then is is a top level process @@ -2421,21 +2546,20 @@ static void apply_apps_groups_targets_inheritance(void) { // give a target to all merged child processes found = 1; while(found) { - if(unlikely(debug)) loops++; + if(unlikely(debug_enabled)) loops++; found = 0; for(p = root_of_pids; p ; p = p->next) { if(unlikely(!p->target && p->merged && p->parent && p->parent->target)) { p->target = p->parent->target; found++; - if(debug || (p->target && p->target->debug)) - fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s) at phase 2.\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm); + if(debug_enabled || (p->target && p->target->debug_enabled)) + debug_log_int("TARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s) at phase 2.", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm); } } } - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: apply_apps_groups_targets_inheritance() made %d loops on the process tree\n", loops); + debug_log("apply_apps_groups_targets_inheritance() made %d loops on the process tree", loops); } static size_t zero_all_targets(struct target *root) { @@ -2570,9 +2694,10 @@ static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) { reallocate_target_fds(u); reallocate_target_fds(g); - int c, size = p->fds_size, *fds = p->fds; + size_t c, size = p->fds_size; + struct pid_fd *fds = p->fds; for(c = 0; c < size ;c++) { - int fd = fds[c]; + int fd = fds[c].fd; if(likely(fd <= 0 || fd >= all_files_size)) continue; @@ -2628,8 +2753,8 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p, w->processes++; w->num_threads += p->num_threads; - if(unlikely(debug || w->debug)) - fprintf(stderr, "apps.plugin: \taggregating '%s' pid %d on target '%s' utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", gtime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", cgtime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT "\n", p->comm, p->pid, w->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt); + if(unlikely(debug_enabled || w->debug_enabled)) + debug_log_int("aggregating '%s' pid %d on target '%s' utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", gtime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", cgtime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT "", p->comm, p->pid, w->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt); } static void calculate_netdata_statistics(void) { @@ -2660,8 +2785,8 @@ static void calculate_netdata_statistics(void) { if(likely(p->user_target && p->user_target->uid == p->uid)) w = p->user_target; else { - if(unlikely(debug && p->user_target)) - fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched user from %u (%s) to %u.\n", p->pid, p->comm, p->user_target->uid, p->user_target->name, p->uid); + if(unlikely(debug_enabled && p->user_target)) + debug_log("pid %d (%s) switched user from %u (%s) to %u.", p->pid, p->comm, p->user_target->uid, p->user_target->name, p->uid); w = p->user_target = get_users_target(p->uid); } @@ -2676,8 +2801,8 @@ static void calculate_netdata_statistics(void) { if(likely(p->group_target && p->group_target->gid == p->gid)) w = p->group_target; else { - if(unlikely(debug && p->group_target)) - fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched group from %u (%s) to %u.\n", p->pid, p->comm, p->group_target->gid, p->group_target->name, p->gid); + if(unlikely(debug_enabled && p->group_target)) + debug_log("pid %d (%s) switched group from %u (%s) to %u.", p->pid, p->comm, p->group_target->gid, p->group_target->name, p->gid); w = p->group_target = get_groups_target(p->gid); } @@ -2698,8 +2823,6 @@ static void calculate_netdata_statistics(void) { // ---------------------------------------------------------------------------- // update chart dimensions -int print_calculated_number(char *str, calculated_number value) { (void)str; (void)value; return 0; } - static inline void send_BEGIN(const char *type, const char *id, usec_t usec) { fprintf(stdout, "BEGIN %s.%s %llu\n", type, id, usec); } @@ -2751,6 +2874,9 @@ void send_resource_usage_to_netdata(usec_t dt) { "CHART netdata.apps_sizes '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_sizes line 140001 %1$d\n" "DIMENSION calls '' incremental 1 1\n" "DIMENSION files '' incremental 1 1\n" + "DIMENSION filenames '' incremental 1 1\n" + "DIMENSION inode_changes '' incremental 1 1\n" + "DIMENSION link_changes '' incremental 1 1\n" "DIMENSION pids '' absolute 1 1\n" "DIMENSION fds '' absolute 1 1\n" "DIMENSION targets '' absolute 1 1\n" @@ -2793,6 +2919,9 @@ void send_resource_usage_to_netdata(usec_t dt) { "BEGIN netdata.apps_sizes %llu\n" "SET calls = %zu\n" "SET files = %zu\n" + "SET filenames = %zu\n" + "SET inode_changes = %zu\n" + "SET link_changes = %zu\n" "SET pids = %zu\n" "SET fds = %d\n" "SET targets = %zu\n" @@ -2804,6 +2933,9 @@ void send_resource_usage_to_netdata(usec_t dt) { , dt , calls_counter , file_counter + , filenames_allocated_counter + , inodes_changed_counter + , links_changed_counter , all_pids_count , all_files_len , apps_groups_targets_count @@ -2854,7 +2986,7 @@ static void normalize_utilization(struct target *root) { // here we try to eliminate them by disabling childs processing either for specific dimensions // or entirely. Of course, either way, we disable it just a single iteration. - kernel_uint_t max_time = processors * hz * RATES_DETAIL; + kernel_uint_t max_time = processors * system_hz * RATES_DETAIL; kernel_uint_t utime = 0, cutime = 0, stime = 0, cstime = 0, gtime = 0, cgtime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0; if(global_utime > max_time) global_utime = max_time; @@ -2932,7 +3064,7 @@ static void normalize_utilization(struct target *root) { // if(gtime_fix_ratio < 0.0) gtime_fix_ratio = 0.0; // if(cgtime_fix_ratio < 0.0) cgtime_fix_ratio = 0.0; - // FIXME + // TODO // we use cpu time to normalize page faults // the problem is that to find the proper max values // for page faults we have to parse /proc/vmstat @@ -2957,14 +3089,12 @@ static void normalize_utilization(struct target *root) { // the report - if(unlikely(debug)) { - fprintf(stderr, + debug_log( "SYSTEM: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " " "COLLECTED: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " cu=" KERNEL_UINT_FORMAT " cs=" KERNEL_UINT_FORMAT " cg=" KERNEL_UINT_FORMAT " " "DELTA: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " " "FIX: u=%0.2f s=%0.2f g=%0.2f cu=%0.2f cs=%0.2f cg=%0.2f " "FINALLY: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " cu=" KERNEL_UINT_FORMAT " cs=" KERNEL_UINT_FORMAT " cg=" KERNEL_UINT_FORMAT " " - "\n" , global_utime , global_stime , global_gtime @@ -2989,8 +3119,7 @@ static void normalize_utilization(struct target *root) { , (kernel_uint_t)(cutime * cutime_fix_ratio) , (kernel_uint_t)(cstime * cstime_fix_ratio) , (kernel_uint_t)(cgtime * cgtime_fix_ratio) - ); - } + ); } #else // ALL_PIDS_ARE_READ_INSTANTLY == 1 static void normalize_utilization(struct target *root) { @@ -3151,7 +3280,8 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type if (!w->exposed && w->processes) { newly_added++; w->exposed = 1; - if (debug || w->debug) fprintf(stderr, "apps.plugin: %s just added - regenerating charts.\n", w->name); + if (debug_enabled || w->debug_enabled) + debug_log_int("%s just added - regenerating charts.", w->name); } } @@ -3163,7 +3293,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type fprintf(stdout, "CHART %s.cpu '' '%s CPU Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu stacked 20001 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, hz * RATES_DETAIL / 100, w->hidden ? "hidden" : ""); + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, system_hz * RATES_DETAIL / 100, w->hidden ? "hidden" : ""); } fprintf(stdout, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every); @@ -3193,20 +3323,20 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type fprintf(stdout, "CHART %s.cpu_user '' '%s CPU User Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_user stacked 20020 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU); + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, system_hz * RATES_DETAIL / 100LLU); } fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU); + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, system_hz * RATES_DETAIL / 100LLU); } if(show_guest_time) { fprintf(stdout, "CHART %s.cpu_guest '' '%s CPU Guest Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20022 %d\n", type, title, (processors * 100), processors, (processors > 1) ? "s" : "", type, update_every); for (w = root; w; w = w->next) { if(unlikely(w->exposed)) - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU); + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, system_hz * RATES_DETAIL / 100LLU); } } @@ -3315,7 +3445,6 @@ cleanup: static void parse_args(int argc, char **argv) { int i, freq = 0; - char *name = NULL; for(i = 1; i < argc; i++) { if(!freq) { @@ -3341,10 +3470,26 @@ static void parse_args(int argc, char **argv) } if(strcmp("debug", argv[i]) == 0) { - debug = 1; - // debug_flags = 0xffffffff; +#ifdef NETDATA_INTERNAL_CHECKS + debug_enabled = 1; +#else + fprintf(stderr, "apps.plugin has been compiled without debugging\n"); +#endif + continue; + } + +#ifndef __FreeBSD__ + if(strcmp("fds-cache-secs", argv[i]) == 0) { + if(argc <= i + 1) { + fprintf(stderr, "Parameter 'fds-cache-secs' requires a number as argument.\n"); + exit(1); + } + i++; + max_fds_cache_seconds = str2i(argv[i]); + if(max_fds_cache_seconds < 0) max_fds_cache_seconds = 0; continue; } +#endif if(strcmp("no-childs", argv[i]) == 0 || strcmp("without-childs", argv[i]) == 0) { include_exited_childs = 0; @@ -3415,44 +3560,54 @@ static void parse_args(int argc, char **argv) " without-files enable / disable reporting files, sockets, pipes\n" " (default is enabled)\n" "\n" - " NAME read apps_NAME.conf instead of\n" - " apps_groups.conf\n" - " (default NAME=groups)\n" +#ifndef __FreeBSD__ + " fds-cache-secs N cache the files of processed for N seconds\n" + " caching is adaptive per file (when a file\n" + " is found, it starts at 0 and while the file\n" + " remains open, it is incremented up to the\n" + " max given)\n" + " (default is %d seconds)\n" "\n" +#endif " version or -v or -V print program version and exit\n" "\n" , VERSION +#ifndef __FreeBSD__ + , max_fds_cache_seconds +#endif ); exit(1); } - if(!name) { - name = argv[i]; - continue; - } - error("Cannot understand option %s", argv[i]); exit(1); } if(freq > 0) update_every = freq; - if(!name) name = "groups"; - if(read_apps_groups_conf(name)) { - error("Cannot read process groups '%s/apps_%s.conf'. There are no internal defaults. Failing.", config_dir, name); - exit(1); + if(read_apps_groups_conf(user_config_dir, "groups")) { + info("Cannot read process groups configuration file '%s/apps_groups.conf'. Will try '%s/apps_groups.conf'", user_config_dir, stock_config_dir); + + if(read_apps_groups_conf(stock_config_dir, "groups")) { + error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", stock_config_dir); + exit(1); + } + else + info("Loaded config file '%s/apps_groups.conf'", stock_config_dir); } + else + info("Loaded config file '%s/apps_groups.conf'", user_config_dir); } static int am_i_running_as_root() { uid_t uid = getuid(), euid = geteuid(); if(uid == 0 || euid == 0) { - if(debug) info("I am running with escalated privileges, uid = %u, euid = %u.", uid, euid); + if(debug_enabled) info("I am running with escalated privileges, uid = %u, euid = %u.", uid, euid); return 1; } - if(debug) info("I am not running with escalated privileges, uid = %u, euid = %u.", uid, euid); + if(debug_enabled) info("I am not running with escalated privileges, uid = %u, euid = %u.", uid, euid); return 0; } @@ -3463,7 +3618,7 @@ static int check_capabilities() { error("Cannot get current capabilities."); return 0; } - else if(debug) + else if(debug_enabled) info("Received my capabilities from the system."); int ret = 1; @@ -3478,7 +3633,7 @@ static int check_capabilities() { error("apps.plugin should run with CAP_DAC_READ_SEARCH."); ret = 0; } - else if(debug) + else if(debug_enabled) info("apps.plugin runs with CAP_DAC_READ_SEARCH."); } @@ -3492,7 +3647,7 @@ static int check_capabilities() { error("apps.plugin should run with CAP_SYS_PTRACE."); ret = 0; } - else if(debug) + else if(debug_enabled) info("apps.plugin runs with CAP_SYS_PTRACE."); } @@ -3521,19 +3676,25 @@ int main(int argc, char **argv) { error_log_errors_per_period = 100; error_log_throttle_period = 3600; + // since apps.plugin runs as root, prevent it from opening symbolic links + procfile_open_flags = O_RDONLY|O_NOFOLLOW; + netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX"); - if(netdata_configured_host_prefix == NULL) { - // info("NETDATA_HOST_PREFIX is not passed from netdata"); - netdata_configured_host_prefix = ""; + if(verify_netdata_host_prefix() == -1) exit(1); + + user_config_dir = getenv("NETDATA_USER_CONFIG_DIR"); + if(user_config_dir == NULL) { + // info("NETDATA_CONFIG_DIR is not passed from netdata"); + user_config_dir = CONFIG_DIR; } - // else info("Found NETDATA_HOST_PREFIX='%s'", netdata_configured_host_prefix); + // else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir); - config_dir = getenv("NETDATA_CONFIG_DIR"); - if(config_dir == NULL) { + stock_config_dir = getenv("NETDATA_STOCK_CONFIG_DIR"); + if(stock_config_dir == NULL) { // info("NETDATA_CONFIG_DIR is not passed from netdata"); - config_dir = CONFIG_DIR; + stock_config_dir = LIBCONFIG_DIR; } - // else info("Found NETDATA_CONFIG_DIR='%s'", config_dir); + // else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir); #ifdef NETDATA_INTERNAL_CHECKS if(debug_flags != 0) { @@ -3561,14 +3722,14 @@ int main(int argc, char **argv) { error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. " "Without these, apps.plugin cannot report disk I/O utilization of other processes. " "To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; " - "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; " + "To enable setuid to root run: sudo chown root:netdata %s; sudo chmod 4750 %s; " , uid, euid, argv[0], argv[0], argv[0] ); #else error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. " "Without these, apps.plugin cannot report disk I/O utilization of other processes. " "Your system does not support capabilities. " - "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; " + "To enable setuid to root run: sudo chown root:netdata %s; sudo chmod 4750 %s; " , uid, euid, argv[0], argv[0] ); #endif @@ -3630,8 +3791,7 @@ int main(int argc, char **argv) { show_guest_time_old = show_guest_time; - if(unlikely(debug)) - fprintf(stderr, "apps.plugin: done Loop No %zu\n", global_iterations_counter); + debug_log("done Loop No %zu", global_iterations_counter); // restart check (14400 seconds) if(now_monotonic_sec() - started_t > 14400) exit(0); diff --git a/src/cgroup-network.c b/collectors/cgroups.plugin/cgroup-network.c index 0e2d5163..0cf2a263 100644 --- a/src/cgroup-network.c +++ b/collectors/cgroups.plugin/cgroup-network.c @@ -1,5 +1,6 @@ -#include "common.h" -#include <libgen.h> +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "libnetdata/libnetdata.h" #ifdef HAVE_SETNS #ifndef _GNU_SOURCE @@ -8,8 +9,6 @@ #include <sched.h> #endif -char *host_prefix = ""; - char environment_variable2[FILENAME_MAX + 50] = ""; char *environment[] = { "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin", @@ -19,14 +18,28 @@ char *environment[] = { // ---------------------------------------------------------------------------- -// callback required by fatal() +// callback required by fatal() void netdata_cleanup_and_exit(int ret) { exit(ret); } -void health_reload(void) {}; -void rrdhost_save_all(void) {}; +// callbacks required by popen() +void signals_block(void) {}; +void signals_unblock(void) {}; +void signals_reset(void) {}; + +// callback required by eval() +int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) { + (void)variable; + (void)hash; + (void)rc; + (void)result; + return 0; +}; + +// required by get_system_cpus() +char *netdata_configured_host_prefix = ""; // ---------------------------------------------------------------------------- @@ -41,8 +54,10 @@ struct iface { }; unsigned int read_iface_iflink(const char *prefix, const char *iface) { + if(!prefix) prefix = ""; + char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/iflink", prefix?prefix:"", iface); + snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/iflink", prefix, iface); unsigned long long iflink = 0; int ret = read_single_number_file(filename, &iflink); @@ -52,8 +67,10 @@ unsigned int read_iface_iflink(const char *prefix, const char *iface) { } unsigned int read_iface_ifindex(const char *prefix, const char *iface) { + if(!prefix) prefix = ""; + char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/ifindex", prefix?prefix:"", iface); + snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/ifindex", prefix, iface); unsigned long long ifindex = 0; int ret = read_single_number_file(filename, &ifindex); @@ -63,10 +80,12 @@ unsigned int read_iface_ifindex(const char *prefix, const char *iface) { } struct iface *read_proc_net_dev(const char *prefix) { + if(!prefix) prefix = ""; + procfile *ff = NULL; char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s%s", prefix?prefix:"", "/proc/net/dev"); + snprintfz(filename, FILENAME_MAX, "%s%s", prefix, (*prefix)?"/proc/1/net/dev":"/proc/net/dev"); ff = procfile_open(filename, " \t,:|", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) { error("Cannot open file '%s'", filename); @@ -163,12 +182,14 @@ static void continue_as_child(void) { } int proc_pid_fd(const char *prefix, const char *ns, pid_t pid) { + if(!prefix) prefix = ""; + char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/proc/%d/%s", prefix?prefix:"", (int)pid, ns); + snprintfz(filename, FILENAME_MAX, "%s/proc/%d/%s", prefix, (int)pid, ns); int fd = open(filename, O_RDONLY); if(fd == -1) - error("Cannot open file '%s'", filename); + error("Cannot open proc_pid_fd() file '%s'", filename); return fd; } @@ -193,6 +214,8 @@ static struct ns { }; int switch_namespace(const char *prefix, pid_t pid) { + if(!prefix) prefix = ""; + #ifdef HAVE_SETNS int i; @@ -207,8 +230,8 @@ int switch_namespace(const char *prefix, pid_t pid) { // 2 passes - found it at nsenter source code // this is related CLONE_NEWUSER functionality - // FIXME: this code cannot switch user namespace - // Fortunately, we don't need it. + // This code cannot switch user namespace (it can all the other namespaces) + // Fortunately, we don't need to switch user namespaces. int pass, errors = 0; for(pass = 0; pass < 2 ;pass++) { @@ -272,9 +295,15 @@ int switch_namespace(const char *prefix, pid_t pid) { } pid_t read_pid_from_cgroup_file(const char *filename) { - FILE *fp = fopen(filename, "r"); + int fd = open(filename, procfile_open_flags); + if(fd == -1) { + error("Cannot open pid_from_cgroup() file '%s'.", filename); + return 0; + } + + FILE *fp = fdopen(fd, "r"); if(!fp) { - error("Cannot read file '%s'.", filename); + error("Cannot upgrade fd to fp for file '%s'.", filename); return 0; } @@ -387,14 +416,13 @@ int send_devices(void) { // since it switches namespaces, so after this call, everything is different! void detect_veth_interfaces(pid_t pid) { - struct iface *host, *cgroup, *h, *c; - const char *prefix = getenv("NETDATA_HOST_PREFIX"); + struct iface *host = NULL, *cgroup = NULL, *h, *c; - host = read_proc_net_dev(prefix); + host = read_proc_net_dev(netdata_configured_host_prefix); if(!host) { errno = 0; error("cannot read host interface list."); - return; + goto cleanup; } if(!eligible_ifaces(host)) { @@ -403,7 +431,7 @@ void detect_veth_interfaces(pid_t pid) { goto cleanup; } - if(switch_namespace(prefix, pid)) { + if(switch_namespace(netdata_configured_host_prefix, pid)) { errno = 0; error("cannot switch to the namespace of pid %u", (unsigned int) pid); goto cleanup; @@ -433,6 +461,7 @@ void detect_veth_interfaces(pid_t pid) { } cleanup: + free_host_ifaces(cgroup); free_host_ifaces(host); } @@ -444,17 +473,18 @@ void call_the_helper(pid_t pid, const char *cgroup) { if(setresuid(0, 0, 0) == -1) error("setresuid(0, 0, 0) failed."); - char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; + char command[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; if(cgroup) - snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --cgroup '%s'", cgroup); + snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --cgroup '%s'", cgroup); else - snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid); + snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid); - info("running: %s", buffer); + info("running: %s", command); pid_t cgroup_pid; - FILE *fp = mypopene(buffer, &cgroup_pid, environment); + FILE *fp = mypopene(command, &cgroup_pid, environment); if(fp) { + char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; char *s; while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) { trim(s); @@ -475,7 +505,7 @@ void call_the_helper(pid_t pid, const char *cgroup) { mypclose(fp, cgroup_pid); } else - error("cannot execute cgroup-network helper script: %s", buffer); + error("cannot execute cgroup-network helper script: %s", command); } int is_valid_path_symbol(char c) { @@ -588,22 +618,23 @@ int main(int argc, char **argv) { program_version = VERSION; error_log_syslog = 0; + // since cgroup-network runs as root, prevent it from opening symbolic links + procfile_open_flags = O_RDONLY|O_NOFOLLOW; // ------------------------------------------------------------------------ // make sure NETDATA_HOST_PREFIX is safe - host_prefix = getenv("NETDATA_HOST_PREFIX"); - if(!host_prefix || !*host_prefix) - host_prefix = ""; + netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX"); + if(verify_netdata_host_prefix() == -1) exit(1); - if(host_prefix[0] != '\0' && verify_path(host_prefix) == -1) - fatal("invalid NETDATA_HOST_PREFIX '%s'", host_prefix); + if(netdata_configured_host_prefix[0] != '\0' && verify_path(netdata_configured_host_prefix) == -1) + fatal("invalid NETDATA_HOST_PREFIX '%s'", netdata_configured_host_prefix); // ------------------------------------------------------------------------ // build a safe environment for our script // the first environment variable is a fixed PATH= - snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", host_prefix); + snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", netdata_configured_host_prefix); // ------------------------------------------------------------------------ diff --git a/src/sys_fs_cgroup.c b/collectors/cgroups.plugin/sys_fs_cgroup.c index f6e613c4..9c0fd7f4 100644 --- a/src/sys_fs_cgroup.c +++ b/collectors/cgroups.plugin/sys_fs_cgroup.c @@ -1,11 +1,14 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "sys_fs_cgroup.h" + +#define PLUGIN_CGROUPS_NAME "cgroups.plugin" +#define PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME "systemd" +#define PLUGIN_CGROUPS_MODULE_CGROUPS_NAME "/sys/fs/cgroup" // ---------------------------------------------------------------------------- // cgroup globals -#define CHART_PRIORITY_SYSTEMD_SERVICES 19000 -#define CHART_PRIORITY_CONTAINERS 40000 - static long system_page_size = 4096; // system will be queried via sysconf() in configuration() static int cgroup_enable_cpuacct_stat = CONFIG_BOOLEAN_AUTO; @@ -71,7 +74,7 @@ void read_cgroup_plugin_configuration() { if(cgroup_update_every < localhost->rrd_update_every) cgroup_update_every = localhost->rrd_update_every; - cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every * cgroup_update_every); + cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", (long long)cgroup_check_for_new_every * (long long)cgroup_update_every); if(cgroup_check_for_new_every < cgroup_update_every) cgroup_check_for_new_every = cgroup_update_every; @@ -751,53 +754,55 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) { debug(D_CGROUP, "looking for the network interfaces of cgroup '%s' with chart id '%s' and title '%s'", cg->id, cg->chart_id, cg->chart_title); pid_t cgroup_pid; - char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; + char command[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; - snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec %s --cgroup '%s%s'", cgroups_network_interface_script, cgroup_cpuacct_base, cg->id); + snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec %s --cgroup '%s%s'", cgroups_network_interface_script, cgroup_cpuacct_base, cg->id); - debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id); - FILE *fp = mypopen(buffer, &cgroup_pid); - if(fp) { - char *s; - while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) { - trim(s); + debug(D_CGROUP, "executing command '%s' for cgroup '%s'", command, cg->id); + FILE *fp = mypopen(command, &cgroup_pid); + if(!fp) { + error("CGROUP: cannot popen(\"%s\", \"r\").", command); + return; + } - if(*s && *s != '\n') { - char *t = s; - while(*t && *t != ' ') t++; - if(*t == ' ') { - *t = '\0'; - t++; - } + char *s; + char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; + while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) { + trim(s); + + if(*s && *s != '\n') { + char *t = s; + while(*t && *t != ' ') t++; + if(*t == ' ') { + *t = '\0'; + t++; + } - if(!*s) { - error("CGROUP: empty host interface returned by script"); - continue; - } + if(!*s) { + error("CGROUP: empty host interface returned by script"); + continue; + } - if(!*t) { - error("CGROUP: empty guest interface returned by script"); - continue; - } + if(!*t) { + error("CGROUP: empty guest interface returned by script"); + continue; + } - struct cgroup_network_interface *i = callocz(1, sizeof(struct cgroup_network_interface)); - i->host_device = strdupz(s); - i->container_device = strdupz(t); - i->next = cg->interfaces; - cg->interfaces = i; + struct cgroup_network_interface *i = callocz(1, sizeof(struct cgroup_network_interface)); + i->host_device = strdupz(s); + i->container_device = strdupz(t); + i->next = cg->interfaces; + cg->interfaces = i; - info("CGROUP: cgroup '%s' has network interface '%s' as '%s'", cg->id, i->host_device, i->container_device); + info("CGROUP: cgroup '%s' has network interface '%s' as '%s'", cg->id, i->host_device, i->container_device); - // register a device rename to proc_net_dev.c - netdev_rename_device_add(i->host_device, i->container_device, cg->chart_id); - } + // register a device rename to proc_net_dev.c + netdev_rename_device_add(i->host_device, i->container_device, cg->chart_id); } - - mypclose(fp, cgroup_pid); - // debug(D_CGROUP, "closed command for cgroup '%s'", cg->id); } - else - error("CGROUP: cannot popen(\"%s\", \"r\").", buffer); + + mypclose(fp, cgroup_pid); + // debug(D_CGROUP, "closed command for cgroup '%s'", cg->id); } static inline void free_cgroup_network_interfaces(struct cgroup *cg) { @@ -845,14 +850,15 @@ static inline void cgroup_get_chart_name(struct cgroup *cg) { debug(D_CGROUP, "looking for the name of cgroup '%s' with chart id '%s' and title '%s'", cg->id, cg->chart_id, cg->chart_title); pid_t cgroup_pid; - char buffer[CGROUP_CHARTID_LINE_MAX + 1]; + char command[CGROUP_CHARTID_LINE_MAX + 1]; - snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s' '%s'", cgroups_rename_script, cg->chart_id, cg->id); + snprintfz(command, CGROUP_CHARTID_LINE_MAX, "exec %s '%s' '%s'", cgroups_rename_script, cg->chart_id, cg->id); - debug(D_CGROUP, "executing command \"%s\" for cgroup '%s'", buffer, cg->id); - FILE *fp = mypopen(buffer, &cgroup_pid); + debug(D_CGROUP, "executing command \"%s\" for cgroup '%s'", command, cg->id); + FILE *fp = mypopen(command, &cgroup_pid); if(fp) { - // debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id); + // debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", command, cg->id); + char buffer[CGROUP_CHARTID_LINE_MAX + 1]; char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp); // debug(D_CGROUP, "closing command for cgroup '%s'", cg->id); mypclose(fp, cgroup_pid); @@ -872,7 +878,7 @@ static inline void cgroup_get_chart_name(struct cgroup *cg) { } } else - error("CGROUP: cannot popen(\"%s\", \"r\").", buffer); + error("CGROUP: cannot popen(\"%s\", \"r\").", command); } static inline struct cgroup *cgroup_add(const char *id) { @@ -1460,9 +1466,9 @@ void update_systemd_services_charts( , "services.cpu" , title , "%" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD , update_every , RRDSET_TYPE_STACKED ); @@ -1484,9 +1490,9 @@ void update_systemd_services_charts( , (cgroup_used_memory_without_cache) ? "Systemd Services Used Memory without Cache" : "Systemd Services Used Memory" , "MB" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 10 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 10 , update_every , RRDSET_TYPE_STACKED ); @@ -1507,9 +1513,9 @@ void update_systemd_services_charts( , "services.mem_rss" , "Systemd Services RSS Memory" , "MB" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 20 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 20 , update_every , RRDSET_TYPE_STACKED ); @@ -1528,9 +1534,9 @@ void update_systemd_services_charts( , "services.mem_mapped" , "Systemd Services Mapped Memory" , "MB" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 30 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 30 , update_every , RRDSET_TYPE_STACKED ); @@ -1549,9 +1555,9 @@ void update_systemd_services_charts( , "services.mem_cache" , "Systemd Services Cache Memory" , "MB" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 40 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 40 , update_every , RRDSET_TYPE_STACKED ); @@ -1570,9 +1576,9 @@ void update_systemd_services_charts( , "services.mem_writeback" , "Systemd Services Writeback Memory" , "MB" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 50 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 50 , update_every , RRDSET_TYPE_STACKED ); @@ -1591,9 +1597,9 @@ void update_systemd_services_charts( , "services.mem_pgfault" , "Systemd Services Memory Minor Page Faults" , "MB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 60 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 60 , update_every , RRDSET_TYPE_STACKED ); @@ -1611,9 +1617,9 @@ void update_systemd_services_charts( , "services.mem_pgmajfault" , "Systemd Services Memory Major Page Faults" , "MB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 70 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 70 , update_every , RRDSET_TYPE_STACKED ); @@ -1632,9 +1638,9 @@ void update_systemd_services_charts( , "services.mem_pgpgin" , "Systemd Services Memory Charging Activity" , "MB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 80 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 80 , update_every , RRDSET_TYPE_STACKED ); @@ -1653,9 +1659,9 @@ void update_systemd_services_charts( , "services.mem_pgpgout" , "Systemd Services Memory Uncharging Activity" , "MB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 90 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 90 , update_every , RRDSET_TYPE_STACKED ); @@ -1676,9 +1682,9 @@ void update_systemd_services_charts( , "services.mem_failcnt" , "Systemd Services Memory Limit Failures" , "MB" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 110 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 110 , update_every , RRDSET_TYPE_STACKED ); @@ -1699,9 +1705,9 @@ void update_systemd_services_charts( , "services.swap_usage" , "Systemd Services Swap Memory Used" , "MB" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 100 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 100 , update_every , RRDSET_TYPE_STACKED ); @@ -1722,9 +1728,9 @@ void update_systemd_services_charts( , "services.io_read" , "Systemd Services Disk Read Bandwidth" , "KB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 120 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 120 , update_every , RRDSET_TYPE_STACKED ); @@ -1743,9 +1749,9 @@ void update_systemd_services_charts( , "services.io_write" , "Systemd Services Disk Write Bandwidth" , "KB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 130 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 130 , update_every , RRDSET_TYPE_STACKED ); @@ -1766,9 +1772,9 @@ void update_systemd_services_charts( , "services.io_ops_read" , "Systemd Services Disk Read Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 140 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 140 , update_every , RRDSET_TYPE_STACKED ); @@ -1787,9 +1793,9 @@ void update_systemd_services_charts( , "services.io_ops_write" , "Systemd Services Disk Write Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 150 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 150 , update_every , RRDSET_TYPE_STACKED ); @@ -1810,9 +1816,9 @@ void update_systemd_services_charts( , "services.throttle_io_read" , "Systemd Services Throttle Disk Read Bandwidth" , "KB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 160 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 160 , update_every , RRDSET_TYPE_STACKED ); @@ -1831,9 +1837,9 @@ void update_systemd_services_charts( , "services.throttle_io_write" , "Systemd Services Throttle Disk Write Bandwidth" , "KB/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 170 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 170 , update_every , RRDSET_TYPE_STACKED ); @@ -1854,9 +1860,9 @@ void update_systemd_services_charts( , "services.throttle_io_ops_read" , "Systemd Services Throttle Disk Read Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 180 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 180 , update_every , RRDSET_TYPE_STACKED ); @@ -1875,9 +1881,9 @@ void update_systemd_services_charts( , "services.throttle_io_ops_write" , "Systemd Services Throttle Disk Write Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 190 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 190 , update_every , RRDSET_TYPE_STACKED ); @@ -1898,9 +1904,9 @@ void update_systemd_services_charts( , "services.queued_io_ops_read" , "Systemd Services Queued Disk Read Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 200 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 200 , update_every , RRDSET_TYPE_STACKED ); @@ -1919,9 +1925,9 @@ void update_systemd_services_charts( , "services.queued_io_ops_write" , "Systemd Services Queued Disk Write Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 210 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 210 , update_every , RRDSET_TYPE_STACKED ); @@ -1942,9 +1948,9 @@ void update_systemd_services_charts( , "services.merged_io_ops_read" , "Systemd Services Merged Disk Read Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 220 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 220 , update_every , RRDSET_TYPE_STACKED ); @@ -1963,9 +1969,9 @@ void update_systemd_services_charts( , "services.merged_io_ops_write" , "Systemd Services Merged Disk Write Operations" , "operations/s" - , "cgroup" - , "systemd" - , CHART_PRIORITY_SYSTEMD_SERVICES + 230 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_SYSTEMD_NAME + , NETDATA_CHART_PRIO_CGROUPS_SYSTEMD + 230 , update_every , RRDSET_TYPE_STACKED ); @@ -1983,7 +1989,7 @@ void update_systemd_services_charts( if(likely(do_cpu && cg->cpuacct_stat.updated)) { if(unlikely(!cg->rd_cpu)) - cg->rd_cpu = rrddim_add(st_cpu, cg->chart_id, cg->chart_title, 100, hz, RRD_ALGORITHM_INCREMENTAL); + cg->rd_cpu = rrddim_add(st_cpu, cg->chart_id, cg->chart_title, 100, system_hz, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_cpu, cg->rd_cpu, cg->cpuacct_stat.user + cg->cpuacct_stat.system); } @@ -2245,15 +2251,15 @@ void update_cgroup_charts(int update_every) { , "cgroup.cpu" , title , "%" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS , update_every , RRDSET_TYPE_STACKED ); - rrddim_add(cg->st_cpu, "user", NULL, 100, hz, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(cg->st_cpu, "system", NULL, 100, hz, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_cpu, "user", NULL, 100, system_hz, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_cpu, "system", NULL, 100, system_hz, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_cpu); @@ -2278,9 +2284,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.cpu_per_core" , title , "%" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 100 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 100 , update_every , RRDSET_TYPE_STACKED ); @@ -2312,9 +2318,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem" , title , "MB" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 210 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 210 , update_every , RRDSET_TYPE_STACKED ); @@ -2332,7 +2338,7 @@ void update_cgroup_charts(int update_every) { rrdset_next(cg->st_mem); rrddim_set(cg->st_mem, "cache", cg->memory.cache); - rrddim_set(cg->st_mem, "rss", cg->memory.rss); + rrddim_set(cg->st_mem, "rss", (cg->memory.rss > cg->memory.rss_huge)?(cg->memory.rss - cg->memory.rss_huge):0); if(cg->memory.detailed_has_swap) rrddim_set(cg->st_mem, "swap", cg->memory.swap); @@ -2352,9 +2358,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.writeback" , title , "MB" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 300 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 300 , update_every , RRDSET_TYPE_AREA ); @@ -2384,9 +2390,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem_activity" , title , "MB/s" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 400 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 400 , update_every , RRDSET_TYPE_LINE ); @@ -2412,9 +2418,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.pgfaults" , title , "MB/s" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 500 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 500 , update_every , RRDSET_TYPE_LINE ); @@ -2442,9 +2448,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem_usage" , title , "MB" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 200 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 200 , update_every , RRDSET_TYPE_STACKED ); @@ -2472,9 +2478,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.mem_failcnt" , title , "count" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 250 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 250 , update_every , RRDSET_TYPE_LINE ); @@ -2500,9 +2506,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.io" , title , "KB/s" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 1200 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 1200 , update_every , RRDSET_TYPE_AREA ); @@ -2530,9 +2536,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.serviced_ops" , title , "operations/s" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 1200 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 1200 , update_every , RRDSET_TYPE_LINE ); @@ -2560,9 +2566,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.throttle_io" , title , "KB/s" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 1200 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 1200 , update_every , RRDSET_TYPE_AREA ); @@ -2590,9 +2596,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.throttle_serviced_ops" , title , "operations/s" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 1200 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 1200 , update_every , RRDSET_TYPE_LINE ); @@ -2620,9 +2626,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.queued_ops" , title , "operations" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 2000 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 2000 , update_every , RRDSET_TYPE_LINE ); @@ -2650,9 +2656,9 @@ void update_cgroup_charts(int update_every) { , "cgroup.merged_ops" , title , "operations/s" - , "cgroup" - , "default" - , CHART_PRIORITY_CONTAINERS + 2100 + , PLUGIN_CGROUPS_NAME + , PLUGIN_CGROUPS_MODULE_CGROUPS_NAME + , NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 2100 , update_every , RRDSET_TYPE_LINE ); @@ -2741,7 +2747,7 @@ void *cgroups_main(void *ptr) { , NULL , "NetData CGroups Plugin CPU usage" , "milliseconds/s" - , "cgroup" + , PLUGIN_CGROUPS_NAME , "stats" , 132000 , cgroup_update_every diff --git a/src/plugin_checks.c b/collectors/checks.plugin/plugin_checks.c index b99b97d4..f8a2008a 100644 --- a/src/plugin_checks.c +++ b/collectors/checks.plugin/plugin_checks.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_checks.h" #ifdef NETDATA_INTERNAL_CHECKS @@ -27,9 +29,9 @@ void *checks_main(void *ptr) { , NULL , "Caller gives microseconds" , "a million !" - , "netdata" - , "checks" - , 99999 + , "checks.plugin" + , "" + , NETDATA_CHART_PRIO_CHECKS , localhost->rrd_update_every , RRDSET_TYPE_LINE ); @@ -45,9 +47,9 @@ void *checks_main(void *ptr) { , NULL , "Netdata calcs microseconds" , "a million !" - , "netdata" - , "checks" - , 99999 + , "checks.plugin" + , "" + , NETDATA_CHART_PRIO_CHECKS , localhost->rrd_update_every , RRDSET_TYPE_LINE ); @@ -62,9 +64,9 @@ void *checks_main(void *ptr) { , NULL , "Clock difference" , "microseconds diff" - , "netdata" - , "checks" - , 99999 + , "checks.plugin" + , "" + , NETDATA_CHART_PRIO_CHECKS , localhost->rrd_update_every , RRDSET_TYPE_LINE ); diff --git a/src/plugin_proc_diskspace.c b/collectors/diskspace.plugin/plugin_diskspace.c index 0a229f38..dca7c907 100644 --- a/src/plugin_proc_diskspace.c +++ b/collectors/diskspace.plugin/plugin_diskspace.c @@ -1,7 +1,11 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_diskspace.h" + +#define PLUGIN_DISKSPACE_NAME "diskspace.plugin" #define DELAULT_EXCLUDED_PATHS "/proc/* /sys/* /var/run/user/* /run/user/* /snap/* /var/lib/docker/*" -#define DEFAULT_EXCLUDED_FILESYSTEMS "" +#define DEFAULT_EXCLUDED_FILESYSTEMS "*gvfs *gluster* *s3fs *ipfs *davfs2 *httpfs *sshfs *gdfs *moosefs fusectl" #define CONFIG_SECTION_DISKSPACE "plugin:proc:diskspace" static struct mountinfo *disk_mountinfo_root = NULL; @@ -129,7 +133,8 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { } // check if the mount point is a directory #2407 - { + // but only when it is enabled by default #4491 + if(def_space != CONFIG_BOOLEAN_NO || def_inodes != CONFIG_BOOLEAN_NO) { struct stat bs; if(stat(mi->mount_point, &bs) == -1) { error("DISKSPACE: Cannot stat() mount point '%s' (disk '%s', filesystem '%s', root '%s')." @@ -259,9 +264,9 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { , "disk.space" , title , "GB" - , "diskspace" + , PLUGIN_DISKSPACE_NAME , NULL - , 2023 + , NETDATA_CHART_PRIO_DISKSPACE_SPACE , update_every , RRDSET_TYPE_STACKED ); @@ -299,9 +304,9 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { , "disk.inodes" , title , "Inodes" - , "diskspace" + , PLUGIN_DISKSPACE_NAME , NULL - , 2024 + , NETDATA_CHART_PRIO_DISKSPACE_INODES , update_every , RRDSET_TYPE_STACKED ); @@ -337,7 +342,7 @@ static void diskspace_main_cleanup(void *ptr) { static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; } -void *proc_diskspace_main(void *ptr) { +void *diskspace_main(void *ptr) { netdata_thread_cleanup_push(diskspace_main_cleanup, ptr); int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1); @@ -359,7 +364,7 @@ void *proc_diskspace_main(void *ptr) { heartbeat_t hb; heartbeat_init(&hb); while(!netdata_exit) { - duration = heartbeat_dt_usec(&hb); + duration = heartbeat_monotonic_dt_to_now_usec(&hb); /* usec_t hb_dt = */ heartbeat_next(&hb, step); if(unlikely(netdata_exit)) break; @@ -406,9 +411,9 @@ void *proc_diskspace_main(void *ptr) { , NULL , "NetData Disk Space Plugin CPU usage" , "milliseconds/s" - , "diskspace" + , PLUGIN_DISKSPACE_NAME , NULL - , 132020 + , NETDATA_CHART_PRIO_NETDATA_DISKSPACE , update_every , RRDSET_TYPE_STACKED ); @@ -434,7 +439,7 @@ void *proc_diskspace_main(void *ptr) { , NULL , "NetData Disk Space Plugin Duration" , "milliseconds/run" - , "diskspace" + , PLUGIN_DISKSPACE_NAME , NULL , 132021 , update_every diff --git a/src/freebsd_devstat.c b/collectors/freebsd.plugin/freebsd_devstat.c index ed7466ea..10279aab 100644 --- a/src/freebsd_devstat.c +++ b/collectors/freebsd.plugin/freebsd_devstat.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_freebsd.h" #include <sys/devicestat.h> @@ -359,9 +361,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.io", "Disk I/O Bandwidth", "kilobytes/s", - "freebsd", + "freebsd.plugin", "devstat", - 2000, + NETDATA_CHART_PRIO_DISK_IO, update_every, RRDSET_TYPE_AREA ); @@ -396,9 +398,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.ops", "Disk Completed I/O Operations", "operations/s", - "freebsd", + "freebsd.plugin", "devstat", - 2001, + NETDATA_CHART_PRIO_DISK_OPS, update_every, RRDSET_TYPE_LINE ); @@ -435,9 +437,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.qops", "Disk Current I/O Operations", "operations", - "freebsd", + "freebsd.plugin", "devstat", - 2002, + NETDATA_CHART_PRIO_DISK_QOPS, update_every, RRDSET_TYPE_LINE ); @@ -464,9 +466,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.util", "Disk Utilization Time", "% of time working", - "freebsd", + "freebsd.plugin", "devstat", - 2004, + NETDATA_CHART_PRIO_DISK_UTIL, update_every, RRDSET_TYPE_AREA ); @@ -497,9 +499,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.iotime", "Disk Total I/O Time", "milliseconds/s", - "freebsd", + "freebsd.plugin", "devstat", - 2022, + NETDATA_CHART_PRIO_DISK_IOTIME, update_every, RRDSET_TYPE_LINE ); @@ -545,9 +547,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.await", "Average Completed I/O Operation Time", "ms per operation", - "freebsd", + "freebsd.plugin", "devstat", - 2005, + NETDATA_CHART_PRIO_DISK_AWAIT, update_every, RRDSET_TYPE_LINE ); @@ -610,9 +612,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", - "freebsd", + "freebsd.plugin", "devstat", - 2006, + NETDATA_CHART_PRIO_DISK_AVGSZ, update_every, RRDSET_TYPE_AREA ); @@ -667,9 +669,9 @@ int do_kern_devstat(int update_every, usec_t dt) { "disk.svctm", "Average Service Time", "ms per operation", - "freebsd", + "freebsd.plugin", "devstat", - 2007, + NETDATA_CHART_PRIO_DISK_SVCTM, update_every, RRDSET_TYPE_LINE ); @@ -727,9 +729,9 @@ int do_kern_devstat(int update_every, usec_t dt) { NULL, "Disk I/O", "kilobytes/s", - "freebsd", + "freebsd.plugin", "devstat", - 150, + NETDATA_CHART_PRIO_SYSTEM_IO, update_every, RRDSET_TYPE_AREA ); diff --git a/src/freebsd_getifaddrs.c b/collectors/freebsd.plugin/freebsd_getifaddrs.c index 73f8f182..e1584585 100644 --- a/src/freebsd_getifaddrs.c +++ b/collectors/freebsd.plugin/freebsd_getifaddrs.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_freebsd.h" #include <ifaddrs.h> @@ -141,19 +143,24 @@ static struct cgroup_network_interface *get_network_interface(const char *name) int do_getifaddrs(int update_every, usec_t dt) { (void)dt; -#define DELAULT_EXLUDED_INTERFACES "lo*" +#define DEFAULT_EXLUDED_INTERFACES "lo*" +#define DEFAULT_PHYSICAL_INTERFACES "igb* ix* cxl* em* ixl* ixlv* bge* ixgbe*" #define CONFIG_SECTION_GETIFADDRS "plugin:freebsd:getifaddrs" static int enable_new_interfaces = -1; - static int do_bandwidth_ipv4 = -1, do_bandwidth_ipv6 = -1, do_bandwidth = -1, do_packets = -1, + static int do_bandwidth_ipv4 = -1, do_bandwidth_ipv6 = -1, do_bandwidth = -1, do_packets = -1, do_bandwidth_net = -1, do_packets_net = -1, do_errors = -1, do_drops = -1, do_events = -1; - static SIMPLE_PATTERN *excluded_interfaces = NULL; + static SIMPLE_PATTERN *excluded_interfaces = NULL, *physical_interfaces = NULL; if (unlikely(enable_new_interfaces == -1)) { enable_new_interfaces = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "enable new interfaces detected at runtime", CONFIG_BOOLEAN_AUTO); - + + do_bandwidth_net = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for physical interfaces", + CONFIG_BOOLEAN_AUTO); + do_packets_net = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total packets for physical interfaces", + CONFIG_BOOLEAN_AUTO); do_bandwidth_ipv4 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv4 interfaces", CONFIG_BOOLEAN_AUTO); do_bandwidth_ipv6 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv6 interfaces", @@ -170,18 +177,27 @@ int do_getifaddrs(int update_every, usec_t dt) { CONFIG_BOOLEAN_AUTO); excluded_interfaces = simple_pattern_create( - config_get(CONFIG_SECTION_GETIFADDRS, "disable by default interfaces matching", DELAULT_EXLUDED_INTERFACES) + config_get(CONFIG_SECTION_GETIFADDRS, "disable by default interfaces matching", DEFAULT_EXLUDED_INTERFACES) + , NULL + , SIMPLE_PATTERN_EXACT + ); + physical_interfaces = simple_pattern_create( + config_get(CONFIG_SECTION_GETIFADDRS, "set physical interfaces for system.net", DEFAULT_PHYSICAL_INTERFACES) , NULL , SIMPLE_PATTERN_EXACT ); } - if (likely(do_bandwidth_ipv4 || do_bandwidth_ipv6 || do_bandwidth || do_packets || do_errors || + if (likely(do_bandwidth_ipv4 || do_bandwidth_ipv6 || do_bandwidth || do_packets || do_errors || do_bandwidth_net || do_packets_net || do_drops || do_events)) { struct ifaddrs *ifap; if (unlikely(getifaddrs(&ifap))) { error("FREEBSD: getifaddrs() failed"); + do_bandwidth_net = 0; + error("DISABLED: system.net chart"); + do_packets_net = 0; + error("DISABLED: system.packets chart"); do_bandwidth_ipv4 = 0; error("DISABLED: system.ipv4 chart"); do_bandwidth_ipv6 = 0; @@ -204,7 +220,103 @@ int do_getifaddrs(int update_every, usec_t dt) { struct iftot { u_long ift_ibytes; u_long ift_obytes; - } iftot = {0, 0}; + u_long ift_ipackets; + u_long ift_opackets; + u_long ift_imcasts; + u_long ift_omcasts; + } iftot = {0, 0, 0, 0, 0, 0}; + + // -------------------------------------------------------------------- + + if (likely(do_bandwidth_net)) { + + iftot.ift_ibytes = iftot.ift_obytes = 0; + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family != AF_LINK) + continue; + if (!simple_pattern_matches(physical_interfaces, ifa->ifa_name)) + continue; + iftot.ift_ibytes += IFA_DATA(ibytes); + iftot.ift_obytes += IFA_DATA(obytes); + } + + static RRDSET *st = NULL; + static RRDDIM *rd_in = NULL, *rd_out = NULL; + + if (unlikely(!st)) { + st = rrdset_create_localhost("system", + "net", + NULL, + "network", + NULL, + "Network Traffic", + "kilobits/s", + "freebsd.plugin", + "getifaddrs", + NETDATA_CHART_PRIO_SYSTEM_NET, + update_every, + RRDSET_TYPE_AREA + ); + + 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; + if (!simple_pattern_matches(physical_interfaces, ifa->ifa_name)) + continue; + iftot.ift_ipackets += IFA_DATA(ipackets); + iftot.ift_opackets += IFA_DATA(opackets); + iftot.ift_imcasts += IFA_DATA(imcasts); + iftot.ift_omcasts += IFA_DATA(omcasts); + } + + static RRDSET *st = NULL; + static RRDDIM *rd_packets_in = NULL, *rd_packets_out = NULL, *rd_packets_m_in = NULL, *rd_packets_m_out = NULL; + + if (unlikely(!st)) { + st = rrdset_create_localhost("system", + "packets", + NULL, + "network", + NULL, + "Network Packets", + "packets/s", + "freebsd.plugin", + "getifaddrs", + NETDATA_CHART_PRIO_SYSTEM_PACKETS, + update_every, + RRDSET_TYPE_LINE + ); + + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rd_packets_in = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + 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); + rrddim_set_by_pointer(st, rd_packets_m_in, iftot.ift_imcasts); + rrddim_set_by_pointer(st, rd_packets_m_out, iftot.ift_omcasts); + rrdset_done(st); + } // -------------------------------------------------------------------- @@ -228,9 +340,9 @@ int do_getifaddrs(int update_every, usec_t dt) { NULL, "IPv4 Bandwidth", "kilobits/s", - "freebsd", + "freebsd.plugin", "getifaddrs", - 500, + NETDATA_CHART_PRIO_SYSTEM_IPV4, update_every, RRDSET_TYPE_AREA ); @@ -267,9 +379,9 @@ int do_getifaddrs(int update_every, usec_t dt) { NULL, "IPv6 Bandwidth", "kilobits/s", - "freebsd", + "freebsd.plugin", "getifaddrs", - 500, + NETDATA_CHART_PRIO_SYSTEM_IPV6, update_every, RRDSET_TYPE_AREA ); @@ -337,9 +449,9 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.net", "Bandwidth", "kilobits/s", - "freebsd", + "freebsd.plugin", "getifaddrs", - 7000, + NETDATA_CHART_PRIO_FIRST_NET_IFACE, update_every, RRDSET_TYPE_AREA ); @@ -366,9 +478,9 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.packets", "Packets", "packets/s", - "freebsd", + "freebsd.plugin", "getifaddrs", - 7001, + NETDATA_CHART_PRIO_FIRST_NET_PACKETS, update_every, RRDSET_TYPE_LINE ); @@ -405,9 +517,9 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.errors", "Interface Errors", "errors/s", - "freebsd", + "freebsd.plugin", "getifaddrs", - 7002, + NETDATA_CHART_PRIO_FIRST_NET_ERRORS, update_every, RRDSET_TYPE_LINE ); @@ -439,9 +551,9 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.drops", "Interface Drops", "drops/s", - "freebsd", + "freebsd.plugin", "getifaddrs", - 7003, + NETDATA_CHART_PRIO_FIRST_NET_DROPS, update_every, RRDSET_TYPE_LINE ); @@ -474,9 +586,9 @@ int do_getifaddrs(int update_every, usec_t dt) { "net.events", "Network Interface Events", "events/s", - "freebsd", + "freebsd.plugin", "getifaddrs", - 7006, + NETDATA_CHART_PRIO_FIRST_NET_EVENTS, update_every, RRDSET_TYPE_LINE ); diff --git a/src/freebsd_getmntinfo.c b/collectors/freebsd.plugin/freebsd_getmntinfo.c index ea82b9fd..c86f2316 100644 --- a/src/freebsd_getmntinfo.c +++ b/collectors/freebsd.plugin/freebsd_getmntinfo.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_freebsd.h" #include <sys/mount.h> @@ -225,9 +227,9 @@ int do_getmntinfo(int update_every, usec_t dt) { "disk.space", title, "GB", - "freebsd", + "freebsd.plugin", "getmntinfo", - 2023, + NETDATA_CHART_PRIO_DISKSPACE_SPACE, update_every, RRDSET_TYPE_STACKED ); @@ -264,9 +266,9 @@ int do_getmntinfo(int update_every, usec_t dt) { "disk.inodes", title, "Inodes", - "freebsd", + "freebsd.plugin", "getmntinfo", - 2024, + NETDATA_CHART_PRIO_DISKSPACE_INODES, update_every, RRDSET_TYPE_STACKED ); diff --git a/src/freebsd_ipfw.c b/collectors/freebsd.plugin/freebsd_ipfw.c index 81264b3f..c256da8b 100644 --- a/src/freebsd_ipfw.c +++ b/collectors/freebsd.plugin/freebsd_ipfw.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_freebsd.h" #include <netinet/ip_fw.h> @@ -162,9 +164,9 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Memory allocated by rules", "bytes", - "freebsd", + "freebsd.plugin", "ipfw", - 3005, + NETDATA_CHART_PRIO_IPFW_MEM, update_every, RRDSET_TYPE_STACKED ); @@ -195,9 +197,9 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Packets", "packets/s", - "freebsd", + "freebsd.plugin", "ipfw", - 3001, + NETDATA_CHART_PRIO_IPFW_PACKETS, update_every, RRDSET_TYPE_STACKED ); @@ -212,9 +214,9 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Bytes", "bytes/s", - "freebsd", + "freebsd.plugin", "ipfw", - 3002, + NETDATA_CHART_PRIO_IPFW_BYTES, update_every, RRDSET_TYPE_STACKED ); @@ -316,9 +318,9 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Active rules", "rules", - "freebsd", + "freebsd.plugin", "ipfw", - 3003, + NETDATA_CHART_PRIO_IPFW_ACTIVE, update_every, RRDSET_TYPE_STACKED ); @@ -333,9 +335,9 @@ int do_ipfw(int update_every, usec_t dt) { NULL, "Expired rules", "rules", - "freebsd", + "freebsd.plugin", "ipfw", - 3004, + NETDATA_CHART_PRIO_IPFW_EXPIRED, update_every, RRDSET_TYPE_STACKED ); diff --git a/src/freebsd_kstat_zfs.c b/collectors/freebsd.plugin/freebsd_kstat_zfs.c index 1bd48d4b..93dfc320 100644 --- a/src/freebsd_kstat_zfs.c +++ b/collectors/freebsd.plugin/freebsd_kstat_zfs.c @@ -1,5 +1,7 @@ -#include "common.h" -#include "zfs_common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_freebsd.h" +#include "collectors/proc.plugin/zfs_common.h" extern struct arcstats arcstats; @@ -207,8 +209,8 @@ int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt) { // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_need_free", mibs.arc_need_free, arcstats.arc_need_free); // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_sys_free", mibs.arc_sys_free, arcstats.arc_sys_free); - generate_charts_arcstats("freebsd", update_every); - generate_charts_arc_summary("freebsd", update_every); + generate_charts_arcstats("freebsd", "zfs", update_every); + generate_charts_arc_summary("freebsd", "zfs", update_every); return 0; } diff --git a/src/freebsd_sysctl.c b/collectors/freebsd.plugin/freebsd_sysctl.c index 1e11255a..da5a351d 100644 --- a/src/freebsd_sysctl.c +++ b/collectors/freebsd.plugin/freebsd_sysctl.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_freebsd.h" #include <sys/vmmeter.h> #include <vm/vm_param.h> @@ -84,6 +86,10 @@ typedef struct __vmmeter vmmeter_t; typedef struct vmmeter vmmeter_t; #endif +#if (__FreeBSD_version >= 1101516 && __FreeBSD_version < 1200000) || __FreeBSD_version >= 1200015 +#define NETDATA_COLLECT_LAUNDRY 1 +#endif + // -------------------------------------------------------------------------------------------------------------------- // FreeBSD plugin initialization @@ -141,9 +147,9 @@ int do_vm_loadavg(int update_every, usec_t dt){ NULL, "System Load Average", "load", - "freebsd", + "freebsd.plugin", "vm.loadavg", - 100, + NETDATA_CHART_PRIO_SYSTEM_LOAD, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE ); @@ -210,9 +216,9 @@ int do_vm_vmtotal(int update_every, usec_t dt) { NULL, "System Active Processes", "processes", - "freebsd", + "freebsd.plugin", "vm.vmtotal", - 750, + NETDATA_CHART_PRIO_SYSTEM_ACTIVE_PROCESSES, update_every, RRDSET_TYPE_LINE ); @@ -239,9 +245,9 @@ int do_vm_vmtotal(int update_every, usec_t dt) { NULL, "System Processes", "processes", - "freebsd", + "freebsd.plugin", "vm.vmtotal", - 600, + NETDATA_CHART_PRIO_SYSTEM_PROCESSES, update_every, RRDSET_TYPE_LINE ); @@ -271,7 +277,7 @@ int do_vm_vmtotal(int update_every, usec_t dt) { NULL, "Committed (Allocated) Memory", "MB", - "freebsd", + "freebsd.plugin", "vm.vmtotal", NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED, update_every, @@ -330,9 +336,10 @@ int do_kern_cp_time(int update_every, usec_t dt) { "system.cpu", "Total CPU utilization", "percentage", - "freebsd", + "freebsd.plugin", "kern.cp_time", - 100, update_every, + NETDATA_CHART_PRIO_SYSTEM_CPU, + update_every, RRDSET_TYPE_STACKED ); @@ -411,9 +418,9 @@ int do_kern_cp_times(int update_every, usec_t dt) { "cpu.cpu", "Core utilization", "percentage", - "freebsd", + "freebsd.plugin", "kern.cp_times", - 1000, + NETDATA_CHART_PRIO_CPU_PER_CORE, update_every, RRDSET_TYPE_STACKED ); @@ -495,9 +502,9 @@ int do_dev_cpu_temperature(int update_every, usec_t dt) { "cpu.temperatute", "Core temperature", "Celsius", - "freebsd", + "freebsd.plugin", "dev.cpu.temperature", - 1050, + NETDATA_CHART_PRIO_CPU_TEMPERATURE, update_every, RRDSET_TYPE_LINE ); @@ -548,9 +555,9 @@ int do_dev_cpu_0_freq(int update_every, usec_t dt) { NULL, "Current CPU Scaling Frequency", "MHz", - "freebsd", + "freebsd.plugin", "dev.cpu.0.freq", - 5003, + NETDATA_CHART_PRIO_CPUFREQ_SCALING_CUR_FREQ, update_every, RRDSET_TYPE_LINE ); @@ -612,9 +619,9 @@ int do_hw_intcnt(int update_every, usec_t dt) { NULL, "Total Hardware Interrupts", "interrupts/s", - "freebsd", + "freebsd.plugin", "hw.intrcnt", - 900, + NETDATA_CHART_PRIO_SYSTEM_INTR, update_every, RRDSET_TYPE_LINE ); @@ -657,9 +664,9 @@ int do_hw_intcnt(int update_every, usec_t dt) { NULL, "System interrupts", "interrupts/s", - "freebsd", + "freebsd.plugin", "hw.intrcnt", - 1000, + NETDATA_CHART_PRIO_SYSTEM_INTERRUPTS, update_every, RRDSET_TYPE_STACKED ); @@ -715,9 +722,9 @@ int do_vm_stats_sys_v_intr(int update_every, usec_t dt) { NULL, "Device Interrupts", "interrupts/s", - "freebsd", + "freebsd.plugin", "vm.stats.sys.v_intr", - 1000, + NETDATA_CHART_PRIO_SYSTEM_DEV_INTR, update_every, RRDSET_TYPE_LINE ); @@ -761,9 +768,9 @@ int do_vm_stats_sys_v_soft(int update_every, usec_t dt) { NULL, "Software Interrupts", "interrupts/s", - "freebsd", + "freebsd.plugin", "vm.stats.sys.v_soft", - 1100, + NETDATA_CHART_PRIO_SYSTEM_SOFT_INTR, update_every, RRDSET_TYPE_LINE ); @@ -807,9 +814,9 @@ int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) { NULL, "CPU Context Switches", "context switches/s", - "freebsd", + "freebsd.plugin", "vm.stats.sys.v_swtch", - 800, + NETDATA_CHART_PRIO_SYSTEM_CTXT, update_every, RRDSET_TYPE_LINE ); @@ -853,9 +860,9 @@ int do_vm_stats_sys_v_forks(int update_every, usec_t dt) { NULL, "Started Processes", "processes/s", - "freebsd", + "freebsd.plugin", "vm.stats.sys.v_swtch", - 700, + NETDATA_CHART_PRIO_SYSTEM_FORKS, update_every, RRDSET_TYPE_LINE ); @@ -930,9 +937,9 @@ int do_vm_swap_info(int update_every, usec_t dt) { NULL, "System Swap", "MB", - "freebsd", + "freebsd.plugin", "vm.swap_info", - 201, + NETDATA_CHART_PRIO_SYSTEM_SWAP, update_every, RRDSET_TYPE_STACKED ); @@ -958,7 +965,8 @@ int do_vm_swap_info(int update_every, usec_t dt) { int do_system_ram(int update_every, usec_t dt) { (void)dt; static int mib_active_count[4] = {0, 0, 0, 0}, mib_inactive_count[4] = {0, 0, 0, 0}, mib_wire_count[4] = {0, 0, 0, 0}, - mib_cache_count[4] = {0, 0, 0, 0}, mib_vfs_bufspace[2] = {0, 0}, mib_free_count[4] = {0, 0, 0, 0}; + mib_cache_count[4] = {0, 0, 0, 0}, mib_laundry_count[4] = {0, 0, 0, 0}, mib_vfs_bufspace[2] = {0, 0}, + mib_free_count[4] = {0, 0, 0, 0}; vmmeter_t vmmeter_data; int vfs_bufspace_count; @@ -968,6 +976,9 @@ int do_system_ram(int update_every, usec_t dt) { #if __FreeBSD_version < 1200016 GETSYSCTL_SIMPLE("vm.stats.vm.v_cache_count", mib_cache_count, vmmeter_data.v_cache_count) || #endif +#if defined(NETDATA_COLLECT_LAUNDRY) + GETSYSCTL_SIMPLE("vm.stats.vm.v_laundry_count", mib_laundry_count, vmmeter_data.v_laundry_count) || +#endif GETSYSCTL_SIMPLE("vfs.bufspace", mib_vfs_bufspace, vfs_bufspace_count) || GETSYSCTL_SIMPLE("vm.stats.vm.v_free_count", mib_free_count, vmmeter_data.v_free_count))) { error("DISABLED: system.ram chart"); @@ -978,8 +989,8 @@ int do_system_ram(int update_every, usec_t dt) { // -------------------------------------------------------------------- static RRDSET *st = NULL; - static RRDDIM *rd_free = NULL, *rd_active = NULL, *rd_inactive = NULL, - *rd_wired = NULL, *rd_cache = NULL, *rd_buffers = NULL; + static RRDDIM *rd_free = NULL, *rd_active = NULL, *rd_inactive = NULL, *rd_wired = NULL, + *rd_cache = NULL, *rd_laundry = NULL, *rd_buffers = NULL; if (unlikely(!st)) { st = rrdset_create_localhost( @@ -990,9 +1001,9 @@ int do_system_ram(int update_every, usec_t dt) { NULL, "System RAM", "MB", - "freebsd", + "freebsd.plugin", "system.ram", - 200, + NETDATA_CHART_PRIO_SYSTEM_RAM, update_every, RRDSET_TYPE_STACKED ); @@ -1004,6 +1015,9 @@ int do_system_ram(int update_every, usec_t dt) { #if __FreeBSD_version < 1200016 rd_cache = rrddim_add(st, "cache", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); #endif +#if defined(NETDATA_COLLECT_LAUNDRY) + rd_laundry = rrddim_add(st, "laundry", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); +#endif rd_buffers = rrddim_add(st, "buffers", NULL, 1, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -1015,6 +1029,9 @@ int do_system_ram(int update_every, usec_t dt) { #if __FreeBSD_version < 1200016 rrddim_set_by_pointer(st, rd_cache, vmmeter_data.v_cache_count); #endif +#if defined(NETDATA_COLLECT_LAUNDRY) + rrddim_set_by_pointer(st, rd_laundry, vmmeter_data.v_laundry_count); +#endif rrddim_set_by_pointer(st, rd_buffers, vfs_bufspace_count); rrdset_done(st); } @@ -1051,9 +1068,9 @@ int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) { NULL, "Swap I/O", "kilobytes/s", - "freebsd", + "freebsd.plugin", "vm.stats.vm.v_swappgs", - 250, + NETDATA_CHART_PRIO_SYSTEM_SWAPIO, update_every, RRDSET_TYPE_AREA ); @@ -1105,7 +1122,7 @@ int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) { NULL, "Memory Page Faults", "page faults/s", - "freebsd", + "freebsd.plugin", "vm.stats.vm.v_pgfaults", NETDATA_CHART_PRIO_MEM_SYSTEM_PGFAULTS, update_every, @@ -1187,9 +1204,9 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { NULL, "IPC Semaphores", "semaphores", - "freebsd", + "freebsd.plugin", "kern.ipc.sem", - 1000, + NETDATA_CHART_PRIO_SYSTEM_IPC_SEMAPHORES, update_every, RRDSET_TYPE_AREA ); @@ -1212,9 +1229,9 @@ int do_kern_ipc_sem(int update_every, usec_t dt) { NULL, "IPC Semaphore Arrays", "arrays", - "freebsd", + "freebsd.plugin", "kern.ipc.sem", - 1000, + NETDATA_CHART_PRIO_SYSTEM_IPC_SEM_ARRAYS, update_every, RRDSET_TYPE_AREA ); @@ -1286,9 +1303,9 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { NULL, "IPC Shared Memory Segments", "segments", - "freebsd", + "freebsd.plugin", "kern.ipc.shm", - 1000, + NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SEGS, update_every, RRDSET_TYPE_AREA ); @@ -1311,9 +1328,9 @@ int do_kern_ipc_shm(int update_every, usec_t dt) { NULL, "IPC Shared Memory Segments Size", "kilobytes", - "freebsd", + "freebsd.plugin", "kern.ipc.shm", - 1000, + NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SIZE, update_every, RRDSET_TYPE_AREA ); @@ -1391,9 +1408,9 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { NULL, "Number of IPC Message Queues", "queues", - "freebsd", + "freebsd.plugin", "kern.ipc.msq", - 990, + NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_QUEUES, update_every, RRDSET_TYPE_AREA ); @@ -1416,9 +1433,9 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { NULL, "Number of Messages in IPC Message Queues", "messages", - "freebsd", + "freebsd.plugin", "kern.ipc.msq", - 1000, + NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_MESSAGES, update_every, RRDSET_TYPE_AREA ); @@ -1441,9 +1458,9 @@ int do_kern_ipc_msq(int update_every, usec_t dt) { NULL, "Size of IPC Message Queues", "bytes", - "freebsd", + "freebsd.plugin", "kern.ipc.msq", - 1100, + NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_SIZE, update_every, RRDSET_TYPE_LINE ); @@ -1485,9 +1502,9 @@ int do_uptime(int update_every, usec_t dt) { NULL, "System Uptime", "seconds", - "freebsd", + "freebsd.plugin", "uptime", - 1000, + NETDATA_CHART_PRIO_SYSTEM_UPTIME, update_every, RRDSET_TYPE_LINE ); @@ -1613,9 +1630,9 @@ int do_net_isr(int update_every, usec_t dt) { NULL, "System softnet_stat", "events/s", - "freebsd", + "freebsd.plugin", "net.isr", - 955, + NETDATA_CHART_PRIO_SYSTEM_SOFTNET_STAT, update_every, RRDSET_TYPE_LINE ); @@ -1666,9 +1683,9 @@ int do_net_isr(int update_every, usec_t dt) { NULL, "Per CPU netisr statistics", "events/s", - "freebsd", + "freebsd.plugin", "net.isr", - 1101 + i, + NETDATA_CHART_PRIO_SOFTNET_PER_CORE + i, update_every, RRDSET_TYPE_LINE ); @@ -1728,7 +1745,7 @@ int do_net_inet_tcp_states(int update_every, usec_t dt) { NULL, "IPv4 TCP Connections", "active connections", - "freebsd", + "freebsd.plugin", "net.inet.tcp.states", 2500, update_every, @@ -1812,7 +1829,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "IPv4 TCP Packets", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 2600, update_every, @@ -1844,7 +1861,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "IPv4 TCP Errors", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 2700, update_every, @@ -1886,7 +1903,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "IPv4 TCP Handshake Issues", "events/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 2900, update_every, @@ -1927,7 +1944,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "TCP Connection Aborts", "connections/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 3010, update_every, @@ -1967,7 +1984,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "TCP Out-Of-Order Queue", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 3050, update_every, @@ -1999,7 +2016,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "TCP SYN Cookies", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 3100, update_every, @@ -2036,7 +2053,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "TCP Listen Socket Issues", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 3015, update_every, @@ -2070,7 +2087,7 @@ int do_net_inet_tcp_stats(int update_every, usec_t dt) { NULL, "IPv4 ECN Statistics", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.tcp.stats", 8700, update_every, @@ -2144,7 +2161,7 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { NULL, "IPv4 UDP Packets", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.udp.stats", 2601, update_every, @@ -2177,7 +2194,7 @@ int do_net_inet_udp_stats(int update_every, usec_t dt) { NULL, "IPv4 UDP Errors", "events/s", - "freebsd", + "freebsd.plugin", "net.inet.udp.stats", 2701, update_every, @@ -2263,7 +2280,7 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { , NULL , "IPv4 ICMP Packets" , "packets/s" - , "freebsd" + , "freebsd.plugin" , "net.inet.icmp.stats" , 2602 , update_every @@ -2296,7 +2313,7 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { , NULL , "IPv4 ICMP Errors" , "packets/s" - , "freebsd" + , "freebsd.plugin" , "net.inet.icmp.stats" , 2603 , update_every @@ -2332,7 +2349,7 @@ int do_net_inet_icmp_stats(int update_every, usec_t dt) { , NULL , "IPv4 ICMP Messages" , "packets/s" - , "freebsd" + , "freebsd.plugin" , "net.inet.icmp.stats" , 2604 , update_every @@ -2410,7 +2427,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { NULL, "IPv4 Packets", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.ip.stats", 3000, update_every, @@ -2446,7 +2463,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { NULL, "IPv4 Fragments Sent", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.ip.stats", 3010, update_every, @@ -2482,7 +2499,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { NULL, "IPv4 Fragments Reassembly", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.ip.stats", 3011, update_every, @@ -2520,7 +2537,7 @@ int do_net_inet_ip_stats(int update_every, usec_t dt) { NULL, "IPv4 Errors", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet.ip.stats", 3002, update_every, @@ -2611,7 +2628,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { NULL, "IPv6 Packets", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet6.ip6.stats", 3000, update_every, @@ -2651,7 +2668,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { NULL, "IPv6 Fragments Sent", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet6.ip6.stats", 3010, update_every, @@ -2691,7 +2708,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { NULL, "IPv6 Fragments Reassembly", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet6.ip6.stats", 3011, update_every, @@ -2742,7 +2759,7 @@ int do_net_inet6_ip6_stats(int update_every, usec_t dt) { NULL, "IPv6 Errors", "packets/s", - "freebsd", + "freebsd.plugin", "net.inet6.ip6.stats", 3002, update_every, @@ -2856,7 +2873,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { NULL, "IPv6 ICMP Messages", "messages/s", - "freebsd", + "freebsd.plugin", "net.inet6.icmp6.stats", 10000, update_every, @@ -2891,7 +2908,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { NULL, "IPv6 ICMP Redirects", "redirects/s", - "freebsd", + "freebsd.plugin", "net.inet6.icmp6.stats", 10050, update_every, @@ -2938,7 +2955,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { NULL, "IPv6 ICMP Errors", "errors/s", - "freebsd", + "freebsd.plugin", "net.inet6.icmp6.stats", 10100, update_every, @@ -2993,7 +3010,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { NULL, "IPv6 ICMP Echo", "messages/s", - "freebsd", + "freebsd.plugin", "net.inet6.icmp6.stats", 10200, update_every, @@ -3036,7 +3053,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { NULL, "IPv6 Router Messages", "messages/s", - "freebsd", + "freebsd.plugin", "net.inet6.icmp6.stats", 10400, update_every, @@ -3079,7 +3096,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { NULL, "IPv6 Neighbor Messages", "messages/s", - "freebsd", + "freebsd.plugin", "net.inet6.icmp6.stats", 10500, update_every, @@ -3129,7 +3146,7 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) { NULL, "IPv6 ICMP Types", "messages/s", - "freebsd", + "freebsd.plugin", "net.inet6.icmp6.stats", 10700, update_every, diff --git a/src/plugin_freebsd.c b/collectors/freebsd.plugin/plugin_freebsd.c index a0d3dc2e..5cde3711 100644 --- a/src/plugin_freebsd.c +++ b/collectors/freebsd.plugin/plugin_freebsd.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_freebsd.h" static struct freebsd_module { const char *name; @@ -113,7 +115,7 @@ void *freebsd_main(void *ptr) { debug(D_PROCNETDEV_LOOP, "FREEBSD calling %s.", pm->name); pm->enabled = !pm->func(localhost->rrd_update_every, hb_dt); - pm->duration = heartbeat_dt_usec(&hb) - duration; + pm->duration = heartbeat_monotonic_dt_to_now_usec(&hb) - duration; duration += pm->duration; if(unlikely(netdata_exit)) break; diff --git a/src/freeipmi_plugin.c b/collectors/freeipmi.plugin/freeipmi_plugin.c index df4c019a..a1cff3af 100644 --- a/src/freeipmi_plugin.c +++ b/collectors/freeipmi.plugin/freeipmi_plugin.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0-or-later /* * netdata freeipmi.plugin * Copyright (C) 2017 Costa Tsaousis @@ -14,7 +15,7 @@ * UCRL-CODE-222073 */ -#include "common.h" +#include "../../libnetdata/libnetdata.h" #include <stdio.h> #include <stdlib.h> @@ -27,6 +28,32 @@ #ifdef HAVE_FREEIPMI +// ---------------------------------------------------------------------------- + +// callback required by fatal() +void netdata_cleanup_and_exit(int ret) { + exit(ret); +} + +// callbacks required by popen() +void signals_block(void) {}; +void signals_unblock(void) {}; +void signals_reset(void) {}; + +// callback required by eval() +int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) { + (void)variable; + (void)hash; + (void)rc; + (void)result; + return 0; +}; + +// required by get_system_cpus() +char *netdata_configured_host_prefix = ""; + +// ---------------------------------------------------------------------------- + #include <ipmi_monitoring.h> #include <ipmi_monitoring_bitmasks.h> @@ -46,8 +73,8 @@ char *driver_device = NULL; /* not used if probing */ int protocol_version = -1; //IPMI_MONITORING_PROTOCOL_VERSION_1_5; /* or -1 for default */ char *username = "foousername"; char *password = "foopassword"; -unsigned char *k_g = NULL; -unsigned int k_g_len = 0; +unsigned char *ipmi_k_g = NULL; +unsigned int ipmi_k_g_len = 0; int privilege_level = -1; // IPMI_MONITORING_PRIVILEGE_LEVEL_USER; /* or -1 for default */ int authentication_type = -1; // IPMI_MONITORING_AUTHENTICATION_TYPE_MD5; /* or -1 for default */ int cipher_suite_id = 0; /* or -1 for default */ @@ -123,8 +150,8 @@ _init_ipmi_config (struct ipmi_monitoring_ipmi_config *ipmi_config) ipmi_config->protocol_version = protocol_version; ipmi_config->username = username; ipmi_config->password = password; - ipmi_config->k_g = k_g; - ipmi_config->k_g_len = k_g_len; + ipmi_config->k_g = ipmi_k_g; + ipmi_config->k_g_len = ipmi_k_g_len; ipmi_config->privilege_level = privilege_level; ipmi_config->authentication_type = authentication_type; ipmi_config->cipher_suite_id = cipher_suite_id; @@ -557,6 +584,41 @@ static void excluded_record_ids_parse(const char *s) { } } +static int *excluded_status_record_ids = NULL; +size_t excluded_status_record_ids_length = 0; + +static void excluded_status_record_ids_parse(const char *s) { + if(!s) return; + + while(*s) { + while(*s && !isdigit(*s)) s++; + + if(isdigit(*s)) { + char *e; + unsigned long n = strtoul(s, &e, 10); + s = e; + + if(n != 0) { + excluded_status_record_ids = realloc(excluded_status_record_ids, (excluded_status_record_ids_length + 1) * sizeof(int)); + if(!excluded_status_record_ids) { + fprintf(stderr, "freeipmi.plugin: failed to allocate memory. Exiting."); + exit(1); + } + excluded_status_record_ids[excluded_status_record_ids_length++] = (int)n; + } + } + } + + if(debug) { + fprintf(stderr, "freeipmi.plugin: excluded status record ids:"); + size_t i; + for(i = 0; i < excluded_status_record_ids_length; i++) { + fprintf(stderr, " %d", excluded_status_record_ids[i]); + } + fprintf(stderr, "\n"); + } +} + static int excluded_record_ids_check(int record_id) { size_t i; @@ -569,6 +631,17 @@ static int excluded_record_ids_check(int record_id) { return 0; } +static int excluded_status_record_ids_check(int record_id) { + size_t i; + + for(i = 0; i < excluded_status_record_ids_length; i++) { + if(excluded_status_record_ids[i] == record_id) + return 1; + } + + return 0; +} + static void netdata_get_sensor( int record_id , int sensor_number @@ -641,6 +714,10 @@ static void netdata_get_sensor( break; } + // check if it is excluded + if(excluded_status_record_ids_check(record_id)) + return; + switch(sensor_state) { case IPMI_MONITORING_STATE_NOMINAL: netdata_sensors_states_nominal++; @@ -672,10 +749,6 @@ static void netdata_get_sel( } -void netdata_cleanup_and_exit(int ret) { - exit(ret); -} - // END NETDATA CODE // ---------------------------------------------------------------------------- @@ -1478,8 +1551,8 @@ int main (int argc, char **argv) { int i, freq = 0; for(i = 1; i < argc ; i++) { if(isdigit(*argv[i]) && !freq) { - int n = atoi(argv[i]); - if(n > 0 && freq < 86400) { + int n = str2i(argv[i]); + if(n > 0 && n < 86400) { freq = n; continue; } @@ -1536,6 +1609,9 @@ int main (int argc, char **argv) { " ignore N1,N2,N3,... sensor IDs to ignore\n" " default: none\n" "\n" + " ignore-status N1,N2,N3,... sensor IDs to ignore status (nominal/warning/critical)\n" + " default: none\n" + "\n" " -v\n" " -V\n" " version print version and exit\n" @@ -1548,7 +1624,7 @@ int main (int argc, char **argv) { " options ipmi_si kipmid_max_busy_us=10\n" "\n" " For more information:\n" - " https://github.com/firehol/netdata/wiki/monitoring-IPMI\n" + " https://github.com/ktsaou/netdata/tree/master/plugins/freeipmi.plugin\n" "\n" , VERSION , netdata_update_every @@ -1596,6 +1672,10 @@ int main (int argc, char **argv) { excluded_record_ids_parse(argv[++i]); continue; } + else if(i < argc && strcmp("ignore-status", argv[i]) == 0) { + excluded_status_record_ids_parse(argv[++i]); + continue; + } error("freeipmi.plugin: ignoring parameter '%s'", argv[i]); } diff --git a/src/plugin_idlejitter.c b/collectors/idlejitter.plugin/plugin_idlejitter.c index 77bd95d5..3fe3b030 100644 --- a/src/plugin_idlejitter.c +++ b/collectors/idlejitter.plugin/plugin_idlejitter.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_idlejitter.h" #define CPU_IDLEJITTER_SLEEP_TIME_MS 20 @@ -28,9 +30,9 @@ void *cpuidlejitter_main(void *ptr) { , NULL , "CPU Idle Jitter" , "microseconds lost/s" - , "idlejitter" + , "idlejitter.plugin" , NULL - , 800 + , NETDATA_CHART_PRIO_SYSTEM_IDLEJITTER , localhost->rrd_update_every , RRDSET_TYPE_AREA ); diff --git a/src/macos_fw.c b/collectors/macos.plugin/macos_fw.c index 5e8ce0ee..5d0ba929 100644 --- a/src/macos_fw.c +++ b/collectors/macos.plugin/macos_fw.c @@ -1,4 +1,7 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_macos.h" + #include <CoreFoundation/CoreFoundation.h> #include <IOKit/IOKitLib.h> #include <IOKit/storage/IOBlockStorageDriver.h> diff --git a/src/macos_mach_smi.c b/collectors/macos.plugin/macos_mach_smi.c index 47d32a9f..1c43d624 100644 --- a/src/macos_mach_smi.c +++ b/collectors/macos.plugin/macos_mach_smi.c @@ -1,4 +1,7 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_macos.h" + #include <mach/mach.h> int do_macos_mach_smi(int update_every, usec_t dt) { diff --git a/src/macos_sysctl.c b/collectors/macos.plugin/macos_sysctl.c index cb6fa8af..6b443c04 100644 --- a/src/macos_sysctl.c +++ b/collectors/macos.plugin/macos_sysctl.c @@ -1,6 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_macos.h" + #include <Availability.h> -#include <sys/sysctl.h> // NEEDED BY: do_bandwidth #include <net/route.h> // NEEDED BY do_tcp... @@ -1488,17 +1490,3 @@ int do_macos_sysctl(int update_every, usec_t dt) { return 0; } -int getsysctl_by_name(const char *name, void *ptr, size_t len) -{ - size_t nlen = len; - - if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) { - error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno)); - return 1; - } - if (unlikely(nlen != len)) { - error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); - return 1; - } - return 0; -} diff --git a/src/plugin_macos.c b/collectors/macos.plugin/plugin_macos.c index 6ac3d25d..628a5b10 100644 --- a/src/plugin_macos.c +++ b/collectors/macos.plugin/plugin_macos.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_macos.h" static void macos_main_cleanup(void *ptr) { struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; diff --git a/src/plugin_nfacct.c b/collectors/nfacct.plugin/plugin_nfacct.c index 02815ef0..7d42dd18 100644 --- a/src/plugin_nfacct.c +++ b/collectors/nfacct.plugin/plugin_nfacct.c @@ -1,6 +1,10 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later -#ifdef INTERNAL_PLUGIN_NFACCT +#include "plugin_nfacct.h" + +#if defined(INTERNAL_PLUGIN_NFACCT) + +#define PLUGIN_NFACCT_NAME "nfacct.plugin" #ifdef HAVE_LIBMNL #include <libmnl/libmnl.h> @@ -19,7 +23,7 @@ static inline size_t mnl_buffer_size() { #define DO_NFSTAT 1 #define RRD_TYPE_NET_STAT_NETFILTER "netfilter" -#define RRD_TYPE_NET_STAT_CONNTRACK "netlink" // FIXME: should be "conntrack" when merged with the /proc plugin +#define RRD_TYPE_NET_STAT_CONNTRACK "netlink" #include <linux/netfilter/nfnetlink_conntrack.h> @@ -302,9 +306,9 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker New Connections" , "connections/s" - , "nfacct" + , PLUGIN_NFACCT_NAME , NULL - , 3001 + , NETDATA_CHART_PRIO_NETFILTER_NEW , nfstat_root.update_every , RRDSET_TYPE_LINE ); @@ -338,9 +342,9 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Changes" , "changes/s" - , "nfacct" + , PLUGIN_NFACCT_NAME , NULL - , 3002 + , NETDATA_CHART_PRIO_NETFILTER_CHANGES , nfstat_root.update_every , RRDSET_TYPE_LINE ); @@ -375,9 +379,9 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Searches" , "searches/s" - , "nfacct" + , PLUGIN_NFACCT_NAME , NULL - , 3010 + , NETDATA_CHART_PRIO_NETFILTER_SEARCH , nfstat_root.update_every , RRDSET_TYPE_LINE ); @@ -412,9 +416,9 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Errors" , "events/s" - , "nfacct" + , PLUGIN_NFACCT_NAME , NULL - , 3005 + , NETDATA_CHART_PRIO_NETFILTER_ERRORS , nfstat_root.update_every , RRDSET_TYPE_LINE ); @@ -451,9 +455,9 @@ static void nfstat_send_metrics() { , NULL , "Connection Tracker Expectations" , "expectations/s" - , "nfacct" + , PLUGIN_NFACCT_NAME , NULL - , 3003 + , NETDATA_CHART_PRIO_NETFILTER_EXPECT , nfstat_root.update_every , RRDSET_TYPE_LINE ); @@ -590,7 +594,7 @@ static void nfacct_cleanup() { nfacct_root.buf = NULL; nfacct_root.buf_size = 0; - // FIXME: cleanup the metrics linked list + // TODO: cleanup the metrics linked list } static int nfacct_callback(const struct nlmsghdr *nlh, void *data) { @@ -671,9 +675,9 @@ static void nfacct_send_metrics() { , NULL , "Netfilter Accounting Packets" , "packets/s" - , "nfacct" + , PLUGIN_NFACCT_NAME , NULL - , 3206 + , NETDATA_CHART_PRIO_NETFILTER_PACKETS , nfacct_root.update_every , RRDSET_TYPE_STACKED ); @@ -714,9 +718,9 @@ static void nfacct_send_metrics() { , NULL , "Netfilter Accounting Bandwidth" , "kilobytes/s" - , "nfacct" + , PLUGIN_NFACCT_NAME , NULL - , 3207 + , NETDATA_CHART_PRIO_NETFILTER_BYTES , nfacct_root.update_every , RRDSET_TYPE_STACKED ); @@ -788,7 +792,6 @@ void *nfacct_main(void *ptr) { heartbeat_t hb; heartbeat_init(&hb); for(;;) { - heartbeat_dt_usec(&hb); heartbeat_next(&hb, step); if(unlikely(netdata_exit)) break; diff --git a/src/plugins_d.c b/collectors/plugins.d/plugins_d.c index 5693dda0..465ecd79 100644 --- a/src/plugins_d.c +++ b/collectors/plugins.d/plugins_d.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugins_d.h" char *plugin_directories[PLUGINSD_MAX_DIRECTORIES] = { NULL }; char *netdata_configured_plugins_dir_base; diff --git a/src/plugins_d.h b/collectors/plugins.d/plugins_d.h index 692d7cae..adccf3f0 100644 --- a/src/plugins_d.h +++ b/collectors/plugins.d/plugins_d.h @@ -1,6 +1,22 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_PLUGINS_D_H #define NETDATA_PLUGINS_D_H 1 +#include "../../daemon/common.h" + +#define NETDATA_PLUGIN_HOOK_PLUGINSD \ + { \ + .name = "PLUGINSD", \ + .config_section = NULL, \ + .config_name = NULL, \ + .enabled = 1, \ + .thread = NULL, \ + .init_routine = NULL, \ + .start_routine = pluginsd_main \ + }, + + #define PLUGINSD_FILE_SUFFIX ".plugin" #define PLUGINSD_FILE_SUFFIX_LEN strlen(PLUGINSD_FILE_SUFFIX) #define PLUGINSD_CMD_MAX (FILENAME_MAX*2) diff --git a/src/ipc.c b/collectors/proc.plugin/ipc.c index a9076fca..6c6bee51 100644 --- a/src/ipc.c +++ b/collectors/proc.plugin/ipc.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" #include <sys/sem.h> #include <sys/msg.h> @@ -166,7 +168,7 @@ int do_ipc(int update_every, usec_t dt) { static int initialized = 0, read_limits_next = -1; static struct ipc_limits limits; static struct ipc_status status; - static RRDSETVAR *arrays_max = NULL, *semaphores_max = NULL; + static RRDVAR *arrays_max = NULL, *semaphores_max = NULL; static RRDSET *st_semaphores = NULL, *st_arrays = NULL; static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL; @@ -195,9 +197,9 @@ int do_ipc(int update_every, usec_t dt) { , NULL , "IPC Semaphores" , "semaphores" - , "linux" + , PLUGIN_PROC_NAME , "ipc" - , 1000 + , NETDATA_CHART_PRIO_SYSTEM_IPC_SEMAPHORES , localhost->rrd_update_every , RRDSET_TYPE_AREA ); @@ -213,9 +215,9 @@ int do_ipc(int update_every, usec_t dt) { , NULL , "IPC Semaphore Arrays" , "arrays" - , "linux" + , PLUGIN_PROC_NAME , "ipc" - , 1000 + , NETDATA_CHART_PRIO_SYSTEM_IPC_SEM_ARRAYS , localhost->rrd_update_every , RRDSET_TYPE_AREA ); @@ -223,8 +225,8 @@ int do_ipc(int update_every, usec_t dt) { } // variables - semaphores_max = rrdsetvar_custom_chart_variable_create(st_semaphores, "ipc.semaphores.max"); - arrays_max = rrdsetvar_custom_chart_variable_create(st_arrays, "ipc.semaphores.arrays.max"); + semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_max"); + arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_arrays_max"); } if(unlikely(read_limits_next < 0)) { @@ -232,8 +234,8 @@ int do_ipc(int update_every, usec_t dt) { error("Unable to fetch semaphore limits."); } else { - if(semaphores_max) rrdsetvar_custom_chart_variable_set(semaphores_max, limits.semmns); - if(arrays_max) rrdsetvar_custom_chart_variable_set(arrays_max, limits.semmni); + if(semaphores_max) rrdvar_custom_host_variable_set(localhost, semaphores_max, limits.semmns); + if(arrays_max) rrdvar_custom_host_variable_set(localhost, arrays_max, limits.semmni); st_arrays->red = limits.semmni; st_semaphores->red = limits.semmns; diff --git a/src/plugin_proc.c b/collectors/proc.plugin/plugin_proc.c index e0afb0d6..0c3244d6 100644 --- a/src/plugin_proc.c +++ b/collectors/proc.plugin/plugin_proc.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" static struct proc_module { const char *name; @@ -37,6 +39,7 @@ static struct proc_module { { .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/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 }, @@ -91,8 +94,12 @@ void *proc_main(void *ptr) { usec_t step = localhost->rrd_update_every * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); + size_t iterations = 0; while(!netdata_exit) { + iterations++; + (void)iterations; + usec_t hb_dt = heartbeat_next(&hb, step); usec_t duration = 0ULL; @@ -106,10 +113,19 @@ void *proc_main(void *ptr) { debug(D_PROCNETDEV_LOOP, "PROC calling %s.", pm->name); +//#ifdef NETDATA_LOG_ALLOCATIONS +// if(pm->func == do_proc_interrupts) +// log_thread_memory_allocations = iterations; +//#endif pm->enabled = !pm->func(localhost->rrd_update_every, hb_dt); - pm->duration = heartbeat_dt_usec(&hb) - duration; + pm->duration = heartbeat_monotonic_dt_to_now_usec(&hb) - duration; duration += pm->duration; +//#ifdef NETDATA_LOG_ALLOCATIONS +// if(pm->func == do_proc_interrupts) +// log_thread_memory_allocations = 0; +//#endif + if(unlikely(netdata_exit)) break; } diff --git a/src/plugin_proc.h b/collectors/proc.plugin/plugin_proc.h index a7f9b4e3..bfefe1ad 100644 --- a/src/plugin_proc.h +++ b/collectors/proc.plugin/plugin_proc.h @@ -1,7 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_PLUGIN_PROC_H #define NETDATA_PLUGIN_PROC_H 1 -void *proc_main(void *ptr); +#include "../../daemon/common.h" + +#if (TARGET_OS == OS_LINUX) + +#define NETDATA_PLUGIN_HOOK_LINUX_PROC \ + { \ + .name = "PLUGIN[proc]", \ + .config_section = CONFIG_SECTION_PLUGINS, \ + .config_name = "proc", \ + .enabled = 1, \ + .thread = NULL, \ + .init_routine = NULL, \ + .start_routine = proc_main \ + }, + + +#define PLUGIN_PROC_CONFIG_NAME "proc" +#define PLUGIN_PROC_NAME PLUGIN_PROC_CONFIG_NAME ".plugin" + +extern void *proc_main(void *ptr); extern int do_proc_net_dev(int update_every, usec_t dt); extern int do_proc_diskstats(int update_every, usec_t dt); @@ -29,7 +50,8 @@ extern int do_proc_spl_kstat_zfs_arcstats(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 get_numa_node_count(void); // metrics that need to be shared among data collectors @@ -39,4 +61,14 @@ extern unsigned long long tcpext_TCPSynRetrans; extern void netdev_rename_device_add(const char *host_device, const char *container_device, const char *container_name); extern void netdev_rename_device_del(const char *host_device); +#include "proc_self_mountinfo.h" +#include "zfs_common.h" + +#else // (TARGET_OS == OS_LINUX) + +#define NETDATA_PLUGIN_HOOK_LINUX_PROC + +#endif // (TARGET_OS == OS_LINUX) + + #endif /* NETDATA_PLUGIN_PROC_H */ diff --git a/src/proc_diskstats.c b/collectors/proc.plugin/proc_diskstats.c index 8cde3334..387b395a 100644 --- a/src/proc_diskstats.c +++ b/collectors/proc.plugin/proc_diskstats.c @@ -1,13 +1,16 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" #define RRD_TYPE_DISK "disk" +#define PLUGIN_PROC_MODULE_DISKSTATS_NAME "/proc/diskstats" +#define CONFIG_SECTION_PLUGIN_PROC_DISKSTATS "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_DISKSTATS_NAME #define DISK_TYPE_UNKNOWN 0 #define DISK_TYPE_PHYSICAL 1 #define DISK_TYPE_PARTITION 2 #define DISK_TYPE_VIRTUAL 3 -#define CONFIG_SECTION_DISKSTATS "plugin:proc:/proc/diskstats" #define DEFAULT_EXCLUDED_DISKS "loop* ram*" static struct disk { @@ -48,6 +51,12 @@ static struct disk { char *bcache_filename_stats_total_cache_bypass_hits; char *bcache_filename_stats_total_cache_bypass_misses; char *bcache_filename_stats_total_cache_readaheads; + char *bcache_filename_cache_read_races; + char *bcache_filename_cache_io_errors; + char *bcache_filename_priority_stats; + + usec_t bcache_priority_stats_update_every_usec; + usec_t bcache_priority_stats_elapsed_usec; RRDSET *st_io; RRDDIM *rd_io_reads; @@ -111,6 +120,17 @@ static struct disk { RRDDIM *rd_bcache_readaheads; RRDDIM *rd_bcache_rate_writeback; + RRDSET *st_bcache_cache_allocations; + RRDDIM *rd_bcache_cache_allocations_unused; + RRDDIM *rd_bcache_cache_allocations_clean; + RRDDIM *rd_bcache_cache_allocations_dirty; + RRDDIM *rd_bcache_cache_allocations_metadata; + RRDDIM *rd_bcache_cache_allocations_unknown; + + RRDSET *st_bcache_cache_read_races; + RRDDIM *rd_bcache_cache_read_races; + RRDDIM *rd_bcache_cache_io_errors; + struct disk *next; } *disk_root = NULL; @@ -125,7 +145,9 @@ static char *path_to_sys_devices_virtual_block_device = NULL; static char *path_to_device_mapper = NULL; static char *path_to_device_label = NULL; static char *path_to_device_id = NULL; +static char *path_to_veritas_volume_groups = NULL; static int name_disks_by_id = CONFIG_BOOLEAN_NO; +static int global_bcache_priority_stats_update_every = 0; // disabled by default static int global_enable_new_disks_detected_at_runtime = CONFIG_BOOLEAN_YES, global_enable_performance_for_physical_disks = CONFIG_BOOLEAN_AUTO, @@ -170,6 +192,98 @@ static unsigned long long int bcache_read_number_with_units(const char *filename return 0; } +void bcache_read_priority_stats(struct disk *d, const char *family, int update_every, usec_t dt) { + static procfile *ff = NULL; + static char *separators = " \t:%[]"; + + static ARL_BASE *arl_base = NULL; + + static unsigned long long unused; + static unsigned long long clean; + static unsigned long long dirty; + static unsigned long long metadata; + static unsigned long long unknown; + + // check if it is time to update this metric + d->bcache_priority_stats_elapsed_usec += dt; + if(likely(d->bcache_priority_stats_elapsed_usec < d->bcache_priority_stats_update_every_usec)) return; + d->bcache_priority_stats_elapsed_usec = 0; + + // initialize ARL + if(unlikely(!arl_base)) { + arl_base = arl_create("bcache/priority_stats", NULL, 60); + arl_expect(arl_base, "Unused", &unused); + arl_expect(arl_base, "Clean", &clean); + arl_expect(arl_base, "Dirty", &dirty); + arl_expect(arl_base, "Metadata", &metadata); + } + + ff = procfile_reopen(ff, d->bcache_filename_priority_stats, separators, PROCFILE_FLAG_DEFAULT); + if(likely(ff)) ff = procfile_readall(ff); + if(unlikely(!ff)) { + separators = " \t:%[]"; + return; + } + + // do not reset the separators on every iteration + separators = NULL; + + arl_begin(arl_base); + unused = clean = dirty = metadata = unknown = 0; + + size_t lines = procfile_lines(ff), l; + + for(l = 0; l < lines ;l++) { + size_t words = procfile_linewords(ff, l); + if(unlikely(words < 2)) { + if(unlikely(words)) error("Cannot read '%s' line %zu. Expected 2 params, read %zu.", d->bcache_filename_priority_stats, l, words); + continue; + } + + if(unlikely(arl_check(arl_base, + procfile_lineword(ff, l, 0), + procfile_lineword(ff, l, 1)))) break; + } + + unknown = 100 - unused - clean - dirty - metadata; + + // create / update the cache allocations chart + { + if(unlikely(!d->st_bcache_cache_allocations)) { + d->st_bcache_cache_allocations = rrdset_create_localhost( + "disk_bcache_cache_alloc" + , d->device + , d->disk + , family + , "disk.bcache_cache_alloc" + , "BCache Cache Allocations" + , "percentage" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_CACHE_ALLOC + , update_every + , RRDSET_TYPE_STACKED + ); + + d->rd_bcache_cache_allocations_unused = rrddim_add(d->st_bcache_cache_allocations, "unused", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_bcache_cache_allocations_dirty = rrddim_add(d->st_bcache_cache_allocations, "dirty", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_bcache_cache_allocations_clean = rrddim_add(d->st_bcache_cache_allocations, "clean", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_bcache_cache_allocations_metadata = rrddim_add(d->st_bcache_cache_allocations, "metadata", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + d->rd_bcache_cache_allocations_unknown = rrddim_add(d->st_bcache_cache_allocations, "undefined", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + + 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); + rrddim_set_by_pointer(d->st_bcache_cache_allocations, d->rd_bcache_cache_allocations_clean, clean); + rrddim_set_by_pointer(d->st_bcache_cache_allocations, d->rd_bcache_cache_allocations_metadata, metadata); + rrddim_set_by_pointer(d->st_bcache_cache_allocations, d->rd_bcache_cache_allocations_unknown, unknown); + rrdset_done(d->st_bcache_cache_allocations); + } +} + static inline int is_major_enabled(int major) { static int8_t *major_configs = NULL; static size_t major_size = 0; @@ -191,67 +305,101 @@ static inline int is_major_enabled(int major) { if(major_configs[major] == -1) { char buffer[CONFIG_MAX_NAME + 1]; snprintfz(buffer, CONFIG_MAX_NAME, "performance metrics for disks with major %d", major); - major_configs[major] = (char)config_get_boolean(CONFIG_SECTION_DISKSTATS, buffer, 1); + major_configs[major] = (char)config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, buffer, 1); } return (int)major_configs[major]; } -static inline int get_disk_name_from_path(const char *path, char *result, size_t result_size, unsigned long major, unsigned long minor, char *disk) { - char filename[FILENAME_MAX + 1]; - int found = 0; +static inline int get_disk_name_from_path(const char *path, char *result, size_t result_size, unsigned long major, unsigned long minor, char *disk, char *prefix, int depth) { + //info("DEVICE-MAPPER ('%s', %lu:%lu): examining directory '%s' (allowed depth %d).", disk, major, minor, path, depth); - result_size--; + int found = 0; DIR *dir = opendir(path); if (!dir) { - error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot open directory '%s'. Disabling device-mapper support.", disk, major, minor, path); - goto cleanup; + error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot open directory '%s'.", disk, major, minor, path); + goto failed; } struct dirent *de = NULL; while ((de = readdir(dir))) { - if(de->d_type != DT_LNK) continue; + if(de->d_type == DT_DIR) { + if((de->d_name[0] == '.' && de->d_name[1] == '\0') || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) + continue; - snprintfz(filename, FILENAME_MAX, "%s/%s", path, de->d_name); - ssize_t len = readlink(filename, result, result_size); - if(len <= 0) { - error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot read link '%s'.", disk, major, minor, filename); - continue; - } + if(depth <= 0) { + error("DEVICE-MAPPER ('%s', %lu:%lu): Depth limit reached for path '%s/%s'. Ignoring path.", disk, major, minor, path, de->d_name); + break; + } + else { + char *path_nested = NULL; + char *prefix_nested = NULL; - result[len] = '\0'; - if(result[0] != '/') - snprintfz(filename, FILENAME_MAX, "%s/%s", path, result); - else - strncpyz(filename, result, FILENAME_MAX); + { + char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%s/%s", path, de->d_name); + path_nested = strdupz(buffer); - struct stat sb; - if(stat(filename, &sb) == -1) { - error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot stat() file '%s'.", disk, major, minor, filename); - continue; - } + snprintfz(buffer, FILENAME_MAX, "%s%s%s", (prefix)?prefix:"", (prefix)?"_":"", de->d_name); + prefix_nested = strdupz(buffer); + } - if((sb.st_mode & S_IFMT) != S_IFBLK) { - // info("DEVICE-MAPPER ('%s', %lu:%lu): file '%s' is not a block device.", disk, major, minor, filename); - continue; - } + found = get_disk_name_from_path(path_nested, result, result_size, major, minor, disk, prefix_nested, depth - 1); + freez(path_nested); + freez(prefix_nested); - if(major(sb.st_rdev) != major || minor(sb.st_rdev) != minor) { - // info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' does not match %lu:%lu.", disk, major, minor, filename, (unsigned long)major(sb.st_rdev), (unsigned long)minor(sb.st_rdev)); - continue; + if(found) break; + } } + else if(de->d_type == DT_LNK || de->d_type == DT_BLK) { + char filename[FILENAME_MAX + 1]; + + if(de->d_type == DT_LNK) { + snprintfz(filename, FILENAME_MAX, "%s/%s", path, de->d_name); + ssize_t len = readlink(filename, result, result_size - 1); + if(len <= 0) { + error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot read link '%s'.", disk, major, minor, filename); + continue; + } + + result[len] = '\0'; + if(result[0] != '/') + snprintfz(filename, FILENAME_MAX, "%s/%s", path, result); + else + strncpyz(filename, result, FILENAME_MAX); + } + else { + snprintfz(filename, FILENAME_MAX, "%s/%s", path, de->d_name); + } + + struct stat sb; + if(stat(filename, &sb) == -1) { + error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot stat() file '%s'.", disk, major, minor, filename); + continue; + } + + if((sb.st_mode & S_IFMT) != S_IFBLK) { + //info("DEVICE-MAPPER ('%s', %lu:%lu): file '%s' is not a block device.", disk, major, minor, filename); + continue; + } + + if(major(sb.st_rdev) != major || minor(sb.st_rdev) != minor) { + //info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' does not match %lu:%lu.", disk, major, minor, filename, (unsigned long)major(sb.st_rdev), (unsigned long)minor(sb.st_rdev)); + continue; + } - // info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' matches.", disk, major, minor, filename); + //info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' matches.", disk, major, minor, filename); - strncpy(result, de->d_name, result_size); - found = 1; - break; + snprintfz(result, result_size - 1, "%s%s%s", (prefix)?prefix:"", (prefix)?"_":"", de->d_name); + found = 1; + break; + } } closedir(dir); -cleanup: +failed: if(!found) result[0] = '\0'; @@ -262,10 +410,11 @@ cleanup: static inline char *get_disk_name(unsigned long major, unsigned long minor, char *disk) { char result[FILENAME_MAX + 1] = ""; - if(!path_to_device_mapper || !*path_to_device_mapper || !get_disk_name_from_path(path_to_device_mapper, result, FILENAME_MAX + 1, major, minor, disk)) - if(!path_to_device_label || !*path_to_device_label || !get_disk_name_from_path(path_to_device_label, result, FILENAME_MAX + 1, major, minor, disk)) - if(name_disks_by_id != CONFIG_BOOLEAN_YES || !path_to_device_id || !*path_to_device_id || !get_disk_name_from_path(path_to_device_id, result, FILENAME_MAX + 1, major, minor, disk)) - strncpy(result, disk, FILENAME_MAX); + if(!path_to_device_mapper || !*path_to_device_mapper || !get_disk_name_from_path(path_to_device_mapper, result, FILENAME_MAX + 1, major, minor, disk, NULL, 0)) + if(!path_to_device_label || !*path_to_device_label || !get_disk_name_from_path(path_to_device_label, result, FILENAME_MAX + 1, major, minor, disk, NULL, 0)) + if(!path_to_veritas_volume_groups || !*path_to_veritas_volume_groups || !get_disk_name_from_path(path_to_veritas_volume_groups, result, FILENAME_MAX + 1, major, minor, disk, "vx", 2)) + if(name_disks_by_id != CONFIG_BOOLEAN_YES || !path_to_device_id || !*path_to_device_id || !get_disk_name_from_path(path_to_device_id, result, FILENAME_MAX + 1, major, minor, disk, NULL, 0)) + strncpy(result, disk, FILENAME_MAX); if(!result[0]) strncpy(result, disk, FILENAME_MAX); @@ -281,7 +430,7 @@ static void get_disk_config(struct disk *d) { def_enable = CONFIG_BOOLEAN_NO; char var_name[4096 + 1]; - snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", d->disk); + snprintfz(var_name, 4096, CONFIG_SECTION_PLUGIN_PROC_DISKSTATS ":%s", d->disk); def_enable = config_get_boolean_ondemand(var_name, "enable", def_enable); if(unlikely(def_enable == CONFIG_BOOLEAN_NO)) { @@ -532,6 +681,24 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis else error("bcache file '%s' cannot be read.", buffer2); + snprintfz(buffer2, FILENAME_MAX, "%s/cache/cache0/priority_stats", buffer); // only one cache is supported by bcache + if(access(buffer2, R_OK) == 0) + d->bcache_filename_priority_stats = strdupz(buffer2); + else + error("bcache file '%s' cannot be read.", buffer2); + + snprintfz(buffer2, FILENAME_MAX, "%s/cache/internal/cache_read_races", buffer); + if(access(buffer2, R_OK) == 0) + d->bcache_filename_cache_read_races = strdupz(buffer2); + else + error("bcache file '%s' cannot be read.", buffer2); + + snprintfz(buffer2, FILENAME_MAX, "%s/cache/cache0/io_errors", buffer); + if(access(buffer2, R_OK) == 0) + d->bcache_filename_cache_io_errors = strdupz(buffer2); + else + error("bcache file '%s' cannot be read.", buffer2); + snprintfz(buffer2, FILENAME_MAX, "%s/dirty_data", buffer); if(access(buffer2, R_OK) == 0) d->bcache_filename_dirty_data = strdupz(buffer2); @@ -615,55 +782,59 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!globals_initialized)) { globals_initialized = 1; - global_enable_new_disks_detected_at_runtime = config_get_boolean(CONFIG_SECTION_DISKSTATS, "enable new disks detected at runtime", global_enable_new_disks_detected_at_runtime); - global_enable_performance_for_physical_disks = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for physical disks", global_enable_performance_for_physical_disks); - global_enable_performance_for_virtual_disks = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for virtual disks", global_enable_performance_for_virtual_disks); - global_enable_performance_for_partitions = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for partitions", global_enable_performance_for_partitions); - - global_do_io = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "bandwidth for all disks", global_do_io); - global_do_ops = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "operations for all disks", global_do_ops); - global_do_mops = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "merged operations for all disks", global_do_mops); - global_do_iotime = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "i/o time for all disks", global_do_iotime); - global_do_qops = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "queued operations for all disks", global_do_qops); - global_do_util = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "utilization percentage for all disks", global_do_util); - global_do_backlog = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "backlog for all disks", global_do_backlog); - global_do_bcache = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "bcache for all disks", global_do_bcache); - - global_cleanup_removed_disks = config_get_boolean(CONFIG_SECTION_DISKSTATS, "remove charts of removed disks" , global_cleanup_removed_disks); + global_enable_new_disks_detected_at_runtime = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "enable new disks detected at runtime", global_enable_new_disks_detected_at_runtime); + global_enable_performance_for_physical_disks = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "performance metrics for physical disks", global_enable_performance_for_physical_disks); + global_enable_performance_for_virtual_disks = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "performance metrics for virtual disks", global_enable_performance_for_virtual_disks); + global_enable_performance_for_partitions = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "performance metrics for partitions", global_enable_performance_for_partitions); + + global_do_io = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "bandwidth for all disks", global_do_io); + global_do_ops = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "operations for all disks", global_do_ops); + global_do_mops = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "merged operations for all disks", global_do_mops); + global_do_iotime = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "i/o time for all disks", global_do_iotime); + global_do_qops = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "queued operations for all disks", global_do_qops); + global_do_util = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "utilization percentage for all disks", global_do_util); + global_do_backlog = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "backlog for all disks", global_do_backlog); + global_do_bcache = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "bcache for all disks", global_do_bcache); + global_bcache_priority_stats_update_every = (int)config_get_number(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "bcache priority stats update every", global_bcache_priority_stats_update_every); + + global_cleanup_removed_disks = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "remove charts of removed disks" , global_cleanup_removed_disks); char buffer[FILENAME_MAX + 1]; snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s"); - path_to_sys_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device", buffer); + path_to_sys_block_device = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to get block device", buffer); snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/bcache"); - path_to_sys_block_device_bcache = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device bcache", buffer); + path_to_sys_block_device_bcache = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to get block device bcache", buffer); snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/block/%s"); - path_to_sys_devices_virtual_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get virtual block device", buffer); + path_to_sys_devices_virtual_block_device = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to get virtual block device", buffer); snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/%s"); - path_to_sys_dev_block_major_minor_string = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer); + path_to_sys_dev_block_major_minor_string = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to get block device infos", buffer); //snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size"); - //path_to_get_hw_sector_size = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer); + //path_to_get_hw_sector_size = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to get h/w sector size", buffer); //snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size"); - //path_to_get_hw_sector_size_partitions = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size for partitions", buffer); + //path_to_get_hw_sector_size_partitions = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to get h/w sector size for partitions", buffer); snprintfz(buffer, FILENAME_MAX, "%s/dev/mapper", netdata_configured_host_prefix); - path_to_device_mapper = config_get(CONFIG_SECTION_DISKSTATS, "path to device mapper", buffer); + path_to_device_mapper = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to device mapper", buffer); snprintfz(buffer, FILENAME_MAX, "%s/dev/disk/by-label", netdata_configured_host_prefix); - path_to_device_label = config_get(CONFIG_SECTION_DISKSTATS, "path to /dev/disk/by-label", buffer); + path_to_device_label = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to /dev/disk/by-label", buffer); snprintfz(buffer, FILENAME_MAX, "%s/dev/disk/by-id", netdata_configured_host_prefix); - path_to_device_id = config_get(CONFIG_SECTION_DISKSTATS, "path to /dev/disk/by-id", buffer); + path_to_device_id = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to /dev/disk/by-id", buffer); - name_disks_by_id = config_get_boolean(CONFIG_SECTION_DISKSTATS, "name disks by id", name_disks_by_id); + snprintfz(buffer, FILENAME_MAX, "%s/dev/vx/dsk", netdata_configured_host_prefix); + path_to_veritas_volume_groups = config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "path to /dev/vx/dsk", buffer); + + name_disks_by_id = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "name disks by id", name_disks_by_id); excluded_disks = simple_pattern_create( - config_get(CONFIG_SECTION_DISKSTATS, "exclude disks", DEFAULT_EXCLUDED_DISKS) + config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "exclude disks", DEFAULT_EXCLUDED_DISKS) , NULL , SIMPLE_PATTERN_EXACT ); @@ -674,7 +845,7 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/diskstats"); - ff = procfile_open(config_get(CONFIG_SECTION_DISKSTATS, "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_DISKSTATS, "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); } if(unlikely(!ff)) return 0; @@ -790,9 +961,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.io" , "Disk I/O Bandwidth" , "kilobytes/s" - , "proc" - , "diskstats" - , 2000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_IO , update_every , RRDSET_TYPE_AREA ); @@ -821,9 +992,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.ops" , "Disk Completed I/O Operations" , "operations/s" - , "proc" - , "diskstats" - , 2001 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_OPS , update_every , RRDSET_TYPE_LINE ); @@ -854,9 +1025,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.qops" , "Disk Current I/O Operations" , "operations" - , "proc" - , "diskstats" - , 2002 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_QOPS , update_every , RRDSET_TYPE_LINE ); @@ -885,9 +1056,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.backlog" , "Disk Backlog" , "backlog (ms)" - , "proc" - , "diskstats" - , 2003 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_BACKLOG , update_every , RRDSET_TYPE_AREA ); @@ -916,9 +1087,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.util" , "Disk Utilization Time" , "% of time working" - , "proc" - , "diskstats" - , 2004 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_UTIL , update_every , RRDSET_TYPE_AREA ); @@ -947,9 +1118,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.mops" , "Disk Merged Operations" , "merged operations/s" - , "proc" - , "diskstats" - , 2021 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_MOPS , update_every , RRDSET_TYPE_LINE ); @@ -980,9 +1151,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.iotime" , "Disk Total I/O Time" , "milliseconds/s" - , "proc" - , "diskstats" - , 2022 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_IOTIME , update_every , RRDSET_TYPE_LINE ); @@ -1016,9 +1187,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.await" , "Average Completed I/O Operation Time" , "ms per operation" - , "proc" - , "diskstats" - , 2005 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_AWAIT , update_every , RRDSET_TYPE_LINE ); @@ -1047,9 +1218,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.avgsz" , "Average Completed I/O Operation Bandwidth" , "kilobytes per operation" - , "proc" - , "diskstats" - , 2006 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_AVGSZ , update_every , RRDSET_TYPE_AREA ); @@ -1078,9 +1249,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.svctm" , "Average Service Time" , "ms per operation" - , "proc" - , "diskstats" - , 2007 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_DISK_SVCTM , update_every , RRDSET_TYPE_LINE ); @@ -1112,6 +1283,8 @@ int do_proc_diskstats(int update_every, usec_t dt) { stats_total_cache_hit_ratio = 0, cache_available_percent = 0, cache_readaheads = 0, + cache_read_races = 0, + cache_io_errors = 0, cache_congested = 0, dirty_data = 0, writeback_rate = 0; @@ -1160,11 +1333,18 @@ int do_proc_diskstats(int update_every, usec_t dt) { if(d->bcache_filename_stats_total_cache_readaheads) cache_readaheads = bcache_read_number_with_units(d->bcache_filename_stats_total_cache_readaheads); + if(d->bcache_filename_cache_read_races) + read_single_number_file(d->bcache_filename_cache_read_races, &cache_read_races); + + if(d->bcache_filename_cache_io_errors) + read_single_number_file(d->bcache_filename_cache_io_errors, &cache_io_errors); + + if(d->bcache_filename_priority_stats && global_bcache_priority_stats_update_every >= 1) + bcache_read_priority_stats(d, family, global_bcache_priority_stats_update_every, dt); // update the charts { - if(unlikely(!d->st_bcache_hit_ratio)) { d->st_bcache_hit_ratio = rrdset_create_localhost( "disk_bcache_hit_ratio" @@ -1174,9 +1354,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.bcache_hit_ratio" , "BCache Cache Hit Ratio" , "percentage" - , "proc" - , "diskstats" - , 2120 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_HIT_RATIO , update_every , RRDSET_TYPE_LINE ); @@ -1206,9 +1386,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.bcache_rates" , "BCache Rates" , "KB/s" - , "proc" - , "diskstats" - , 2121 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_RATES , update_every , RRDSET_TYPE_AREA ); @@ -1233,9 +1413,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.bcache_size" , "BCache Cache Sizes" , "MB" - , "proc" - , "diskstats" - , 2122 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_SIZE , update_every , RRDSET_TYPE_AREA ); @@ -1258,9 +1438,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.bcache_usage" , "BCache Cache Usage" , "percent" - , "proc" - , "diskstats" - , 2123 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_USAGE , update_every , RRDSET_TYPE_AREA ); @@ -1273,6 +1453,34 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_done(d->st_bcache_usage); } + { + + 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->disk + , family + , "disk.bcache_cache_read_races" + , "BCache Cache Read Races" + , "operations/s" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_CACHE_READ_RACES + , update_every + , RRDSET_TYPE_LINE + ); + + d->rd_bcache_cache_read_races = rrddim_add(d->st_bcache_cache_read_races, "races", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_bcache_cache_io_errors = rrddim_add(d->st_bcache_cache_read_races, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + 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); + rrdset_done(d->st_bcache_cache_read_races); + } + if(d->do_bcache == CONFIG_BOOLEAN_YES || (d->do_bcache == CONFIG_BOOLEAN_AUTO && (stats_total_cache_hits != 0 || stats_total_cache_misses != 0 || stats_total_cache_miss_collisions != 0))) { if(unlikely(!d->st_bcache)) { @@ -1284,9 +1492,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.bcache" , "BCache Cache I/O Operations" , "operations/s" - , "proc" - , "diskstats" - , 2124 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_OPS , update_every , RRDSET_TYPE_LINE ); @@ -1318,9 +1526,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , "disk.bcache_bypass" , "BCache Cache Bypass I/O Operations" , "operations/s" - , "proc" - , "diskstats" - , 2125 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_BCACHE_BYPASS , update_every , RRDSET_TYPE_LINE ); @@ -1356,9 +1564,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { , NULL , "Disk I/O" , "kilobytes/s" - , "proc" - , "diskstats" - , 150 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_DISKSTATS_NAME + , NETDATA_CHART_PRIO_SYSTEM_IO , update_every , RRDSET_TYPE_AREA ); @@ -1421,6 +1629,9 @@ int do_proc_diskstats(int update_every, usec_t dt) { freez(t->bcache_filename_stats_total_cache_bypass_hits); freez(t->bcache_filename_stats_total_cache_bypass_misses); freez(t->bcache_filename_stats_total_cache_readaheads); + freez(t->bcache_filename_cache_read_races); + freez(t->bcache_filename_cache_io_errors); + freez(t->bcache_filename_priority_stats); freez(t->disk); freez(t->device); diff --git a/src/proc_interrupts.c b/collectors/proc.plugin/proc_interrupts.c index 867f39eb..73b11717 100644 --- a/src/proc_interrupts.c +++ b/collectors/proc.plugin/proc_interrupts.c @@ -1,4 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_INTERRUPTS_NAME "/proc/interrupts" +#define CONFIG_SECTION_PLUGIN_PROC_INTERRUPTS "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_INTERRUPTS_NAME #define MAX_INTERRUPT_NAME 50 @@ -51,16 +56,16 @@ static inline struct interrupt *get_interrupts_array(size_t lines, int cpus) { int do_proc_interrupts(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; - static int cpus = -1, do_per_core = -1; + static int cpus = -1, do_per_core = CONFIG_BOOLEAN_INVALID; struct interrupt *irrs = NULL; - if(unlikely(do_per_core == -1)) - do_per_core = config_get_boolean("plugin:proc:/proc/interrupts", "interrupts per core", 1); + if(unlikely(do_per_core == CONFIG_BOOLEAN_INVALID)) + do_per_core = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_INTERRUPTS, "interrupts per core", CONFIG_BOOLEAN_AUTO); if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/interrupts"); - ff = procfile_open(config_get("plugin:proc:/proc/interrupts", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_INTERRUPTS, "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); } if(unlikely(!ff)) return 1; @@ -109,8 +114,8 @@ int do_proc_interrupts(int update_every, usec_t dt) { if(unlikely(!irr->id || !irr->id[0])) continue; size_t idlen = strlen(irr->id); - if(unlikely(idlen && irr->id[idlen - 1] == ':')) - irr->id[idlen - 1] = '\0'; + if(irr->id[idlen - 1] == ':') + irr->id[--idlen] = '\0'; int c; for(c = 0; c < cpus ;c++) { @@ -125,7 +130,6 @@ int do_proc_interrupts(int update_every, usec_t dt) { if(unlikely(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words)) { strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME); size_t nlen = strlen(irr->name); - idlen = strlen(irr->id); if(likely(nlen + 1 + idlen <= MAX_INTERRUPT_NAME)) { irr->name[nlen] = '_'; strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen - 1); @@ -154,9 +158,9 @@ int do_proc_interrupts(int update_every, usec_t dt) { , NULL , "System interrupts" , "interrupts/s" - , "proc" - , "interrupts" - , 1000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_INTERRUPTS_NAME + , NETDATA_CHART_PRIO_SYSTEM_INTERRUPTS , update_every , RRDSET_TYPE_STACKED ); @@ -165,34 +169,30 @@ int do_proc_interrupts(int update_every, usec_t dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(unlikely(!irr->used)) continue; - - // 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)) { - irr->rd = rrddim_find(st_system_interrupts, irr->id); - - if(unlikely(!irr->rd)) + if(irr->used && irr->total) { + // 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)) { irr->rd = rrddim_add(st_system_interrupts, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - else rrddim_set_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)) { - int c; - for (c = 0; c < cpus ;c++) irr->cpu[c].rd = NULL; + // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop + if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { + int c; + for(c = 0; c < cpus; c++) irr->cpu[c].rd = NULL; + } } - } - rrddim_set_by_pointer(st_system_interrupts, irr->rd, irr->total); + rrddim_set_by_pointer(st_system_interrupts, irr->rd, irr->total); + } } rrdset_done(st_system_interrupts); // -------------------------------------------------------------------- - if(likely(do_per_core)) { + if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { static RRDSET **core_st = NULL; static int old_cpus = 0; @@ -219,9 +219,9 @@ int do_proc_interrupts(int update_every, usec_t dt) { , "cpu.interrupts" , title , "interrupts/s" - , "proc" - , "interrupts" - , 1100 + c + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_INTERRUPTS_NAME + , NETDATA_CHART_PRIO_INTERRUPTS_PER_CORE + c , update_every , RRDSET_TYPE_STACKED ); @@ -230,19 +230,14 @@ int do_proc_interrupts(int update_every, usec_t dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - - if(unlikely(!irr->used)) continue; - - if(unlikely(!irr->cpu[c].rd)) { - irr->cpu[c].rd = rrddim_find(core_st[c], irr->id); - - if(unlikely(!irr->cpu[c].rd)) + 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); - else rrddim_set_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); + rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value); + } } rrdset_done(core_st[c]); diff --git a/src/proc_loadavg.c b/collectors/proc.plugin/proc_loadavg.c index 868f7d50..db95b168 100644 --- a/src/proc_loadavg.c +++ b/collectors/proc.plugin/proc_loadavg.c @@ -1,4 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_LOADAVG_NAME "/proc/loadavg" +#define CONFIG_SECTION_PLUGIN_PROC_LOADAVG "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_LOADAVG_NAME // linux calculates this once every 5 seconds #define MIN_LOADAVG_UPDATE_EVERY 5 @@ -12,7 +17,7 @@ int do_proc_loadavg(int update_every, usec_t dt) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/loadavg"); - ff = procfile_open(config_get("plugin:proc:/proc/loadavg", "filename to monitor", filename), " \t,:|/", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_LOADAVG, "filename to monitor", filename), " \t,:|/", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } @@ -22,8 +27,8 @@ int do_proc_loadavg(int update_every, usec_t dt) { return 0; // we return 0, so that we will retry to open it next time if(unlikely(do_loadavg == -1)) { - do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1); - do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1); + do_loadavg = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_LOADAVG, "enable load average", 1); + do_all_processes = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_LOADAVG, "enable total processes", 1); } if(unlikely(procfile_lines(ff) < 1)) { @@ -60,9 +65,9 @@ int do_proc_loadavg(int update_every, usec_t dt) { , NULL , "System Load Average" , "load" - , "proc" - , "loadavg" - , 100 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_LOADAVG_NAME + , NETDATA_CHART_PRIO_SYSTEM_LOAD , (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every , RRDSET_TYPE_LINE ); @@ -100,9 +105,9 @@ int do_proc_loadavg(int update_every, usec_t dt) { , NULL , "System Active Processes" , "processes" - , "proc" - , "loadavg" - , 750 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_LOADAVG_NAME + , NETDATA_CHART_PRIO_SYSTEM_ACTIVE_PROCESSES , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_meminfo.c b/collectors/proc.plugin/proc_meminfo.c index 3915bf0e..f77159eb 100644 --- a/src/proc_meminfo.c +++ b/collectors/proc.plugin/proc_meminfo.c @@ -1,4 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_MEMINFO_NAME "/proc/meminfo" +#define CONFIG_SECTION_PLUGIN_PROC_MEMINFO "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_MEMINFO_NAME int do_proc_meminfo(int update_every, usec_t dt) { (void)dt; @@ -56,15 +61,15 @@ int do_proc_meminfo(int update_every, usec_t dt) { HardwareCorrupted = 0; if(unlikely(!arl_base)) { - do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1); - do_swap = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "system swap", CONFIG_BOOLEAN_AUTO); - do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_BOOLEAN_AUTO); - do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1); - do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1); - do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1); - do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1); - do_hugepages = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hugepages", CONFIG_BOOLEAN_AUTO); - do_transparent_hugepages = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "transparent hugepages", CONFIG_BOOLEAN_AUTO); + do_ram = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "system ram", 1); + do_swap = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "system swap", CONFIG_BOOLEAN_AUTO); + do_hwcorrupt = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "hardware corrupted ECC", CONFIG_BOOLEAN_AUTO); + do_committed = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "committed memory", 1); + do_writeback = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "writeback memory", 1); + do_kernel = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "kernel memory", 1); + do_slab = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "slab memory", 1); + do_hugepages = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "hugepages", CONFIG_BOOLEAN_AUTO); + do_transparent_hugepages = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "transparent hugepages", CONFIG_BOOLEAN_AUTO); arl_base = arl_create("meminfo", NULL, 60); arl_expect(arl_base, "MemTotal", &MemTotal); @@ -116,7 +121,7 @@ int do_proc_meminfo(int update_every, usec_t dt) { if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/meminfo"); - ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } @@ -158,9 +163,9 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "System RAM" , "MB" - , "proc" - , "meminfo" - , 200 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME + , NETDATA_CHART_PRIO_SYSTEM_RAM , update_every , RRDSET_TYPE_STACKED ); @@ -193,8 +198,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Available RAM for applications" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_SYSTEM_AVAILABLE , update_every , RRDSET_TYPE_AREA @@ -229,9 +234,9 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "System Swap" , "MB" - , "proc" - , "meminfo" - , 201 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME + , NETDATA_CHART_PRIO_SYSTEM_SWAP , update_every , RRDSET_TYPE_STACKED ); @@ -266,8 +271,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Corrupted Memory, detected by ECC" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_HW , update_every , RRDSET_TYPE_LINE @@ -299,8 +304,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Committed (Allocated) Memory" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED , update_every , RRDSET_TYPE_AREA @@ -332,8 +337,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Writeback Memory" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_KERNEL , update_every , RRDSET_TYPE_LINE @@ -372,8 +377,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Memory Used by Kernel" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_KERNEL + 1 , update_every , RRDSET_TYPE_STACKED @@ -411,8 +416,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Reclaimable Kernel Memory" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_SLAB , update_every , RRDSET_TYPE_STACKED @@ -448,8 +453,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Dedicated HugePages Memory" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_HUGEPAGES + 1 , update_every , RRDSET_TYPE_STACKED @@ -489,8 +494,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { , NULL , "Transparent HugePages Memory" , "MB" - , "proc" - , "meminfo" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_MEMINFO_NAME , NETDATA_CHART_PRIO_MEM_HUGEPAGES , update_every , RRDSET_TYPE_STACKED diff --git a/src/proc_net_dev.c b/collectors/proc.plugin/proc_net_dev.c index 341b9e0c..97cbc060 100644 --- a/src/proc_net_dev.c +++ b/collectors/proc.plugin/proc_net_dev.c @@ -1,4 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_NETDEV_NAME "/proc/net/dev" +#define CONFIG_SECTION_PLUGIN_PROC_NETDEV "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NETDEV_NAME // ---------------------------------------------------------------------------- // netdev list @@ -61,6 +66,7 @@ static struct netdev { kernel_uint_t tcollisions; kernel_uint_t tcarrier; kernel_uint_t tcompressed; + kernel_uint_t speed_max; // charts RRDSET *st_bandwidth; @@ -296,7 +302,7 @@ static inline void netdev_rename_cgroup(struct netdev *d, struct netdev_rename * snprintfz(buffer, RRD_ID_LENGTH_MAX, "net %s", r->container_device); d->chart_family = strdupz(buffer); - d->priority = 43000; + d->priority = NETDATA_CHART_PRIO_CGROUP_NET_IFACE; d->flipped = 1; } @@ -405,7 +411,7 @@ static struct netdev *get_netdev(const char *name) { d->chart_id_net_packets = strdupz(d->name); d->chart_family = strdupz(d->name); - d->priority = 7000; + d->priority = NETDATA_CHART_PRIO_FIRST_NET_IFACE; netdev_rename_lock(d); @@ -430,30 +436,31 @@ int do_proc_net_dev(int update_every, usec_t dt) { static int enable_new_interfaces = -1; static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1; static char *path_to_sys_devices_virtual_net = NULL; + static char *path_to_sys_net_speed = NULL; if(unlikely(enable_new_interfaces == -1)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/net/%s"); - path_to_sys_devices_virtual_net = config_get("plugin:proc:/proc/net/dev", "path to get virtual interfaces", filename); + path_to_sys_devices_virtual_net = config_get(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "path to get virtual interfaces", filename); - enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_BOOLEAN_AUTO); + enable_new_interfaces = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "enable new interfaces detected at runtime", CONFIG_BOOLEAN_AUTO); - do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_BOOLEAN_AUTO); - do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_BOOLEAN_AUTO); - do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_BOOLEAN_AUTO); - do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_BOOLEAN_AUTO); - do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_BOOLEAN_AUTO); - do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_BOOLEAN_AUTO); - do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_BOOLEAN_AUTO); + do_bandwidth = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "bandwidth for all interfaces", CONFIG_BOOLEAN_AUTO); + do_packets = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "packets for all interfaces", CONFIG_BOOLEAN_AUTO); + do_errors = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "errors for all interfaces", CONFIG_BOOLEAN_AUTO); + do_drops = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "drops for all interfaces", CONFIG_BOOLEAN_AUTO); + do_fifo = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "fifo for all interfaces", CONFIG_BOOLEAN_AUTO); + do_compressed = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "compressed packets for all interfaces", CONFIG_BOOLEAN_AUTO); + do_events = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "frames, collisions, carrier counters for all interfaces", CONFIG_BOOLEAN_AUTO); - disabled_list = simple_pattern_create(config_get("plugin:proc:/proc/net/dev", "disable by default interfaces matching", "lo fireqos* *-ifb"), NULL, SIMPLE_PATTERN_EXACT); + disabled_list = simple_pattern_create(config_get(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "disable by default interfaces matching", "lo fireqos* *-ifb"), NULL, SIMPLE_PATTERN_EXACT); } if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/dev"); - ff = procfile_open(config_get("plugin:proc:/proc/net/dev", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT); + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, (*netdata_configured_host_prefix)?"/proc/1/net/dev":"/proc/net/dev"); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } @@ -498,6 +505,14 @@ int do_proc_net_dev(int update_every, usec_t dt) { else d->virtual = 0; + // set nic speed if present + if(likely(!d->virtual)) { + snprintfz(buffer, FILENAME_MAX, "%s/sys/class/net/%s/speed", netdata_configured_host_prefix, d->name); + path_to_sys_net_speed = config_get(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "path to get net device speed", buffer); + int ret = read_single_number_file(path_to_sys_net_speed, (unsigned long long*)&d->speed_max); + if(ret) error("Cannot read '%s'.", path_to_sys_net_speed); + } + snprintfz(buffer, FILENAME_MAX, "plugin:proc:/proc/net/dev:%s", d->name); d->enabled = config_get_boolean_ondemand(buffer, "enabled", d->enabled); d->virtual = config_get_boolean(buffer, "virtual", d->virtual); @@ -575,13 +590,16 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.net" , "Bandwidth" , "kilobits/s" - , "proc" - , "net/dev" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME , d->priority , update_every , RRDSET_TYPE_AREA ); + RRDSETVAR *nic_speed_max = rrdsetvar_custom_chart_variable_create(d->st_bandwidth, "nic_speed_max"); + if(nic_speed_max) rrdsetvar_custom_chart_variable_set(nic_speed_max, (calculated_number)d->speed_max); + d->rd_rbytes = rrddim_add(d->st_bandwidth, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); d->rd_tbytes = rrddim_add(d->st_bandwidth, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); @@ -616,8 +634,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.packets" , "Packets" , "packets/s" - , "proc" - , "net/dev" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME , d->priority + 1 , update_every , RRDSET_TYPE_LINE @@ -661,8 +679,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.errors" , "Interface Errors" , "errors/s" - , "proc" - , "net/dev" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME , d->priority + 2 , update_every , RRDSET_TYPE_LINE @@ -704,8 +722,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.drops" , "Interface Drops" , "drops/s" - , "proc" - , "net/dev" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME , d->priority + 3 , update_every , RRDSET_TYPE_LINE @@ -747,8 +765,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.fifo" , "Interface FIFO Buffer Errors" , "errors" - , "proc" - , "net/dev" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME , d->priority + 4 , update_every , RRDSET_TYPE_LINE @@ -790,8 +808,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.compressed" , "Compressed Packets" , "packets/s" - , "proc" - , "net/dev" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME , d->priority + 5 , update_every , RRDSET_TYPE_LINE @@ -833,8 +851,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { , "net.events" , "Network Interface Events" , "events/s" - , "proc" - , "net/dev" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME , d->priority + 6 , update_every , RRDSET_TYPE_LINE @@ -869,9 +887,9 @@ int do_proc_net_dev(int update_every, usec_t dt) { , NULL , "Physical Network Interfaces Aggregated Bandwidth" , "kilobits/s" - , "proc" - , "net/dev" - , 500 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETDEV_NAME + , NETDATA_CHART_PRIO_SYSTEM_NET , update_every , RRDSET_TYPE_AREA ); diff --git a/src/proc_net_ip_vs_stats.c b/collectors/proc.plugin/proc_net_ip_vs_stats.c index d76972f3..43dcf2a8 100644 --- a/src/proc_net_ip_vs_stats.c +++ b/collectors/proc.plugin/proc_net_ip_vs_stats.c @@ -1,20 +1,24 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later -#define RRD_TYPE_NET_IPVS "ipvs" +#include "plugin_proc.h" + +#define RRD_TYPE_NET_IPVS "ipvs" +#define PLUGIN_PROC_MODULE_NET_IPVS_NAME "/proc/net/ip_vs_stats" +#define CONFIG_SECTION_PLUGIN_PROC_NET_IPVS "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NET_IPVS_NAME int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { (void)dt; static int do_bandwidth = -1, do_sockets = -1, do_packets = -1; static procfile *ff = NULL; - if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS bandwidth", 1); - if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS connections", 1); - if(do_packets == -1) do_packets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS packets", 1); + if(do_bandwidth == -1) do_bandwidth = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NET_IPVS, "IPVS bandwidth", 1); + if(do_sockets == -1) do_sockets = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NET_IPVS, "IPVS connections", 1); + if(do_packets == -1) do_packets = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NET_IPVS, "IPVS packets", 1); if(!ff) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/ip_vs_stats"); - ff = procfile_open(config_get("plugin:proc:/proc/net/ip_vs_stats", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_NET_IPVS, "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT); } if(!ff) return 1; @@ -50,9 +54,9 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { , NULL , "IPVS New Connections" , "connections/s" - , "proc" - , "net/ip_vs_stats" - , 3101 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_IPVS_NAME + , NETDATA_CHART_PRIO_IPVS_SOCKETS , update_every , RRDSET_TYPE_LINE ); @@ -78,9 +82,9 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { , NULL , "IPVS Packets" , "packets/s" - , "proc" - , "net/ip_vs_stats" - , 3102 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_IPVS_NAME + , NETDATA_CHART_PRIO_IPVS_PACKETS , update_every , RRDSET_TYPE_LINE ); @@ -108,9 +112,9 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { , NULL , "IPVS Bandwidth" , "kilobits/s" - , "proc" - , "net/ip_vs_stats" - , 3100 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_IPVS_NAME + , NETDATA_CHART_PRIO_IPVS_NET , update_every , RRDSET_TYPE_AREA ); diff --git a/src/proc_net_netstat.c b/collectors/proc.plugin/proc_net_netstat.c index dd070e4c..2dc3c59c 100644 --- a/src/proc_net_netstat.c +++ b/collectors/proc.plugin/proc_net_netstat.c @@ -1,6 +1,12 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later -unsigned long long tcpext_TCPSynRetrans; +#include "plugin_proc.h" + +#define RRD_TYPE_NET_NETSTAT "ip" +#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); @@ -23,7 +29,7 @@ int do_proc_net_netstat(int update_every, usec_t dt) { static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \ do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1, - do_tcpext_listen = -1; + do_tcpext_syn_queue = -1, do_tcpext_accept_queue = -1; static uint32_t hash_ipext = 0, hash_tcpext = 0; static procfile *ff = NULL; @@ -32,61 +38,61 @@ int do_proc_net_netstat(int update_every, usec_t dt) { static ARL_BASE *arl_ipext = NULL; // -------------------------------------------------------------------- - // IPv4 + // IP - // IPv4 bandwidth + // IP bandwidth static unsigned long long ipext_InOctets = 0; static unsigned long long ipext_OutOctets = 0; - // IPv4 input errors + // IP input errors static unsigned long long ipext_InNoRoutes = 0; static unsigned long long ipext_InTruncatedPkts = 0; static unsigned long long ipext_InCsumErrors = 0; - // IPv4 multicast bandwidth + // IP multicast bandwidth static unsigned long long ipext_InMcastOctets = 0; static unsigned long long ipext_OutMcastOctets = 0; - // IPv4 multicast packets + // IP multicast packets static unsigned long long ipext_InMcastPkts = 0; static unsigned long long ipext_OutMcastPkts = 0; - // IPv4 broadcast bandwidth + // IP broadcast bandwidth static unsigned long long ipext_InBcastOctets = 0; static unsigned long long ipext_OutBcastOctets = 0; - // IPv4 broadcast packets + // IP broadcast packets static unsigned long long ipext_InBcastPkts = 0; static unsigned long long ipext_OutBcastPkts = 0; - // IPv4 ECN + // IP ECN static unsigned long long ipext_InNoECTPkts = 0; static unsigned long long ipext_InECT1Pkts = 0; static unsigned long long ipext_InECT0Pkts = 0; static unsigned long long ipext_InCEPkts = 0; // -------------------------------------------------------------------- - // IPv4 TCP + // IP TCP - // IPv4 TCP Reordering + // IP TCP Reordering static unsigned long long tcpext_TCPRenoReorder = 0; static unsigned long long tcpext_TCPFACKReorder = 0; static unsigned long long tcpext_TCPSACKReorder = 0; static unsigned long long tcpext_TCPTSReorder = 0; - // IPv4 TCP SYN Cookies + // IP TCP SYN Cookies static unsigned long long tcpext_SyncookiesSent = 0; static unsigned long long tcpext_SyncookiesRecv = 0; static unsigned long long tcpext_SyncookiesFailed = 0; - // IPv4 TCP Out Of Order Queue + // IP TCP Out Of Order Queue // http://www.spinics.net/lists/netdev/msg204696.html static unsigned long long tcpext_TCPOFOQueue = 0; // Number of packets queued in OFO queue static unsigned long long tcpext_TCPOFODrop = 0; // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit. static unsigned long long tcpext_TCPOFOMerge = 0; // Number of packets in OFO that were merged with other packets. static unsigned long long tcpext_OfoPruned = 0; // packets dropped from out-of-order queue because of socket buffer overrun - // IPv4 TCP connection resets + // IP TCP connection resets // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c static unsigned long long tcpext_TCPAbortOnData = 0; // connections reset due to unexpected data static unsigned long long tcpext_TCPAbortOnClose = 0; // connections reset due to early user close @@ -99,9 +105,12 @@ int do_proc_net_netstat(int update_every, usec_t dt) { static unsigned long long tcpext_ListenOverflows = 0; // times the listen queue of a socket overflowed static unsigned long long tcpext_ListenDrops = 0; // SYNs to LISTEN sockets ignored - // IPv4 TCP memory pressures + // IP TCP memory pressures static unsigned long long tcpext_TCPMemoryPressures = 0; + static unsigned long long tcpext_TCPReqQFullDrop = 0; + static unsigned long long tcpext_TCPReqQFullDoCookies = 0; + // shared: tcpext_TCPSynRetrans @@ -109,26 +118,28 @@ int do_proc_net_netstat(int update_every, usec_t dt) { hash_ipext = simple_hash("IpExt"); hash_tcpext = simple_hash("TcpExt"); - do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_BOOLEAN_AUTO); - do_inerrors = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_BOOLEAN_AUTO); - do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_BOOLEAN_AUTO); - do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO); - do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_BOOLEAN_AUTO); - do_bcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_BOOLEAN_AUTO); - do_ecn = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_BOOLEAN_AUTO); - - do_tcpext_reorder = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_BOOLEAN_AUTO); - do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO); - do_tcpext_ofo = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO); - do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_BOOLEAN_AUTO); - do_tcpext_memory = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_BOOLEAN_AUTO); - do_tcpext_listen = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP listen issues", CONFIG_BOOLEAN_AUTO); + do_bandwidth = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "bandwidth", CONFIG_BOOLEAN_AUTO); + do_inerrors = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "input errors", CONFIG_BOOLEAN_AUTO); + do_mcast = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "multicast bandwidth", CONFIG_BOOLEAN_AUTO); + do_bcast = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "broadcast bandwidth", CONFIG_BOOLEAN_AUTO); + do_mcast_p = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "multicast packets", CONFIG_BOOLEAN_AUTO); + do_bcast_p = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "broadcast packets", CONFIG_BOOLEAN_AUTO); + do_ecn = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "ECN packets", CONFIG_BOOLEAN_AUTO); + + do_tcpext_reorder = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP reorders", CONFIG_BOOLEAN_AUTO); + do_tcpext_syscookies = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP SYN cookies", CONFIG_BOOLEAN_AUTO); + do_tcpext_ofo = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO); + do_tcpext_connaborts = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP connection aborts", CONFIG_BOOLEAN_AUTO); + do_tcpext_memory = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP memory pressures", CONFIG_BOOLEAN_AUTO); + + do_tcpext_syn_queue = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP SYN queue", CONFIG_BOOLEAN_AUTO); + do_tcpext_accept_queue = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP accept queue", CONFIG_BOOLEAN_AUTO); arl_ipext = arl_create("netstat/ipext", NULL, 60); arl_tcpext = arl_create("netstat/tcpext", NULL, 60); // -------------------------------------------------------------------- - // IPv4 + // IP if(do_bandwidth != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InOctets", &ipext_InOctets); @@ -169,7 +180,7 @@ int do_proc_net_netstat(int update_every, usec_t dt) { } // -------------------------------------------------------------------- - // IPv4 TCP + // IP TCP if(do_tcpext_reorder != CONFIG_BOOLEAN_NO) { arl_expect(arl_tcpext, "TCPFACKReorder", &tcpext_TCPFACKReorder); @@ -204,11 +215,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures); } - if(do_tcpext_listen != CONFIG_BOOLEAN_NO) { + if(do_tcpext_accept_queue != CONFIG_BOOLEAN_NO) { arl_expect(arl_tcpext, "ListenOverflows", &tcpext_ListenOverflows); arl_expect(arl_tcpext, "ListenDrops", &tcpext_ListenDrops); } + if(do_tcpext_syn_queue != CONFIG_BOOLEAN_NO) { + arl_expect(arl_tcpext, "TCPReqQFullDrop", &tcpext_TCPReqQFullDrop); + arl_expect(arl_tcpext, "TCPReqQFullDoCookies", &tcpext_TCPReqQFullDoCookies); + } + // shared metrics arl_expect(arl_tcpext, "TCPSynRetrans", &tcpext_TCPSynRetrans); } @@ -216,7 +232,7 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/netstat"); - ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } @@ -248,111 +264,111 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (ipext_InOctets || ipext_OutOctets))) { do_bandwidth = CONFIG_BOOLEAN_YES; - static RRDSET *st_system_ipv4 = NULL; + static RRDSET *st_system_ip = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; - if(unlikely(!st_system_ipv4)) { - st_system_ipv4 = rrdset_create_localhost( + if(unlikely(!st_system_ip)) { + st_system_ip = rrdset_create_localhost( "system" - , "ipv4" + , RRD_TYPE_NET_NETSTAT , NULL , "network" , NULL - , "IPv4 Bandwidth" + , "IP Bandwidth" , "kilobits/s" - , "proc" - , "net/netstat" - , 501 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_IP , update_every , RRDSET_TYPE_AREA ); - rd_in = rrddim_add(st_system_ipv4, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_system_ipv4, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + 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_ipv4); + rrdset_next(st_system_ip); - rrddim_set_by_pointer(st_system_ipv4, rd_in, ipext_InOctets); - rrddim_set_by_pointer(st_system_ipv4, rd_out, ipext_OutOctets); + 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_ipv4); + rrdset_done(st_system_ip); } // -------------------------------------------------------------------- if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && (ipext_InNoRoutes || ipext_InTruncatedPkts))) { do_inerrors = CONFIG_BOOLEAN_YES; - static RRDSET *st_ipv4_inerrors = NULL; + static RRDSET *st_ip_inerrors = NULL; static RRDDIM *rd_noroutes = NULL, *rd_truncated = NULL, *rd_checksum = NULL; - if(unlikely(!st_ipv4_inerrors)) { - st_ipv4_inerrors = rrdset_create_localhost( - "ipv4" + if(unlikely(!st_ip_inerrors)) { + st_ip_inerrors = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT , "inerrors" , NULL , "errors" , NULL - , "IPv4 Input Errors" + , "IP Input Errors" , "packets/s" - , "proc" - , "net/netstat" - , 4000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_ERRORS , update_every , RRDSET_TYPE_LINE ); - rrdset_flag_set(st_ipv4_inerrors, RRDSET_FLAG_DETAIL); + rrdset_flag_set(st_ip_inerrors, RRDSET_FLAG_DETAIL); - rd_noroutes = rrddim_add(st_ipv4_inerrors, "InNoRoutes", "noroutes", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_truncated = rrddim_add(st_ipv4_inerrors, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_checksum = rrddim_add(st_ipv4_inerrors, "InCsumErrors", "checksum", 1, 1, RRD_ALGORITHM_INCREMENTAL); + 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_ipv4_inerrors); + rrdset_next(st_ip_inerrors); - rrddim_set_by_pointer(st_ipv4_inerrors, rd_noroutes, ipext_InNoRoutes); - rrddim_set_by_pointer(st_ipv4_inerrors, rd_truncated, ipext_InTruncatedPkts); - rrddim_set_by_pointer(st_ipv4_inerrors, rd_checksum, ipext_InCsumErrors); + 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_ipv4_inerrors); + rrdset_done(st_ip_inerrors); } // -------------------------------------------------------------------- if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (ipext_InMcastOctets || ipext_OutMcastOctets))) { do_mcast = CONFIG_BOOLEAN_YES; - static RRDSET *st_ipv4_mcast = NULL; + static RRDSET *st_ip_mcast = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; - if(unlikely(!st_ipv4_mcast)) { - st_ipv4_mcast = rrdset_create_localhost( - "ipv4" + if(unlikely(!st_ip_mcast)) { + st_ip_mcast = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT , "mcast" , NULL , "multicast" , NULL - , "IPv4 Multicast Bandwidth" + , "IP Multicast Bandwidth" , "kilobits/s" - , "proc" - , "net/netstat" - , 9000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_MCAST , update_every , RRDSET_TYPE_AREA ); - rrdset_flag_set(st_ipv4_mcast, RRDSET_FLAG_DETAIL); + rrdset_flag_set(st_ip_mcast, RRDSET_FLAG_DETAIL); - rd_in = rrddim_add(st_ipv4_mcast, "InMcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ipv4_mcast, "OutMcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + 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_ipv4_mcast); + rrdset_next(st_ip_mcast); - rrddim_set_by_pointer(st_ipv4_mcast, rd_in, ipext_InMcastOctets); - rrddim_set_by_pointer(st_ipv4_mcast, rd_out, ipext_OutMcastOctets); + 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_ipv4_mcast); + rrdset_done(st_ip_mcast); } // -------------------------------------------------------------------- @@ -360,37 +376,37 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (ipext_InBcastOctets || ipext_OutBcastOctets))) { do_bcast = CONFIG_BOOLEAN_YES; - static RRDSET *st_ipv4_bcast = NULL; + static RRDSET *st_ip_bcast = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; - if(unlikely(!st_ipv4_bcast)) { - st_ipv4_bcast = rrdset_create_localhost( - "ipv4" + if(unlikely(!st_ip_bcast)) { + st_ip_bcast = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT , "bcast" , NULL , "broadcast" , NULL - , "IPv4 Broadcast Bandwidth" + , "IP Broadcast Bandwidth" , "kilobits/s" - , "proc" - , "net/netstat" - , 8000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_BCAST , update_every , RRDSET_TYPE_AREA ); - rrdset_flag_set(st_ipv4_bcast, RRDSET_FLAG_DETAIL); + rrdset_flag_set(st_ip_bcast, RRDSET_FLAG_DETAIL); - rd_in = rrddim_add(st_ipv4_bcast, "InBcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ipv4_bcast, "OutBcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); + 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_ipv4_bcast); + rrdset_next(st_ip_bcast); - rrddim_set_by_pointer(st_ipv4_bcast, rd_in, ipext_InBcastOctets); - rrddim_set_by_pointer(st_ipv4_bcast, rd_out, ipext_OutBcastOctets); + 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_ipv4_bcast); + rrdset_done(st_ip_bcast); } // -------------------------------------------------------------------- @@ -398,36 +414,36 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InMcastPkts || ipext_OutMcastPkts))) { do_mcast_p = CONFIG_BOOLEAN_YES; - static RRDSET *st_ipv4_mcastpkts = NULL; + static RRDSET *st_ip_mcastpkts = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; - if(unlikely(!st_ipv4_mcastpkts)) { - st_ipv4_mcastpkts = rrdset_create_localhost( - "ipv4" + if(unlikely(!st_ip_mcastpkts)) { + st_ip_mcastpkts = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT , "mcastpkts" , NULL , "multicast" , NULL - , "IPv4 Multicast Packets" + , "IP Multicast Packets" , "packets/s" - , "proc" - , "net/netstat" - , 8600 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_MCAST_PACKETS , update_every , RRDSET_TYPE_LINE ); - rrdset_flag_set(st_ipv4_mcastpkts, RRDSET_FLAG_DETAIL); + rrdset_flag_set(st_ip_mcastpkts, RRDSET_FLAG_DETAIL); - rd_in = rrddim_add(st_ipv4_mcastpkts, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ipv4_mcastpkts, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + 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_ipv4_mcastpkts); + else rrdset_next(st_ip_mcastpkts); - rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_in, ipext_InMcastPkts); - rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_out, ipext_OutMcastPkts); + 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_ipv4_mcastpkts); + rrdset_done(st_ip_mcastpkts); } // -------------------------------------------------------------------- @@ -435,37 +451,37 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InBcastPkts || ipext_OutBcastPkts))) { do_bcast_p = CONFIG_BOOLEAN_YES; - static RRDSET *st_ipv4_bcastpkts = NULL; + static RRDSET *st_ip_bcastpkts = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; - if(unlikely(!st_ipv4_bcastpkts)) { - st_ipv4_bcastpkts = rrdset_create_localhost( - "ipv4" + if(unlikely(!st_ip_bcastpkts)) { + st_ip_bcastpkts = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT , "bcastpkts" , NULL , "broadcast" , NULL - , "IPv4 Broadcast Packets" + , "IP Broadcast Packets" , "packets/s" - , "proc" - , "net/netstat" - , 8500 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_BCAST_PACKETS , update_every , RRDSET_TYPE_LINE ); - rrdset_flag_set(st_ipv4_bcastpkts, RRDSET_FLAG_DETAIL); + rrdset_flag_set(st_ip_bcastpkts, RRDSET_FLAG_DETAIL); - rd_in = rrddim_add(st_ipv4_bcastpkts, "InBcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_out = rrddim_add(st_ipv4_bcastpkts, "OutBcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + 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_ipv4_bcastpkts); + rrdset_next(st_ip_bcastpkts); - rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_in, ipext_InBcastPkts); - rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_out, ipext_OutBcastPkts); + 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_ipv4_bcastpkts); + rrdset_done(st_ip_bcastpkts); } // -------------------------------------------------------------------- @@ -478,16 +494,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(unlikely(!st_ecnpkts)) { st_ecnpkts = rrdset_create_localhost( - "ipv4" + RRD_TYPE_NET_NETSTAT , "ecnpkts" , NULL , "ecn" , NULL - , "IPv4 ECN Statistics" + , "IP ECN Statistics" , "packets/s" - , "proc" - , "net/netstat" - , 8700 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_ECN , update_every , RRDSET_TYPE_LINE ); @@ -530,16 +546,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(unlikely(!st_tcpmemorypressures)) { st_tcpmemorypressures = rrdset_create_localhost( - "ipv4" + RRD_TYPE_NET_NETSTAT , "tcpmemorypressures" , NULL , "tcp" , NULL , "TCP Memory Pressures" , "events/s" - , "proc" - , "net/netstat" - , 3000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_MEM , update_every , RRDSET_TYPE_LINE ); @@ -564,16 +580,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(unlikely(!st_tcpconnaborts)) { st_tcpconnaborts = rrdset_create_localhost( - "ipv4" + RRD_TYPE_NET_NETSTAT , "tcpconnaborts" , NULL , "tcp" , NULL , "TCP Connection Aborts" , "connections/s" - , "proc" - , "net/netstat" - , 3010 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_CONNABORTS , update_every , RRDSET_TYPE_LINE ); @@ -608,16 +624,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(unlikely(!st_tcpreorders)) { st_tcpreorders = rrdset_create_localhost( - "ipv4" + RRD_TYPE_NET_NETSTAT , "tcpreorders" , NULL , "tcp" , NULL , "TCP Reordered Packets by Detection Method" , "packets/s" - , "proc" - , "net/netstat" - , 3020 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_REORDERS , update_every , RRDSET_TYPE_LINE ); @@ -643,40 +659,40 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) { do_tcpext_ofo = CONFIG_BOOLEAN_YES; - static RRDSET *st_ipv4_tcpofo = NULL; + static RRDSET *st_ip_tcpofo = NULL; static RRDDIM *rd_inqueue = NULL, *rd_dropped = NULL, *rd_merged = NULL, *rd_pruned = NULL; - if(unlikely(!st_ipv4_tcpofo)) { + if(unlikely(!st_ip_tcpofo)) { - st_ipv4_tcpofo = rrdset_create_localhost( - "ipv4" + st_ip_tcpofo = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT , "tcpofo" , NULL , "tcp" , NULL , "TCP Out-Of-Order Queue" , "packets/s" - , "proc" - , "net/netstat" - , 3050 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_OFO , update_every , RRDSET_TYPE_LINE ); - rd_inqueue = rrddim_add(st_ipv4_tcpofo, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_dropped = rrddim_add(st_ipv4_tcpofo, "TCPOFODrop", "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_merged = rrddim_add(st_ipv4_tcpofo, "TCPOFOMerge", "merged", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_pruned = rrddim_add(st_ipv4_tcpofo, "OfoPruned", "pruned", -1, 1, RRD_ALGORITHM_INCREMENTAL); + 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_ipv4_tcpofo); + rrdset_next(st_ip_tcpofo); - rrddim_set_by_pointer(st_ipv4_tcpofo, rd_inqueue, tcpext_TCPOFOQueue); - rrddim_set_by_pointer(st_ipv4_tcpofo, rd_dropped, tcpext_TCPOFODrop); - rrddim_set_by_pointer(st_ipv4_tcpofo, rd_merged, tcpext_TCPOFOMerge); - rrddim_set_by_pointer(st_ipv4_tcpofo, rd_pruned, tcpext_OfoPruned); + 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_ipv4_tcpofo); + rrdset_done(st_ip_tcpofo); } // -------------------------------------------------------------------- @@ -690,16 +706,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { if(unlikely(!st_syncookies)) { st_syncookies = rrdset_create_localhost( - "ipv4" + RRD_TYPE_NET_NETSTAT , "tcpsyncookies" , NULL , "tcp" , NULL , "TCP SYN Cookies" , "packets/s" - , "proc" - , "net/netstat" - , 3100 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_SYNCOOKIES , update_every , RRDSET_TYPE_LINE ); @@ -720,40 +736,81 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && (tcpext_ListenOverflows || tcpext_ListenDrops))) { - do_tcpext_listen = CONFIG_BOOLEAN_YES; + if(do_tcpext_syn_queue == CONFIG_BOOLEAN_YES || (do_tcpext_syn_queue == CONFIG_BOOLEAN_AUTO && (tcpext_TCPReqQFullDrop || tcpext_TCPReqQFullDoCookies))) { + do_tcpext_syn_queue = CONFIG_BOOLEAN_YES; - static RRDSET *st_listen = NULL; - static RRDDIM *rd_overflows = NULL, *rd_drops = NULL; + static RRDSET *st_syn_queue = NULL; + static RRDDIM + *rd_TCPReqQFullDrop = NULL, + *rd_TCPReqQFullDoCookies = NULL; - if(unlikely(!st_listen)) { + if(unlikely(!st_syn_queue)) { - st_listen = rrdset_create_localhost( - "ipv4" - , "tcplistenissues" + st_syn_queue = rrdset_create_localhost( + RRD_TYPE_NET_NETSTAT + , "tcp_syn_queue" , NULL , "tcp" , NULL - , "TCP Listen Socket Issues" + , "TCP SYN Queue Issues" , "packets/s" - , "proc" - , "net/netstat" - , 3015 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NETSTAT_NAME + , NETDATA_CHART_PRIO_IP_TCP_SYN_QUEUE , update_every , RRDSET_TYPE_LINE ); - rd_overflows = rrddim_add(st_listen, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL); - rd_drops = rrddim_add(st_listen, "ListenDrops", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL); + 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_listen); + rrdset_next(st_syn_queue); - rrddim_set_by_pointer(st_listen, rd_overflows, tcpext_ListenOverflows); - rrddim_set_by_pointer(st_listen, rd_drops, tcpext_ListenDrops); + 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_listen); + rrdset_done(st_syn_queue); } + + // -------------------------------------------------------------------- + + if(do_tcpext_accept_queue == CONFIG_BOOLEAN_YES || (do_tcpext_accept_queue == CONFIG_BOOLEAN_AUTO && (tcpext_ListenOverflows || tcpext_ListenDrops))) { + 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); + } + } } diff --git a/src/proc_net_rpc_nfs.c b/collectors/proc.plugin/proc_net_rpc_nfs.c index a4c778cb..f5702859 100644 --- a/src/proc_net_rpc_nfs.c +++ b/collectors/proc.plugin/proc_net_rpc_nfs.c @@ -1,4 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_NFS_NAME "/proc/net/rpc/nfs" +#define CONFIG_SECTION_PLUGIN_PROC_NFS "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NFS_NAME struct nfs_procs { char name[30]; @@ -143,18 +148,18 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { if(!ff) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/rpc/nfs"); - ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_NFS, "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); } if(!ff) return 1; ff = procfile_readall(ff); if(!ff) return 0; // we return 0, so that we will retry to open it next time - if(do_net == -1) do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "network", 1); - if(do_rpc == -1) do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "rpc", 1); - if(do_proc2 == -1) do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v2 procedures", 1); - if(do_proc3 == -1) do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v3 procedures", 1); - if(do_proc4 == -1) do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v4 procedures", 1); + if(do_net == -1) do_net = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NFS, "network", 1); + if(do_rpc == -1) do_rpc = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NFS, "rpc", 1); + if(do_proc2 == -1) do_proc2 = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NFS, "NFS v2 procedures", 1); + if(do_proc3 == -1) do_proc3 = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NFS, "NFS v3 procedures", 1); + if(do_proc4 == -1) do_proc4 = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_NFS, "NFS v4 procedures", 1); // if they are enabled, reset them to 1 // later we do them =2 to avoid doing strcmp() for all lines @@ -286,9 +291,9 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , NULL , "NFS Client Network" , "operations/s" - , "proc" - , "net/rpc/nfs" - , 2207 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFS_NAME + , NETDATA_CHART_PRIO_NFS_NET , update_every , RRDSET_TYPE_STACKED ); @@ -326,9 +331,9 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , NULL , "NFS Client Remote Procedure Calls Statistics" , "calls/s" - , "proc" - , "net/rpc/nfs" - , 2208 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFS_NAME + , NETDATA_CHART_PRIO_NFS_RPC , update_every , RRDSET_TYPE_LINE ); @@ -359,9 +364,9 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , NULL , "NFS v2 Client Remote Procedure Calls" , "calls/s" - , "proc" - , "net/rpc/nfs" - , 2209 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFS_NAME + , NETDATA_CHART_PRIO_NFS_PROC2 , update_every , RRDSET_TYPE_STACKED ); @@ -392,9 +397,9 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , NULL , "NFS v3 Client Remote Procedure Calls" , "calls/s" - , "proc" - , "net/rpc/nfs" - , 2210 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFS_NAME + , NETDATA_CHART_PRIO_NFS_PROC3 , update_every , RRDSET_TYPE_STACKED ); @@ -425,9 +430,9 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { , NULL , "NFS v4 Client Remote Procedure Calls" , "calls/s" - , "proc" - , "net/rpc/nfs" - , 2211 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFS_NAME + , NETDATA_CHART_PRIO_NFS_PROC4 , update_every , RRDSET_TYPE_STACKED ); diff --git a/src/proc_net_rpc_nfsd.c b/collectors/proc.plugin/proc_net_rpc_nfsd.c index 8aca31ae..20b87e9d 100644 --- a/src/proc_net_rpc_nfsd.c +++ b/collectors/proc.plugin/proc_net_rpc_nfsd.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_NFSD_NAME "/proc/net/rpc/nfsd" struct nfsd_procs { char name[30]; @@ -515,9 +519,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server Read Cache" , "reads/s" - , "proc" - , "net/rpc/nfsd" - , 2100 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_READCACHE , update_every , RRDSET_TYPE_STACKED ); @@ -553,9 +557,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server File Handles" , "handles/s" - , "proc" - , "net/rpc/nfsd" - , 2101 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_FILEHANDLES , update_every , RRDSET_TYPE_LINE ); @@ -593,9 +597,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server I/O" , "kilobytes/s" - , "proc" - , "net/rpc/nfsd" - , 2102 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_IO , update_every , RRDSET_TYPE_AREA ); @@ -626,9 +630,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server Threads" , "threads" - , "proc" - , "net/rpc/nfsd" - , 2103 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_THREADS , update_every , RRDSET_TYPE_LINE ); @@ -654,9 +658,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server Threads Full Count" , "ops/s" - , "proc" - , "net/rpc/nfsd" - , 2104 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_THREADS_FULLCNT , update_every , RRDSET_TYPE_LINE ); @@ -691,9 +695,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server Threads Usage Histogram" , "percentage" - , "proc" - , "net/rpc/nfsd" - , 2105 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_THREADS_HISTOGRAM , update_every , RRDSET_TYPE_LINE ); @@ -750,9 +754,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server Read Ahead Depth" , "percentage" - , "proc" - , "net/rpc/nfsd" - , 2105 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_READAHEAD , update_every , RRDSET_TYPE_STACKED ); @@ -804,9 +808,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server Network Statistics" , "packets/s" - , "proc" - , "net/rpc/nfsd" - , 2107 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_NET , update_every , RRDSET_TYPE_STACKED ); @@ -843,9 +847,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS Server Remote Procedure Calls Statistics" , "calls/s" - , "proc" - , "net/rpc/nfsd" - , 2108 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_RPC , update_every , RRDSET_TYPE_LINE ); @@ -879,9 +883,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS v2 Server Remote Procedure Calls" , "calls/s" - , "proc" - , "net/rpc/nfsd" - , 2109 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_PROC2 , update_every , RRDSET_TYPE_STACKED ); @@ -912,9 +916,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS v3 Server Remote Procedure Calls" , "calls/s" - , "proc" - , "net/rpc/nfsd" - , 2110 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_PROC3 , update_every , RRDSET_TYPE_STACKED ); @@ -945,9 +949,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS v4 Server Remote Procedure Calls" , "calls/s" - , "proc" - , "net/rpc/nfsd" - , 2111 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_PROC4 , update_every , RRDSET_TYPE_STACKED ); @@ -978,9 +982,9 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { , NULL , "NFS v4 Server Operations" , "operations/s" - , "proc" - , "net/rpc/nfsd" - , 2112 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NFSD_NAME + , NETDATA_CHART_PRIO_NFSD_PROC4OPS , update_every , RRDSET_TYPE_STACKED ); diff --git a/src/proc_net_snmp.c b/collectors/proc.plugin/proc_net_snmp.c index 43c010c1..ffd368f6 100644 --- a/src/proc_net_snmp.c +++ b/collectors/proc.plugin/proc_net_snmp.c @@ -1,6 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later -#define RRD_TYPE_NET_SNMP "ipv4" +#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; @@ -102,23 +105,22 @@ int do_proc_net_snmp(int update_every, usec_t dt) { *arl_udplite = NULL; static RRDVAR *tcp_max_connections_var = NULL; - static ssize_t last_max_connections = 0; if(unlikely(!arl_ip)) { - do_ip_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1); - do_ip_fragsout = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", 1); - do_ip_fragsin = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1); - do_ip_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 errors", 1); - do_tcp_sockets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", 1); - do_tcp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", 1); - do_tcp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", 1); - do_tcp_opens = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP opens", 1); - do_tcp_handshake = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", 1); - do_udp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", 1); - do_udp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", 1); - do_icmp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP packets", 1); - do_icmpmsg = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP messages", 1); - do_udplite_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDPLite packets", 1); + 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"); @@ -181,7 +183,7 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // arl_expect(arl_tcp, "RtoAlgorithm", &snmp_root.tcp_RtoAlgorithm); // arl_expect(arl_tcp, "RtoMin", &snmp_root.tcp_RtoMin); // arl_expect(arl_tcp, "RtoMax", &snmp_root.tcp_RtoMax); - arl_expect(arl_tcp, "MaxConn", &snmp_root.tcp_MaxConn); + arl_expect_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); @@ -256,7 +258,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_packets) { + 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))) { + do_ip_packets = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_InReceives = NULL, *rd_OutRequests = NULL, @@ -272,9 +276,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 Packets" , "packets/s" - , "proc" - , "net/snmp" - , 2450 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_PACKETS , update_every , RRDSET_TYPE_LINE ); @@ -295,7 +299,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_fragsout) { + 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))) { + do_ip_fragsout = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_FragOKs = NULL, *rd_FragFails = NULL, @@ -310,9 +316,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 Fragments Sent" , "packets/s" - , "proc" - , "net/snmp" - , 3020 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_FRAGMENTS , update_every , RRDSET_TYPE_LINE ); @@ -332,7 +338,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_fragsin) { + 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))) { + do_ip_fragsin = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_ReasmOKs = NULL, *rd_ReasmFails = NULL, @@ -347,9 +355,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 Fragments Reassembly" , "packets/s" - , "proc" - , "net/snmp" - , 3030 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_FRAGMENTS + 1 , update_every , RRDSET_TYPE_LINE ); @@ -369,7 +377,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_errors) { + 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))) { + do_ip_errors = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_InDiscards = NULL, *rd_OutDiscards = NULL, @@ -387,9 +397,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 Errors" , "packets/s" - , "proc" - , "net/snmp" - , 2470 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_ERRORS , update_every , RRDSET_TYPE_LINE ); @@ -437,7 +447,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_packets) { + 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))) { + do_icmp_packets = CONFIG_BOOLEAN_YES; + { static RRDSET *st_packets = NULL; static RRDDIM *rd_InMsgs = NULL, @@ -452,9 +464,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 ICMP Packets" , "packets/s" - , "proc" - , "net/snmp" - , 2602 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_ICMP , update_every , RRDSET_TYPE_LINE ); @@ -485,9 +497,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 ICMP Errors" , "packets/s" - , "proc" - , "net/snmp" - , 2603 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_ICMP + 1 , update_every , RRDSET_TYPE_LINE ); @@ -515,8 +527,8 @@ int do_proc_net_snmp(int update_every, usec_t dt) { } words = procfile_linewords(ff, l); - if(words < 3) { - error("Cannot read /proc/net/snmp IcmpMsg line. Expected 3+ params, read %zu.", words); + if(words < 2) { + error("Cannot read /proc/net/snmp IcmpMsg line. Expected 2+ params, read %zu.", words); continue; } @@ -528,7 +540,30 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmpmsg) { + 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 + ))) { + do_icmpmsg = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_InEchoReps = NULL, *rd_OutEchoReps = NULL, @@ -560,9 +595,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 ICMP Messages" , "packets/s" - , "proc" - , "net/snmp" - , 2604 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_ICMP + 2 , update_every , RRDSET_TYPE_LINE ); @@ -636,15 +671,15 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(snmp_root.tcp_MaxConn != last_max_connections) { - last_max_connections = snmp_root.tcp_MaxConn; - rrdvar_custom_host_variable_set(localhost, tcp_max_connections_var, last_max_connections); - } + // 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) { + if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && snmp_root.tcp_CurrEstab)) { + do_tcp_sockets = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_CurrEstab = NULL; @@ -657,9 +692,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 TCP Connections" , "active connections" - , "proc" - , "net/snmp" - , 2501 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_TCP , update_every , RRDSET_TYPE_LINE ); @@ -674,7 +709,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcp_packets) { + if(do_tcp_packets == CONFIG_BOOLEAN_YES || (do_tcp_packets == CONFIG_BOOLEAN_AUTO && (snmp_root.tcp_InSegs || snmp_root.tcp_OutSegs))) { + do_tcp_packets = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_InSegs = NULL, *rd_OutSegs = NULL; @@ -688,9 +725,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 TCP Packets" , "packets/s" - , "proc" - , "net/snmp" - , 2510 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + 4 , update_every , RRDSET_TYPE_LINE ); @@ -707,7 +744,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcp_errors) { + 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))) { + do_tcp_errors = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_InErrs = NULL, *rd_InCsumErrors = NULL, @@ -722,9 +761,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 TCP Errors" , "packets/s" - , "proc" - , "net/snmp" - , 2525 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + 20 , update_every , RRDSET_TYPE_LINE ); @@ -744,7 +783,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcp_opens) { + if(do_tcp_opens == CONFIG_BOOLEAN_YES || (do_tcp_opens == CONFIG_BOOLEAN_AUTO && (snmp_root.tcp_ActiveOpens || snmp_root.tcp_PassiveOpens))) { + do_tcp_opens = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_ActiveOpens = NULL, *rd_PassiveOpens = NULL; @@ -758,9 +799,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 TCP Opens" , "connections/s" - , "proc" - , "net/snmp" - , 2502 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_TCP + 5 , update_every , RRDSET_TYPE_LINE ); @@ -778,7 +819,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcp_handshake) { + 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))) { + do_tcp_handshake = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_EstabResets = NULL, *rd_OutRsts = NULL, @@ -794,25 +837,25 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 TCP Handshake Issues" , "events/s" - , "proc" - , "net/snmp" - , 2530 + , 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", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_EstabResets = rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_OutRsts = rrddim_add(st, "OutRsts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_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); + 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); } } @@ -839,7 +882,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html - if(do_udp_packets) { + if(do_udp_packets == CONFIG_BOOLEAN_YES || (do_udp_packets == CONFIG_BOOLEAN_AUTO && (snmp_root.udp_InDatagrams || snmp_root.udp_OutDatagrams))) { + do_udp_packets = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_InDatagrams = NULL, *rd_OutDatagrams = NULL; @@ -853,9 +898,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 UDP Packets" , "packets/s" - , "proc" - , "net/snmp" - , 2602 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_UDP , update_every , RRDSET_TYPE_LINE ); @@ -872,7 +917,16 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_udp_errors) { + 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 + ))) { + do_udp_errors = CONFIG_BOOLEAN_YES; + static RRDSET *st = NULL; static RRDDIM *rd_RcvbufErrors = NULL, *rd_SndbufErrors = NULL, @@ -890,9 +944,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 UDP Errors" , "events/s" - , "proc" - , "net/snmp" - , 2701 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_UDP + 10 , update_every , RRDSET_TYPE_LINE ); @@ -938,7 +992,18 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_udplite_packets) { + 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 + ))) { + do_udplite_packets = CONFIG_BOOLEAN_YES; + { static RRDSET *st = NULL; static RRDDIM *rd_InDatagrams = NULL, @@ -953,9 +1018,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 UDPLite Packets" , "packets/s" - , "proc" - , "net/snmp" - , 2603 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_UDPLITE , update_every , RRDSET_TYPE_LINE ); @@ -988,9 +1053,9 @@ int do_proc_net_snmp(int update_every, usec_t dt) { , NULL , "IPv4 UDPLite Errors" , "packets/s" - , "proc" - , "net/snmp" - , 2604 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP_NAME + , NETDATA_CHART_PRIO_IPV4_UDPLITE + 10 , update_every , RRDSET_TYPE_LINE); diff --git a/src/proc_net_snmp6.c b/collectors/proc.plugin/proc_net_snmp6.c index bd71b391..f0084aa2 100644 --- a/src/proc_net_snmp6.c +++ b/collectors/proc.plugin/proc_net_snmp6.c @@ -1,6 +1,9 @@ -#include "common.h" +// 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; @@ -289,9 +292,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Bandwidth" , "kilobits/s" - , "proc" - , "net/snmp6" - , 502 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_SYSTEM_IPV6 , update_every , RRDSET_TYPE_AREA ); @@ -325,9 +328,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Packets" , "packets/s" - , "proc" - , "net/snmp6" - , 3000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_PACKETS , update_every , RRDSET_TYPE_LINE ); @@ -364,9 +367,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Fragments Sent" , "packets/s" - , "proc" - , "net/snmp6" - , 3011 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_FRAGSOUT , update_every , RRDSET_TYPE_LINE ); @@ -410,9 +413,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Fragments Reassembly" , "packets/s" - , "proc" - , "net/snmp6" - , 3012 + , 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); @@ -465,9 +468,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Errors" , "packets/s" - , "proc" - , "net/snmp6" - , 3002 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ERRORS , update_every , RRDSET_TYPE_LINE ); @@ -514,9 +517,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 UDP Packets" , "packets/s" - , "proc" - , "net/snmp6" - , 3601 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_UDP_PACKETS , update_every , RRDSET_TYPE_LINE ); @@ -560,9 +563,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 UDP Errors" , "events/s" - , "proc" - , "net/snmp6" - , 3701 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_UDP_ERRORS , update_every , RRDSET_TYPE_LINE ); @@ -603,9 +606,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 UDPlite Packets" , "packets/s" - , "proc" - , "net/snmp6" - , 3602 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_UDPLITE_PACKETS , update_every , RRDSET_TYPE_LINE ); @@ -648,9 +651,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 UDP Lite Errors" , "events/s" - , "proc" - , "net/snmp6" - , 3701 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_UDPLITE_ERRORS , update_every , RRDSET_TYPE_LINE ); @@ -689,9 +692,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Multicast Bandwidth" , "kilobits/s" - , "proc" - , "net/snmp6" - , 9000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_MCAST , update_every , RRDSET_TYPE_AREA ); @@ -724,9 +727,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Broadcast Bandwidth" , "kilobits/s" - , "proc" - , "net/snmp6" - , 8000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_BCAST , update_every , RRDSET_TYPE_AREA ); @@ -759,9 +762,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Multicast Packets" , "packets/s" - , "proc" - , "net/snmp6" - , 9500 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_MCAST_PACKETS , update_every , RRDSET_TYPE_LINE ); @@ -794,9 +797,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ICMP Messages" , "messages/s" - , "proc" - , "net/snmp6" - , 10000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP , update_every , RRDSET_TYPE_LINE ); @@ -828,9 +831,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ICMP Redirects" , "redirects/s" - , "proc" - , "net/snmp6" - , 10050 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_REDIR , update_every , RRDSET_TYPE_LINE ); @@ -884,9 +887,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ICMP Errors" , "errors/s" - , "proc" - , "net/snmp6" - , 10100 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_ERRORS , update_every , RRDSET_TYPE_LINE ); @@ -944,9 +947,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ICMP Echo" , "messages/s" - , "proc" - , "net/snmp6" - , 10200 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_ECHOS , update_every , RRDSET_TYPE_LINE ); @@ -994,9 +997,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ICMP Group Membership" , "messages/s" - , "proc" - , "net/snmp6" - , 10300 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_GROUPMEMB , update_every , RRDSET_TYPE_LINE); @@ -1043,9 +1046,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Router Messages" , "messages/s" - , "proc" - , "net/snmp6" - , 10400 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_ROUTER , update_every , RRDSET_TYPE_LINE ); @@ -1089,9 +1092,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 Neighbor Messages" , "messages/s" - , "proc" - , "net/snmp6" - , 10500 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_NEIGHBOR , update_every , RRDSET_TYPE_LINE ); @@ -1127,9 +1130,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ICMP MLDv2 Reports" , "reports/s" - , "proc" - , "net/snmp6" - , 10600 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_LDV2 , update_every , RRDSET_TYPE_LINE ); @@ -1181,9 +1184,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ICMP Types" , "messages/s" - , "proc" - , "net/snmp6" - , 10700 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ICMP_TYPES , update_every , RRDSET_TYPE_LINE ); @@ -1239,9 +1242,9 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { , NULL , "IPv6 ECT Packets" , "packets/s" - , "proc" - , "net/snmp6" - , 10800 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SNMP6_NAME + , NETDATA_CHART_PRIO_IPV6_ECT , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_net_sockstat.c b/collectors/proc.plugin/proc_net_sockstat.c index db307066..0c3b6e19 100644 --- a/src/proc_net_sockstat.c +++ b/collectors/proc.plugin/proc_net_sockstat.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME "/proc/net/sockstat" static struct proc_net_sockstat { kernel_uint_t sockets_used; @@ -56,9 +60,9 @@ static int read_tcp_mem(void) { // fprintf(stderr, "TCP MEM low = %llu, pressure = %llu, high = %llu\n", low, pressure, high); - rrdvar_custom_host_variable_set(localhost, tcp_mem_low_threshold, low * sysconf(_SC_PAGESIZE) / 1024); - rrdvar_custom_host_variable_set(localhost, tcp_mem_pressure_threshold, pressure * sysconf(_SC_PAGESIZE) / 1024); - rrdvar_custom_host_variable_set(localhost, tcp_mem_high_threshold, high * sysconf(_SC_PAGESIZE) / 1024); + rrdvar_custom_host_variable_set(localhost, tcp_mem_low_threshold, low * sysconf(_SC_PAGESIZE) / 1024.0); + rrdvar_custom_host_variable_set(localhost, tcp_mem_pressure_threshold, pressure * sysconf(_SC_PAGESIZE) / 1024.0); + rrdvar_custom_host_variable_set(localhost, tcp_mem_high_threshold, high * sysconf(_SC_PAGESIZE) / 1024.0); return 0; } @@ -229,9 +233,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 Sockets Used" , "sockets" - , "proc" - , "net/sockstat" - , 2400 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_SOCKETS , update_every , RRDSET_TYPE_LINE ); @@ -264,9 +268,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 TCP Sockets" , "sockets" - , "proc" - , "net/sockstat" - , 2500 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_TCP_SOCKETS , update_every , RRDSET_TYPE_LINE ); @@ -302,9 +306,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 TCP Sockets Memory" , "KB" - , "proc" - , "net/sockstat" - , 4000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_TCP_MEM , update_every , RRDSET_TYPE_AREA ); @@ -334,9 +338,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 UDP Sockets" , "sockets" - , "proc" - , "net/sockstat" - , 2600 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_UDP , update_every , RRDSET_TYPE_LINE ); @@ -366,9 +370,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 UDP Sockets Memory" , "KB" - , "proc" - , "net/sockstat" - , 2603 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_UDP_MEM , update_every , RRDSET_TYPE_AREA ); @@ -398,9 +402,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 UDPLITE Sockets" , "sockets" - , "proc" - , "net/sockstat" - , 2602 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_UDPLITE , update_every , RRDSET_TYPE_LINE ); @@ -430,9 +434,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 RAW Sockets" , "sockets" - , "proc" - , "net/sockstat" - , 3010 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_RAW , update_every , RRDSET_TYPE_LINE ); @@ -462,9 +466,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 FRAG Sockets" , "fragments" - , "proc" - , "net/sockstat" - , 3010 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_FRAGMENTS , update_every , RRDSET_TYPE_LINE ); @@ -494,9 +498,9 @@ int do_proc_net_sockstat(int update_every, usec_t dt) { , NULL , "IPv4 FRAG Sockets Memory" , "KB" - , "proc" - , "net/sockstat" - , 3020 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT_NAME + , NETDATA_CHART_PRIO_IPV4_FRAGMENTS_MEM , update_every , RRDSET_TYPE_AREA ); diff --git a/src/proc_net_sockstat6.c b/collectors/proc.plugin/proc_net_sockstat6.c index 97175ccf..687b9bde 100644 --- a/src/proc_net_sockstat6.c +++ b/collectors/proc.plugin/proc_net_sockstat6.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME "/proc/net/sockstat6" static struct proc_net_sockstat6 { kernel_uint_t tcp6_inuse; @@ -122,9 +126,9 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { , NULL , "IPv6 TCP Sockets" , "sockets" - , "proc" - , "net/sockstat6" - , 3599 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME + , NETDATA_CHART_PRIO_IPV6_TCP , update_every , RRDSET_TYPE_LINE ); @@ -154,9 +158,9 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { , NULL , "IPv6 UDP Sockets" , "sockets" - , "proc" - , "net/sockstat6" - , 3600 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME + , NETDATA_CHART_PRIO_IPV6_UDP , update_every , RRDSET_TYPE_LINE ); @@ -186,9 +190,9 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { , NULL , "IPv6 UDPLITE Sockets" , "sockets" - , "proc" - , "net/sockstat6" - , 3601 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME + , NETDATA_CHART_PRIO_IPV6_UDPLITE , update_every , RRDSET_TYPE_LINE ); @@ -218,9 +222,9 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { , NULL , "IPv6 RAW Sockets" , "sockets" - , "proc" - , "net/sockstat6" - , 3700 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME + , NETDATA_CHART_PRIO_IPV6_RAW , update_every , RRDSET_TYPE_LINE ); @@ -250,9 +254,9 @@ int do_proc_net_sockstat6(int update_every, usec_t dt) { , NULL , "IPv6 FRAG Sockets" , "fragments" - , "proc" - , "net/sockstat6" - , 3010 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME + , NETDATA_CHART_PRIO_IPV6_FRAGMENTS , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_net_softnet_stat.c b/collectors/proc.plugin/proc_net_softnet_stat.c index f3c117e1..7ec783e7 100644 --- a/src/proc_net_softnet_stat.c +++ b/collectors/proc.plugin/proc_net_softnet_stat.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_NET_SOFTNET_NAME "/proc/net/softnet_stat" static inline char *softnet_column_name(size_t column) { switch(column) { @@ -87,9 +91,9 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { , "system.softnet_stat" , "System softnet_stat" , "events/s" - , "proc" - , "net/softnet_stat" - , 955 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOFTNET_NAME + , NETDATA_CHART_PRIO_SYSTEM_SOFTNET_STAT , update_every , RRDSET_TYPE_LINE ); @@ -123,9 +127,9 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { , "cpu.softnet_stat" , title , "events/s" - , "proc" - , "net/softnet_stat" - , 4101 + l + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_NET_SOFTNET_NAME + , NETDATA_CHART_PRIO_SOFTNET_PER_CORE + l , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_net_stat_conntrack.c b/collectors/proc.plugin/proc_net_stat_conntrack.c index 363fbc19..f5257c0a 100644 --- a/src/proc_net_stat_conntrack.c +++ b/collectors/proc.plugin/proc_net_stat_conntrack.c @@ -1,7 +1,10 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" #define RRD_TYPE_NET_STAT_NETFILTER "netfilter" #define RRD_TYPE_NET_STAT_CONNTRACK "conntrack" +#define PLUGIN_PROC_MODULE_CONNTRACK_NAME "/proc/net/stat/nf_conntrack" int do_proc_net_stat_conntrack(int update_every, usec_t dt) { static procfile *ff = NULL; @@ -140,9 +143,9 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { , NULL , "Connection Tracker Connections" , "active connections" - , "proc" - , "net/stat/nf_conntrack" - , 3000 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_CONNTRACK_NAME + , NETDATA_CHART_PRIO_NETFILTER_SOCKETS , update_every , RRDSET_TYPE_LINE ); @@ -173,9 +176,9 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { , NULL , "Connection Tracker New Connections" , "connections/s" - , "proc" - , "net/stat/nf_conntrack" - , 3001 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_CONNTRACK_NAME + , NETDATA_CHART_PRIO_NETFILTER_NEW , update_every , RRDSET_TYPE_LINE ); @@ -210,9 +213,9 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { , NULL , "Connection Tracker Changes" , "changes/s" - , "proc" - , "net/stat/nf_conntrack" - , 3002 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_CONNTRACK_NAME + , NETDATA_CHART_PRIO_NETFILTER_CHANGES , update_every , RRDSET_TYPE_LINE ); @@ -247,9 +250,9 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { , NULL , "Connection Tracker Expectations" , "expectations/s" - , "proc" - , "net/stat/nf_conntrack" - , 3003 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_CONNTRACK_NAME + , NETDATA_CHART_PRIO_NETFILTER_EXPECT , update_every , RRDSET_TYPE_LINE ); @@ -284,9 +287,9 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { , NULL , "Connection Tracker Searches" , "searches/s" - , "proc" - , "net/stat/nf_conntrack" - , 3010 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_CONNTRACK_NAME + , NETDATA_CHART_PRIO_NETFILTER_SEARCH , update_every , RRDSET_TYPE_LINE ); @@ -322,9 +325,9 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { , NULL , "Connection Tracker Errors" , "events/s" - , "proc" - , "net/stat/nf_conntrack" - , 3005 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_CONNTRACK_NAME + , NETDATA_CHART_PRIO_NETFILTER_ERRORS , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_net_stat_synproxy.c b/collectors/proc.plugin/proc_net_stat_synproxy.c index 0d6f6ee0..f0c1f47c 100644 --- a/src/proc_net_stat_synproxy.c +++ b/collectors/proc.plugin/proc_net_stat_synproxy.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_SYNPROXY_NAME "/proc/net/stat/synproxy" #define RRD_TYPE_NET_STAT_NETFILTER "netfilter" #define RRD_TYPE_NET_STAT_SYNPROXY "synproxy" @@ -68,9 +72,9 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { , NULL , "SYNPROXY Entries Used" , "entries" - , "proc" - , "net/stat/synproxy" - , 3304 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_SYNPROXY_NAME + , NETDATA_CHART_PRIO_SYNPROXY_ENTRIES , update_every , RRDSET_TYPE_LINE ); @@ -98,9 +102,9 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { , NULL , "SYNPROXY SYN Packets received" , "SYN/s" - , "proc" - , "net/stat/synproxy" - , 3301 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_SYNPROXY_NAME + , NETDATA_CHART_PRIO_SYNPROXY_SYN_RECEIVED , update_every , RRDSET_TYPE_LINE ); @@ -128,9 +132,9 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { , NULL , "SYNPROXY Connections Reopened" , "connections/s" - , "proc" - , "net/stat/synproxy" - , 3303 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_SYNPROXY_NAME + , NETDATA_CHART_PRIO_SYNPROXY_CONN_OPEN , update_every , RRDSET_TYPE_LINE ); @@ -158,9 +162,9 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { , NULL , "SYNPROXY TCP Cookies" , "cookies/s" - , "proc" - , "net/stat/synproxy" - , 3302 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_SYNPROXY_NAME + , NETDATA_CHART_PRIO_SYNPROXY_COOKIES , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_self_mountinfo.c b/collectors/proc.plugin/proc_self_mountinfo.c index 4ccdddff..3f17ccce 100644 --- a/src/proc_self_mountinfo.c +++ b/collectors/proc.plugin/proc_self_mountinfo.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" // ---------------------------------------------------------------------------- // taken from gnulib/mountlist.c diff --git a/src/proc_self_mountinfo.h b/collectors/proc.plugin/proc_self_mountinfo.h index a8d33753..15d63c78 100644 --- a/src/proc_self_mountinfo.h +++ b/collectors/proc.plugin/proc_self_mountinfo.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_PROC_SELF_MOUNTINFO_H #define NETDATA_PROC_SELF_MOUNTINFO_H 1 diff --git a/src/proc_softirqs.c b/collectors/proc.plugin/proc_softirqs.c index cd7440b0..d68c69bb 100644 --- a/src/proc_softirqs.c +++ b/collectors/proc.plugin/proc_softirqs.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_SOFTIRQS_NAME "/proc/softirqs" #define MAX_INTERRUPT_NAME 50 @@ -51,15 +55,16 @@ static inline struct interrupt *get_interrupts_array(size_t lines, int cpus) { int do_proc_softirqs(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; - static int cpus = -1, do_per_core = -1; + static int cpus = -1, do_per_core = CONFIG_BOOLEAN_INVALID; struct interrupt *irrs = NULL; - if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1); + if(unlikely(do_per_core == CONFIG_BOOLEAN_INVALID)) + do_per_core = config_get_boolean_ondemand("plugin:proc:/proc/softirqs", "interrupts per core", CONFIG_BOOLEAN_AUTO); if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/softirqs"); - ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); + ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } @@ -105,10 +110,6 @@ int do_proc_softirqs(int update_every, usec_t dt) { irr->id = procfile_lineword(ff, l, 0); if(unlikely(!irr->id || !irr->id[0])) continue; - size_t idlen = strlen(irr->id); - if(unlikely(idlen && irr->id[idlen - 1] == ':')) - irr->id[idlen - 1] = '\0'; - int c; for(c = 0; c < cpus ;c++) { if(likely((c + 1) < (int)words)) @@ -136,9 +137,9 @@ int do_proc_softirqs(int update_every, usec_t dt) { , NULL , "System softirqs" , "softirqs/s" - , "proc" - , "softirqs" - , 950 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_SOFTIRQS_NAME + , NETDATA_CHART_PRIO_SYSTEM_SOFTIRQS , update_every , RRDSET_TYPE_STACKED ); @@ -148,34 +149,30 @@ int do_proc_softirqs(int update_every, usec_t dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(unlikely(!irr->used)) continue; - - // 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)) { - irr->rd = rrddim_find(st_system_softirqs, irr->id); - - if(unlikely(!irr->rd)) + if(irr->used && irr->total) { + // 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)) { irr->rd = rrddim_add(st_system_softirqs, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - else rrddim_set_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)) { - int c; - for (c = 0; c < cpus ;c++) irr->cpu[c].rd = NULL; + // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop + if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { + int c; + for(c = 0; c < cpus; c++) irr->cpu[c].rd = NULL; + } } - } - rrddim_set_by_pointer(st_system_softirqs, irr->rd, irr->total); + rrddim_set_by_pointer(st_system_softirqs, irr->rd, irr->total); + } } rrdset_done(st_system_softirqs); // -------------------------------------------------------------------- - if(do_per_core) { + if(do_per_core != CONFIG_BOOLEAN_NO) { static RRDSET **core_st = NULL; static int old_cpus = 0; @@ -214,9 +211,9 @@ int do_proc_softirqs(int update_every, usec_t dt) { , "cpu.softirqs" , title , "softirqs/s" - , "proc" - , "softirqs" - , 3000 + c + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_SOFTIRQS_NAME + , NETDATA_CHART_PRIO_SOFTIRQS_PER_CORE + c , update_every , RRDSET_TYPE_STACKED ); @@ -227,18 +224,14 @@ int do_proc_softirqs(int update_every, usec_t dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(unlikely(!irr->used)) continue; - - if(unlikely(!irr->cpu[c].rd)) { - irr->cpu[c].rd = rrddim_find(core_st[c], irr->id); - - if(unlikely(!irr->cpu[c].rd)) + 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); - else rrddim_set_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); + rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value); + } } rrdset_done(core_st[c]); diff --git a/src/proc_spl_kstat_zfs.c b/collectors/proc.plugin/proc_spl_kstat_zfs.c index 9d489d8e..a96b236c 100644 --- a/src/proc_spl_kstat_zfs.c +++ b/collectors/proc.plugin/proc_spl_kstat_zfs.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" #include "zfs_common.h" #define ZFS_PROC_ARCSTATS "/proc/spl/kstat/zfs/arcstats" @@ -146,8 +148,8 @@ int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt) { if(unlikely(arcstats.l2exist == -1)) arcstats.l2exist = 0; - generate_charts_arcstats("proc", update_every); - generate_charts_arc_summary("proc", update_every); + generate_charts_arcstats(PLUGIN_PROC_NAME, ZFS_PROC_ARCSTATS, update_every); + generate_charts_arc_summary(PLUGIN_PROC_NAME, ZFS_PROC_ARCSTATS, update_every); return 0; } diff --git a/src/proc_stat.c b/collectors/proc.plugin/proc_stat.c index d1aefb73..fb77df64 100644 --- a/src/proc_stat.c +++ b/collectors/proc.plugin/proc_stat.c @@ -1,7 +1,11 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_STAT_NAME "/proc/stat" struct per_core_single_number_file { - char found:1; + unsigned char found:1; const char *filename; int fd; collected_number value; @@ -121,6 +125,8 @@ int do_proc_stat(int update_every, usec_t dt) { static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1, do_core_throttle_count = -1, do_package_throttle_count = -1, do_scaling_cur_freq = -1; 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; + static RRDVAR *cpus_var = NULL; + size_t cores_found = (size_t)processors; if(unlikely(do_cpu == -1)) { do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", CONFIG_BOOLEAN_YES); @@ -196,6 +202,7 @@ int do_proc_stat(int update_every, usec_t dt) { } size_t core = (row_key[3] == '\0') ? 0 : str2ul(&row_key[3]) + 1; + if(core > 0) cores_found = core; if(likely((core == 0 && do_cpu) || (core > 0 && do_cpu_cores))) { char *id; @@ -236,17 +243,17 @@ int do_proc_stat(int update_every, usec_t dt) { type = "system"; context = "system.cpu"; family = id; - priority = 100; + priority = NETDATA_CHART_PRIO_SYSTEM_CPU; } else { title = "Core utilization"; type = "cpu"; context = "cpu.cpu"; family = "utilization"; - priority = 1000; + priority = NETDATA_CHART_PRIO_CPU_PER_CORE; - // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq - // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/stats/time_in_state + // TODO: check for /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq + // TODO: check for /sys/devices/system/cpu/cpu*/cpufreq/stats/time_in_state char filename[FILENAME_MAX + 1]; struct stat stbuf; @@ -287,9 +294,9 @@ int do_proc_stat(int update_every, usec_t dt) { , context , title , "percentage" - , "proc" - , "stat" - , priority + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME + , priority + core , update_every , RRDSET_TYPE_STACKED ); @@ -308,6 +315,9 @@ int do_proc_stat(int update_every, usec_t dt) { cpu_chart->rd_iowait = rrddim_add(cpu_chart->st, "iowait", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); cpu_chart->rd_idle = rrddim_add(cpu_chart->st, "idle", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(cpu_chart->st, "idle"); + + if(unlikely(core == 0 && cpus_var == NULL)) + cpus_var = rrdvar_custom_host_variable_create(localhost, "active_processors"); } else rrdset_next(cpu_chart->st); @@ -339,9 +349,9 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "CPU Interrupts" , "interrupts/s" - , "proc" - , "stat" - , 900 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_INTR , update_every , RRDSET_TYPE_LINE ); @@ -371,9 +381,9 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "CPU Context Switches" , "context switches/s" - , "proc" - , "stat" - , 800 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_CTXT , update_every , RRDSET_TYPE_LINE ); @@ -412,9 +422,9 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "Started Processes" , "processes/s" - , "proc" - , "stat" - , 700 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_FORKS , update_every , RRDSET_TYPE_LINE ); @@ -444,9 +454,9 @@ int do_proc_stat(int update_every, usec_t dt) { , NULL , "System Processes" , "processes" - , "proc" - , "stat" - , 600 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_PROCESSES , update_every , RRDSET_TYPE_LINE ); @@ -478,9 +488,9 @@ int do_proc_stat(int update_every, usec_t dt) { , "cpu.core_throttling" , "Core Thermal Throttling Events" , "events/s" - , "proc" - , "stat" - , 5001 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME + , NETDATA_CHART_PRIO_CORE_THROTTLING , update_every , RRDSET_TYPE_LINE ); @@ -508,9 +518,9 @@ int do_proc_stat(int update_every, usec_t dt) { , "cpu.package_throttling" , "Package Thermal Throttling Events" , "events/s" - , "proc" - , "stat" - , 5002 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME + , NETDATA_CHART_PRIO_PACKAGE_THROTTLING , update_every , RRDSET_TYPE_LINE ); @@ -538,8 +548,8 @@ int do_proc_stat(int update_every, usec_t dt) { , "cpu.scaling_cur_freq" , "Per CPU Core, Current CPU Scaling Frequency" , "MHz" - , "proc" - , "stat" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_STAT_NAME , 5003 , update_every , RRDSET_TYPE_LINE @@ -553,5 +563,8 @@ int do_proc_stat(int update_every, usec_t dt) { } } + if(cpus_var) + rrdvar_custom_host_variable_set(localhost, cpus_var, cores_found); + return 0; } diff --git a/src/proc_sys_kernel_random_entropy_avail.c b/collectors/proc.plugin/proc_sys_kernel_random_entropy_avail.c index ca4d7657..20d2116c 100644 --- a/src/proc_sys_kernel_random_entropy_avail.c +++ b/collectors/proc.plugin/proc_sys_kernel_random_entropy_avail.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) { (void)dt; @@ -29,9 +31,9 @@ int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) { , NULL , "Available Entropy" , "entropy" - , "proc" - , "sys/kernel/random/entropy_avail" - , 1000 + , PLUGIN_PROC_NAME + , "/proc/sys/kernel/random/entropy_avail" + , NETDATA_CHART_PRIO_SYSTEM_ENTROPY , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_uptime.c b/collectors/proc.plugin/proc_uptime.c index 259de476..142ae2d0 100644 --- a/src/proc_uptime.c +++ b/collectors/proc.plugin/proc_uptime.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" static inline collected_number uptime_from_boottime(void) { #ifdef CLOCK_BOOTTIME_IS_AVAILABLE @@ -83,9 +85,9 @@ int do_proc_uptime(int update_every, usec_t dt) { , NULL , "System Uptime" , "seconds" - , "proc" - , "uptime" - , 1000 + , PLUGIN_PROC_NAME + , "/proc/uptime" + , NETDATA_CHART_PRIO_SYSTEM_UPTIME , update_every , RRDSET_TYPE_LINE ); diff --git a/src/proc_vmstat.c b/collectors/proc.plugin/proc_vmstat.c index 52e88d88..f7c93c20 100644 --- a/src/proc_vmstat.c +++ b/collectors/proc.plugin/proc_vmstat.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_VMSTAT_NAME "/proc/vmstat" int do_proc_vmstat(int update_every, usec_t dt) { (void)dt; @@ -102,9 +106,9 @@ int do_proc_vmstat(int update_every, usec_t dt) { , NULL , "Swap I/O" , "kilobytes/s" - , "proc" - , "vmstat" - , 250 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_VMSTAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_SWAPIO , update_every , RRDSET_TYPE_AREA ); @@ -134,9 +138,9 @@ int do_proc_vmstat(int update_every, usec_t dt) { , NULL , "Memory Paged from/to disk" , "kilobytes/s" - , "proc" - , "vmstat" - , 151 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_VMSTAT_NAME + , NETDATA_CHART_PRIO_SYSTEM_PGPGIO , update_every , RRDSET_TYPE_AREA ); @@ -166,8 +170,8 @@ int do_proc_vmstat(int update_every, usec_t dt) { , NULL , "Memory Page Faults" , "page faults/s" - , "proc" - , "vmstat" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_VMSTAT_NAME , NETDATA_CHART_PRIO_MEM_SYSTEM_PGFAULTS , update_every , RRDSET_TYPE_LINE @@ -211,8 +215,8 @@ int do_proc_vmstat(int update_every, usec_t dt) { , NULL , "NUMA events" , "events/s" - , "proc" - , "vmstat" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_VMSTAT_NAME , NETDATA_CHART_PRIO_MEM_NUMA , update_every , RRDSET_TYPE_LINE diff --git a/src/sys_devices_system_edac_mc.c b/collectors/proc.plugin/sys_devices_system_edac_mc.c index caa16192..03cbfff8 100644 --- a/src/sys_devices_system_edac_mc.c +++ b/collectors/proc.plugin/sys_devices_system_edac_mc.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" struct mc { char *name; @@ -140,9 +142,9 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { , NULL , "ECC Memory Correctable Errors" , "errors" - , "proc" + , PLUGIN_PROC_NAME , "/sys/devices/system/edac/mc" - , NETDATA_CHART_PRIO_MEM_HW + 50 + , NETDATA_CHART_PRIO_MEM_HW_ECC_CE , update_every , RRDSET_TYPE_LINE ); @@ -178,9 +180,9 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { , NULL , "ECC Memory Uncorrectable Errors" , "errors" - , "proc" + , PLUGIN_PROC_NAME , "/sys/devices/system/edac/mc" - , NETDATA_CHART_PRIO_MEM_HW + 60 + , NETDATA_CHART_PRIO_MEM_HW_ECC_UE , update_every , RRDSET_TYPE_LINE ); diff --git a/src/sys_devices_system_node.c b/collectors/proc.plugin/sys_devices_system_node.c index d04c8dc3..6e6d0acc 100644 --- a/src/sys_devices_system_node.c +++ b/collectors/proc.plugin/sys_devices_system_node.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" struct node { char *name; @@ -105,9 +107,9 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) { , NULL , "NUMA events" , "events/s" - , "proc" + , PLUGIN_PROC_NAME , "/sys/devices/system/node" - , NETDATA_CHART_PRIO_MEM_NUMA + 10 + , NETDATA_CHART_PRIO_MEM_NUMA_NODES , update_every , RRDSET_TYPE_LINE ); diff --git a/src/sys_fs_btrfs.c b/collectors/proc.plugin/sys_fs_btrfs.c index a8dfb5c9..ed980cea 100644 --- a/src/sys_fs_btrfs.c +++ b/collectors/proc.plugin/sys_fs_btrfs.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_BTRFS_NAME "/sys/fs/btrfs" typedef struct btrfs_disk { char *name; @@ -171,12 +175,16 @@ static inline int find_btrfs_disks(BTRFS_NODE *node, const char *path) { snprintfz(filename, FILENAME_MAX, "%s/%s/size", path, de->d_name); d->size_filename = strdupz(filename); - // for disks - snprintfz(filename, FILENAME_MAX, "%s/%s/queue/hw_sector_size", path, de->d_name); + // for bcache + snprintfz(filename, FILENAME_MAX, "%s/%s/bcache/../queue/hw_sector_size", path, de->d_name); struct stat sb; - if(stat(filename, &sb) == -1) - // for partitions - snprintfz(filename, FILENAME_MAX, "%s/%s/../queue/hw_sector_size", path, de->d_name); + if(stat(filename, &sb) == -1) { + // for disks + snprintfz(filename, FILENAME_MAX, "%s/%s/queue/hw_sector_size", path, de->d_name); + if(stat(filename, &sb) == -1) + // for partitions + snprintfz(filename, FILENAME_MAX, "%s/%s/../queue/hw_sector_size", path, de->d_name); + } d->hw_sector_size_filename = strdupz(filename); @@ -538,7 +546,7 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { snprintf(id, RRD_ID_LENGTH_MAX, "disk_%s", node->id); snprintf(name, RRD_ID_LENGTH_MAX, "disk_%s", node->label); - snprintf(title, 200, "BTRFS Disk Allocation for %s", node->label); + snprintf(title, 200, "BTRFS Physical Disk Allocation for %s", node->label); netdata_fix_chart_id(id); netdata_fix_chart_name(name); @@ -551,20 +559,20 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { , "btrfs.disk" , title , "MB" - , "proc" - , "sys/fs/btrfs" - , 2300 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_BTRFS_NAME + , NETDATA_CHART_PRIO_BTRFS_DISK , update_every , RRDSET_TYPE_STACKED ); - node->rd_allocation_disks_unallocated = rrddim_add(node->st_allocation_disks, "unallocated", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); - node->rd_allocation_disks_data_used = rrddim_add(node->st_allocation_disks, "data_used", "data used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); - node->rd_allocation_disks_data_free = rrddim_add(node->st_allocation_disks, "data_free", "data free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); - node->rd_allocation_disks_metadata_used = rrddim_add(node->st_allocation_disks, "meta_used", "meta used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + node->rd_allocation_disks_unallocated = rrddim_add(node->st_allocation_disks, "unallocated", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + node->rd_allocation_disks_data_free = rrddim_add(node->st_allocation_disks, "data_free", "data free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + node->rd_allocation_disks_data_used = rrddim_add(node->st_allocation_disks, "data_used", "data used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); node->rd_allocation_disks_metadata_free = rrddim_add(node->st_allocation_disks, "meta_free", "meta free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); - node->rd_allocation_disks_system_used = rrddim_add(node->st_allocation_disks, "sys_used", "sys used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); - node->rd_allocation_disks_system_free = rrddim_add(node->st_allocation_disks, "sys_free", "sys free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + node->rd_allocation_disks_metadata_used = rrddim_add(node->st_allocation_disks, "meta_used", "meta used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + node->rd_allocation_disks_system_free = rrddim_add(node->st_allocation_disks, "sys_free", "sys free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + node->rd_allocation_disks_system_used = rrddim_add(node->st_allocation_disks, "sys_used", "sys used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(node->st_allocation_disks); @@ -607,9 +615,9 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { , "btrfs.data" , title , "MB" - , "proc" - , "sys/fs/btrfs" - , 2301 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_BTRFS_NAME + , NETDATA_CHART_PRIO_BTRFS_DATA , update_every , RRDSET_TYPE_STACKED ); @@ -648,9 +656,9 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { , "btrfs.metadata" , title , "MB" - , "proc" - , "sys/fs/btrfs" - , 2302 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_BTRFS_NAME + , NETDATA_CHART_PRIO_BTRFS_METADATA , update_every , RRDSET_TYPE_STACKED ); @@ -691,9 +699,9 @@ int do_sys_fs_btrfs(int update_every, usec_t dt) { , "btrfs.system" , title , "MB" - , "proc" - , "sys/fs/btrfs" - , 2303 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_BTRFS_NAME + , NETDATA_CHART_PRIO_BTRFS_SYSTEM , update_every , RRDSET_TYPE_STACKED ); diff --git a/src/sys_kernel_mm_ksm.c b/collectors/proc.plugin/sys_kernel_mm_ksm.c index 7ca1366b..0f5c79c4 100644 --- a/src/sys_kernel_mm_ksm.c +++ b/collectors/proc.plugin/sys_kernel_mm_ksm.c @@ -1,4 +1,8 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_proc.h" + +#define PLUGIN_PROC_MODULE_KSM_NAME "/sys/kernel/mm/ksm" typedef struct ksm_name_value { char filename[FILENAME_MAX + 1]; @@ -102,8 +106,8 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { , NULL , "Kernel Same Page Merging" , "MB" - , "proc" - , "/sys/kernel/mm/ksm" + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_KSM_NAME , NETDATA_CHART_PRIO_MEM_KSM , update_every , RRDSET_TYPE_AREA @@ -142,9 +146,9 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { , NULL , "Kernel Same Page Merging Savings" , "MB" - , "proc" - , "/sys/kernel/mm/ksm" - , NETDATA_CHART_PRIO_MEM_KSM + 1 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_KSM_NAME + , NETDATA_CHART_PRIO_MEM_KSM_SAVINGS , update_every , RRDSET_TYPE_AREA ); @@ -176,9 +180,9 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { , NULL , "Kernel Same Page Merging Effectiveness" , "percentage" - , "proc" - , "/sys/kernel/mm/ksm" - , NETDATA_CHART_PRIO_MEM_KSM + 2 + , PLUGIN_PROC_NAME + , PLUGIN_PROC_MODULE_KSM_NAME + , NETDATA_CHART_PRIO_MEM_KSM_RATIOS , update_every , RRDSET_TYPE_LINE ); diff --git a/src/zfs_common.c b/collectors/proc.plugin/zfs_common.c index 05935dd0..1aaceb90 100644 --- a/src/zfs_common.c +++ b/collectors/proc.plugin/zfs_common.c @@ -1,9 +1,10 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + #include "zfs_common.h" struct arcstats arcstats = { 0 }; -void generate_charts_arcstats(const char *plugin, int update_every) { +void generate_charts_arcstats(const char *plugin, const char *module, int update_every) { // ARC reads unsigned long long aread = arcstats.hits + arcstats.misses; @@ -47,8 +48,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS ARC Size" , "MB" , plugin - , "zfs" - , 2500 + , module + , NETDATA_CHART_PRIO_ZFS_ARC_SIZE , update_every , RRDSET_TYPE_AREA ); @@ -85,8 +86,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS L2 ARC Size" , "MB" , plugin - , "zfs" - , 2500 + , module + , NETDATA_CHART_PRIO_ZFS_L2_SIZE , update_every , RRDSET_TYPE_AREA ); @@ -122,8 +123,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS Reads" , "reads/s" , plugin - , "zfs" - , 2510 + , module + , NETDATA_CHART_PRIO_ZFS_READS , update_every , RRDSET_TYPE_AREA ); @@ -167,8 +168,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS ARC L2 Read/Write Rate" , "kilobytes/s" , plugin - , "zfs" - , 2700 + , module + , NETDATA_CHART_PRIO_ZFS_IO , update_every , RRDSET_TYPE_AREA ); @@ -201,8 +202,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS ARC Hits" , "percentage" , plugin - , "zfs" - , 2520 + , module + , NETDATA_CHART_PRIO_ZFS_HITS , update_every , RRDSET_TYPE_STACKED ); @@ -235,8 +236,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS Demand Hits" , "percentage" , plugin - , "zfs" - , 2530 + , module + , NETDATA_CHART_PRIO_ZFS_DHITS , update_every , RRDSET_TYPE_STACKED ); @@ -269,8 +270,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS Prefetch Hits" , "percentage" , plugin - , "zfs" - , 2540 + , module + , NETDATA_CHART_PRIO_ZFS_PHITS , update_every , RRDSET_TYPE_STACKED ); @@ -303,8 +304,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS Metadata Hits" , "percentage" , plugin - , "zfs" - , 2550 + , module + , NETDATA_CHART_PRIO_ZFS_MHITS , update_every , RRDSET_TYPE_STACKED ); @@ -337,8 +338,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS L2 Hits" , "percentage" , plugin - , "zfs" - , 2560 + , module + , NETDATA_CHART_PRIO_ZFS_L2HITS , update_every , RRDSET_TYPE_STACKED ); @@ -373,8 +374,8 @@ void generate_charts_arcstats(const char *plugin, int update_every) { , "ZFS List Hits" , "hits/s" , plugin - , "zfs" - , 2600 + , module + , NETDATA_CHART_PRIO_ZFS_LIST_HITS , update_every , RRDSET_TYPE_AREA ); @@ -395,7 +396,7 @@ void generate_charts_arcstats(const char *plugin, int update_every) { } } -void generate_charts_arc_summary(const char *plugin, int update_every) { +void generate_charts_arc_summary(const char *plugin, const char *module, int update_every) { unsigned long long arc_accesses_total = arcstats.hits + arcstats.misses; unsigned long long real_hits = arcstats.mfu_hits + arcstats.mru_hits; unsigned long long real_misses = arc_accesses_total - real_hits; @@ -432,8 +433,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS ARC Size Breakdown" , "percentage" , plugin - , "zfs" - , 2520 + , module + , NETDATA_CHART_PRIO_ZFS_ARC_SIZE_BREAKDOWN , update_every , RRDSET_TYPE_STACKED ); @@ -471,8 +472,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS Memory Operations" , "operations/s" , plugin - , "zfs" - , 2523 + , module + , NETDATA_CHART_PRIO_ZFS_MEMORY_OPS , update_every , RRDSET_TYPE_LINE ); @@ -517,8 +518,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS Important Operations" , "operations/s" , plugin - , "zfs" - , 2522 + , module + , NETDATA_CHART_PRIO_ZFS_IMPORTANT_OPS , update_every , RRDSET_TYPE_LINE ); @@ -555,8 +556,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS Actual Cache Hits" , "percentage" , plugin - , "zfs" - , 2519 + , module + , NETDATA_CHART_PRIO_ZFS_ACTUAL_HITS , update_every , RRDSET_TYPE_STACKED ); @@ -589,8 +590,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS Data Demand Efficiency" , "percentage" , plugin - , "zfs" - , 2531 + , module + , NETDATA_CHART_PRIO_ZFS_DEMAND_DATA_HITS , update_every , RRDSET_TYPE_STACKED ); @@ -623,8 +624,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS Data Prefetch Efficiency" , "percentage" , plugin - , "zfs" - , 2532 + , module + , NETDATA_CHART_PRIO_ZFS_PREFETCH_DATA_HITS , update_every , RRDSET_TYPE_STACKED ); @@ -657,8 +658,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS ARC Hash Elements" , "elements" , plugin - , "zfs" - , 2800 + , module + , NETDATA_CHART_PRIO_ZFS_HASH_ELEMENTS , update_every , RRDSET_TYPE_LINE ); @@ -691,8 +692,8 @@ void generate_charts_arc_summary(const char *plugin, int update_every) { , "ZFS ARC Hash Chains" , "chains" , plugin - , "zfs" - , 2810 + , module + , NETDATA_CHART_PRIO_ZFS_HASH_CHAINS , update_every , RRDSET_TYPE_LINE ); diff --git a/src/zfs_common.h b/collectors/proc.plugin/zfs_common.h index 4494e70c..fab54f59 100644 --- a/src/zfs_common.h +++ b/collectors/proc.plugin/zfs_common.h @@ -1,5 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_ZFS_COMMON_H -#define NETDATA_ZFS_COMMON_H +#define NETDATA_ZFS_COMMON_H 1 + +#include "../../daemon/common.h" #define ZFS_FAMILY_SIZE "size" #define ZFS_FAMILY_EFFICIENCY "efficiency" @@ -105,7 +109,7 @@ struct arcstats { int l2exist; }; -void generate_charts_arcstats(const char *plugin, int update_every); -void generate_charts_arc_summary(const char *plugin, int update_every); +void generate_charts_arcstats(const char *plugin, const char *module, int update_every); +void generate_charts_arc_summary(const char *plugin, const char *module, int update_every); #endif //NETDATA_ZFS_COMMON_H diff --git a/src/.keep b/collectors/python.d.plugin/python_modules/urllib3/contrib/__init__.py index e69de29b..e69de29b 100644 --- a/src/.keep +++ b/collectors/python.d.plugin/python_modules/urllib3/contrib/__init__.py diff --git a/src/statsd.c b/collectors/statsd.plugin/statsd.c index 44ebd889..c92bfd1c 100644 --- a/src/statsd.c +++ b/collectors/statsd.plugin/statsd.c @@ -1,7 +1,10 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "statsd.h" #define STATSD_CHART_PREFIX "statsd" -#define STATSD_CHART_PRIORITY 90000 + +#define PLUGIN_STATSD_NAME "statsd.plugin" // -------------------------------------------------------------------------------------- @@ -87,7 +90,10 @@ typedef enum statsd_metric_options { STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED = 0x00000002, // render a private chart for this metric STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED = 0x00000004, // the metric has been checked if it should get private chart or not STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT = 0x00000008, // show the count of events for this private chart - STATSD_METRIC_OPTION_CHECKED_IN_APPS = 0x00000010, // set when this metric has been checked agains apps + STATSD_METRIC_OPTION_CHECKED_IN_APPS = 0x00000010, // set when this metric has been checked against apps + STATSD_METRIC_OPTION_USED_IN_APPS = 0x00000020, // set when this metric is used in apps + 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) } STATS_METRIC_OPTIONS; typedef enum statsd_metric_type { @@ -101,7 +107,7 @@ typedef enum statsd_metric_type { typedef struct statsd_metric { - avl avl; // indexing + avl avl; // indexing - has to be first const char *name; // the name of the metric uint32_t hash; // hash of the name @@ -122,14 +128,15 @@ typedef struct statsd_metric { // chart related members STATS_METRIC_OPTIONS options; // STATSD_METRIC_OPTION_* (bitfield) - char reset; // set to 1 to reset this metric to zero + char reset; // set to 1 by the charting thread to instruct the collector thread(s) to reset this metric collected_number last; // the last value sent to netdata - RRDSET *st; // the chart of this metric + RRDSET *st; // the private chart of this metric RRDDIM *rd_value; // the dimension of this metric value RRDDIM *rd_count; // the dimension for the number of events received // linking, used for walking through all metrics struct statsd_metric *next; + struct statsd_metric *next_useful; } STATSD_METRIC; @@ -140,10 +147,12 @@ typedef struct statsd_index { char *name; // the name of the index of metrics size_t events; // the number of events processed for this index size_t metrics; // the number of metrics in this index + size_t useful; // the number of useful metrics in this index STATSD_AVL_TREE index; // the AVL tree STATSD_METRIC *first; // the linked list of metrics (new metrics are added in front) + STATSD_METRIC *first_useful; // the linked list of useful metrics (new metrics are added in front) STATSD_FIRST_PTR_MUTEX; // when mutli-threading is enabled, a lock to protect the linked list STATS_METRIC_OPTIONS default_options; // default options for all metrics in this index @@ -255,13 +264,13 @@ static struct statsd { SIMPLE_PATTERN *charts_for; size_t tcp_idle_timeout; - size_t decimal_detail; + collected_number decimal_detail; size_t private_charts; size_t max_private_charts; size_t max_private_charts_hard; RRD_MEMORY_MODE private_charts_memory_mode; long private_charts_rrd_history_entries; - int private_charts_hidden; + unsigned int private_charts_hidden:1; STATSD_APP *apps; size_t recvmmsg_size; @@ -344,6 +353,7 @@ static struct statsd { .threads = 0, .collection_threads_status = NULL, .sockets = { + .config = &netdata_config, .config_section = CONFIG_SECTION_STATSD, .default_bind_to = "udp:localhost tcp:localhost", .default_port = STATSD_LISTEN_PORT, @@ -427,6 +437,13 @@ static inline LONG_DOUBLE statsd_parse_float(const char *v, LONG_DOUBLE def) { return value; } +static inline LONG_DOUBLE statsd_parse_sampling_rate(const char *v) { + LONG_DOUBLE sampling_rate = statsd_parse_float(v, 1.0); + if(unlikely(isless(sampling_rate, 0.001))) sampling_rate = 0.001; + if(unlikely(isgreater(sampling_rate, 1.0))) sampling_rate = 1.0; + return sampling_rate; +} + static inline long long statsd_parse_int(const char *v, long long def) { long long value; @@ -455,7 +472,12 @@ static inline int value_is_zinit(const char *value) { return (value && *value == 'z' && *++value == 'i' && *++value == 'n' && *++value == 'i' && *++value == 't' && *++value == '\0'); } +#define is_metric_checked(m) ((m)->options & STATSD_METRIC_OPTION_CHECKED) +#define is_metric_useful_for_collection(m) (!is_metric_checked(m) || ((m)->options & STATSD_METRIC_OPTION_USEFUL)) + static inline void statsd_process_gauge(STATSD_METRIC *m, const char *value, const char *sampling) { + if(!is_metric_useful_for_collection(m)) return; + if(unlikely(!value || !*value)) { error("STATSD: metric '%s' of type gauge, with empty value is ignored.", m->name); return; @@ -471,16 +493,18 @@ static inline void statsd_process_gauge(STATSD_METRIC *m, const char *value, con } else { if (unlikely(*value == '+' || *value == '-')) - m->gauge.value += statsd_parse_float(value, 1.0) / statsd_parse_float(sampling, 1.0); + m->gauge.value += statsd_parse_float(value, 1.0) / statsd_parse_sampling_rate(sampling); else - m->gauge.value = statsd_parse_float(value, 1.0) / statsd_parse_float(sampling, 1.0); + m->gauge.value = statsd_parse_float(value, 1.0); m->events++; m->count++; } } -static inline void statsd_process_counter(STATSD_METRIC *m, const char *value, const char *sampling) { +static inline void statsd_process_counter_or_meter(STATSD_METRIC *m, const char *value, const char *sampling) { + if(!is_metric_useful_for_collection(m)) return; + // we accept empty values for counters if(unlikely(m->reset)) statsd_reset_metric(m); @@ -489,21 +513,21 @@ static inline void statsd_process_counter(STATSD_METRIC *m, const char *value, c // magic loading of metric, without affecting anything } else { - m->counter.value += llrintl((LONG_DOUBLE) statsd_parse_int(value, 1) / statsd_parse_float(sampling, 1.0)); + m->counter.value += llrintl((LONG_DOUBLE) statsd_parse_int(value, 1) / statsd_parse_sampling_rate(sampling)); m->events++; m->count++; } } -static inline void statsd_process_meter(STATSD_METRIC *m, const char *value, const char *sampling) { - // this is the same with the counter - statsd_process_counter(m, value, sampling); -} +#define statsd_process_counter(m, value, sampling) statsd_process_counter_or_meter(m, value, sampling) +#define statsd_process_meter(m, value, sampling) statsd_process_counter_or_meter(m, value, sampling) + +static inline void statsd_process_histogram_or_timer(STATSD_METRIC *m, const char *value, const char *sampling, const char *type) { + if(!is_metric_useful_for_collection(m)) return; -static inline void statsd_process_histogram(STATSD_METRIC *m, const char *value, const char *sampling) { if(unlikely(!value || !*value)) { - error("STATSD: metric '%s' of type histogram, with empty value is ignored.", m->name); + error("STATSD: metric of type %s, with empty value is ignored.", type); return; } @@ -516,31 +540,35 @@ static inline void statsd_process_histogram(STATSD_METRIC *m, const char *value, // magic loading of metric, without affecting anything } else { - if (unlikely(m->histogram.ext->used == m->histogram.ext->size)) { - netdata_mutex_lock(&m->histogram.ext->mutex); - m->histogram.ext->size += statsd.histogram_increase_step; - m->histogram.ext->values = reallocz(m->histogram.ext->values, sizeof(LONG_DOUBLE) * m->histogram.ext->size); - netdata_mutex_unlock(&m->histogram.ext->mutex); - } + LONG_DOUBLE v = statsd_parse_float(value, 1.0); + LONG_DOUBLE sampling_rate = statsd_parse_sampling_rate(sampling); + if(unlikely(isless(sampling_rate, 0.01))) sampling_rate = 0.01; + if(unlikely(isgreater(sampling_rate, 1.0))) sampling_rate = 1.0; + + long long samples = llrintl(1.0 / sampling_rate); + while(samples-- > 0) { + + if(unlikely(m->histogram.ext->used == m->histogram.ext->size)) { + netdata_mutex_lock(&m->histogram.ext->mutex); + m->histogram.ext->size += statsd.histogram_increase_step; + m->histogram.ext->values = reallocz(m->histogram.ext->values, sizeof(LONG_DOUBLE) * m->histogram.ext->size); + netdata_mutex_unlock(&m->histogram.ext->mutex); + } - m->histogram.ext->values[m->histogram.ext->used++] = statsd_parse_float(value, 1.0) / statsd_parse_float(sampling, 1.0); + m->histogram.ext->values[m->histogram.ext->used++] = v; + } m->events++; m->count++; } } -static inline void statsd_process_timer(STATSD_METRIC *m, const char *value, const char *sampling) { - if(unlikely(!value || !*value)) { - error("STATSD: metric of type timer, with empty value is ignored."); - return; - } - - // timers are a use case of histogram - statsd_process_histogram(m, value, sampling); -} +#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 inline void statsd_process_set(STATSD_METRIC *m, const char *value) { + if(!is_metric_useful_for_collection(m)) return; + if(unlikely(!value || !*value)) { error("STATSD: metric of type set, with empty value is ignored."); return; @@ -578,8 +606,10 @@ static inline void statsd_process_set(STATSD_METRIC *m, const char *value) { // -------------------------------------------------------------------------------------------------------------------- // statsd parsing -static void statsd_process_metric(const char *name, const char *value, const char *type, const char *sampling) { - debug(D_STATSD, "STATSD: raw metric '%s', value '%s', type '%s', rate '%s'", name?name:"(null)", value?value:"(null)", type?type:"(null)", sampling?sampling:"(null)"); +static void statsd_process_metric(const char *name, const char *value, const char *type, const char *sampling, const char *tags) { + (void)tags; + + debug(D_STATSD, "STATSD: raw metric '%s', value '%s', type '%s', sampling '%s', tags '%s'", name?name:"(null)", value?value:"(null)", type?type:"(null)", sampling?sampling:"(null)", tags?tags:"(null)"); if(unlikely(!name || !*name)) return; if(unlikely(!type || !*type)) type = "m"; @@ -663,8 +693,8 @@ static inline size_t statsd_process(char *buffer, size_t size, int require_newli const char *s = buffer; while(*s) { - const char *name = NULL, *value = NULL, *type = NULL, *sampling = NULL; - char *name_end = NULL, *value_end = NULL, *type_end = NULL, *sampling_end = NULL; + const char *name = NULL, *value = NULL, *type = NULL, *sampling = NULL, *tags = NULL; + char *name_end = NULL, *value_end = NULL, *type_end = NULL, *sampling_end = NULL, *tags_end = NULL; s = name_end = (char *)statsd_parse_skip_up_to(name = s, ':', '|'); if(name == name_end) { @@ -679,10 +709,15 @@ static inline size_t statsd_process(char *buffer, size_t size, int require_newli s = type_end = (char *) statsd_parse_skip_up_to(type = ++s, '|', '@'); if(likely(*s == '|' || *s == '@')) { - s = sampling_end = (char *) statsd_parse_skip_up_to(sampling = ++s, '\r', '\n'); + s = sampling_end = (char *) statsd_parse_skip_up_to(sampling = ++s, '|', '#'); if(*sampling == '@') sampling++; } + if(likely(*s == '|' || *s == '#')) { + s = tags_end = (char *) statsd_parse_skip_up_to(tags = ++s, '|', '|'); + if(*tags == '#') tags++; + } + // skip everything until the end of the line while(*s && *s != '\n') s++; @@ -700,6 +735,7 @@ static inline size_t statsd_process(char *buffer, size_t size, int require_newli , statsd_parse_field_trim(value, value_end) , statsd_parse_field_trim(type, type_end) , statsd_parse_field_trim(sampling, sampling_end) + , statsd_parse_field_trim(tags, tags_end) ); } @@ -997,7 +1033,7 @@ void *statsd_collector_thread(void *ptr) { #define STATSD_CONF_LINE_MAX 8192 -static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t line, const char *path, const char *filename) { +static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t line, const char *filename) { if(!type || !*type) type = "last"; if(!strcmp(type, "events")) return STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS; @@ -1010,7 +1046,7 @@ static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t else if(!strcmp(type, "stddev")) return STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV; else if(!strcmp(type, "percentile")) return STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE; - error("STATSD: invalid type '%s' at line %zu of file '%s/%s'. Using 'last'.", type, line, path, filename); + error("STATSD: invalid type '%s' at line %zu of file '%s'. Using 'last'.", type, line, filename); return STATSD_APP_CHART_DIM_VALUE_TYPE_LAST; } @@ -1076,19 +1112,14 @@ static STATSD_APP_CHART_DIM *add_dimension_to_app_chart( return dim; } -static int statsd_readfile(const char *path, const char *filename, STATSD_APP *app, STATSD_APP_CHART *chart, DICTIONARY *dict) { - debug(D_STATSD, "STATSD configuration reading file '%s/%s'", path, filename); +static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHART *chart, DICTIONARY *dict) { + debug(D_STATSD, "STATSD configuration reading file '%s'", filename); char *buffer = mallocz(STATSD_CONF_LINE_MAX + 1); - if(filename[0] == '/') - strncpyz(buffer, filename, STATSD_CONF_LINE_MAX); - else - snprintfz(buffer, STATSD_CONF_LINE_MAX, "%s/%s", path, filename); - - FILE *fp = fopen(buffer, "r"); + FILE *fp = fopen(filename, "r"); if(!fp) { - error("STATSD: cannot open file '%s'.", buffer); + error("STATSD: cannot open file '%s'.", filename); freez(buffer); return -1; } @@ -1101,18 +1132,31 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a s = trim(buffer); if (!s || *s == '#') { - debug(D_STATSD, "STATSD: ignoring line %zu of file '%s/%s', it is empty.", line, path, filename); + debug(D_STATSD, "STATSD: ignoring line %zu of file '%s', it is empty.", line, filename); continue; } - debug(D_STATSD, "STATSD: processing line %zu of file '%s/%s': %s", line, path, filename, buffer); + debug(D_STATSD, "STATSD: processing line %zu of file '%s': %s", line, filename, buffer); if(*s == 'i' && strncmp(s, "include", 7) == 0) { s = trim(&s[7]); - if(s && *s) - statsd_readfile(path, s, app, chart, dict); + if(s && *s) { + char *tmp; + if(*s == '/') + tmp = strdupz(s); + else { + // the file to be included is relative to current file + // find the directory name from the file we already read + char *filename2 = strdupz(filename); // copy filename, since dirname() will change it + char *dir = dirname(filename2); // find the directory part of the filename + tmp = strdupz_path_subpath(dir, s); // compose the new filename to read; + freez(filename2); // free the filename we copied + } + statsd_readfile(tmp, app, chart, dict); + freez(tmp); + } else - error("STATSD: ignoring line %zu of file '%s/%s', include filename is empty", line, path, s); + error("STATSD: ignoring line %zu of file '%s', include filename is empty", line, filename); continue; } @@ -1160,7 +1204,7 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a chart->context = strdupz(s); chart->family = strdupz("overview"); chart->units = strdupz("value"); - chart->priority = STATSD_CHART_PRIORITY; + chart->priority = NETDATA_CHART_PRIO_STATSD_PRIVATE; chart->chart_type = RRDSET_TYPE_LINE; chart->next = app->charts; @@ -1174,20 +1218,20 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a } } else - error("STATSD: ignoring line %zu ('%s') of file '%s/%s', [app] is not defined.", line, s, path, filename); + error("STATSD: ignoring line %zu ('%s') of file '%s', [app] is not defined.", line, s, filename); continue; } if(!app) { - error("STATSD: ignoring line %zu ('%s') of file '%s/%s', it is outside all sections.", line, s, path, filename); + error("STATSD: ignoring line %zu ('%s') of file '%s', it is outside all sections.", line, s, filename); continue; } char *name = s; char *value = strchr(s, '='); if(!value) { - error("STATSD: ignoring line %zu ('%s') of file '%s/%s', there is no = in it.", line, s, path, filename); + error("STATSD: ignoring line %zu ('%s') of file '%s', there is no = in it.", line, s, filename); continue; } *value = '\0'; @@ -1197,11 +1241,11 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a value = trim(value); if(!name || *name == '#') { - error("STATSD: ignoring line %zu of file '%s/%s', name is empty.", line, path, filename); + error("STATSD: ignoring line %zu of file '%s', name is empty.", line, filename); continue; } if(!value) { - debug(D_CONFIG, "STATSD: ignoring line %zu of file '%s/%s', value is empty.", line, path, filename); + debug(D_CONFIG, "STATSD: ignoring line %zu of file '%s', value is empty.", line, filename); continue; } @@ -1241,7 +1285,7 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a app->rrd_history_entries = 5; } else { - error("STATSD: ignoring line %zu ('%s') of file '%s/%s'. Unknown keyword for the [app] section.", line, name, path, filename); + error("STATSD: ignoring line %zu ('%s') of file '%s'. Unknown keyword for the [app] section.", line, name, filename); continue; } } @@ -1326,14 +1370,14 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a , (multipler && *multipler)?str2l(multipler):1 , (divisor && *divisor)?str2l(divisor):1 , flags - , string2valuetype(type, line, path, filename) + , string2valuetype(type, line, filename) ); if(pattern) dim->metric_pattern = simple_pattern_create(dim->metric, NULL, SIMPLE_PATTERN_EXACT); } else { - error("STATSD: ignoring line %zu ('%s') of file '%s/%s'. Unknown keyword for the [%s] section.", line, name, path, filename, chart->id); + error("STATSD: ignoring line %zu ('%s') of file '%s'. Unknown keyword for the [%s] section.", line, name, filename, chart->id); continue; } } @@ -1344,49 +1388,13 @@ static int statsd_readfile(const char *path, const char *filename, STATSD_APP *a return 0; } -static void statsd_readdir(const char *path) { - size_t pathlen = strlen(path); - - debug(D_STATSD, "STATSD configuration reading directory '%s'", path); - - DIR *dir = opendir(path); - if (!dir) { - error("STATSD configuration cannot open directory '%s'.", path); - return; - } - - struct dirent *de = NULL; - while ((de = readdir(dir))) { - size_t len = strlen(de->d_name); - - if(de->d_type == DT_DIR - && ( - (de->d_name[0] == '.' && de->d_name[1] == '\0') - || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') - )) { - debug(D_STATSD, "STATSD: ignoring directory '%s'", de->d_name); - continue; - } - - else if(de->d_type == DT_DIR) { - char *s = mallocz(pathlen + strlen(de->d_name) + 2); - strcpy(s, path); - strcat(s, "/"); - strcat(s, de->d_name); - statsd_readdir(s); - freez(s); - continue; - } - - else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) && - len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { - statsd_readfile(path, de->d_name, NULL, NULL, NULL); - } - - else debug(D_STATSD, "STATSD: ignoring file '%s'", de->d_name); - } +static int statsd_file_callback(const char *filename, void *data) { + (void)data; + return statsd_readfile(filename, NULL, NULL, NULL); +} - closedir(dir); +static inline void statsd_readdir(const char *user_path, const char *stock_path, const char *subpath) { + recursive_config_double_dir_load(user_path, stock_path, subpath, statsd_file_callback, NULL, 0); } // -------------------------------------------------------------------------------------------------------------------- @@ -1445,7 +1453,7 @@ static inline RRDSET *statsd_private_rrdset_create( , context // context , title // title , units // units - , "statsd" // plugin + , PLUGIN_STATSD_NAME // plugin , "private_chart" // module , priority // priority , update_every // update every @@ -1484,7 +1492,7 @@ static inline void statsd_private_chart_gauge(STATSD_METRIC *m) { , context // context , title // title , "value" // units - , STATSD_CHART_PRIORITY + , NETDATA_CHART_PRIO_STATSD_PRIVATE , statsd.update_every , RRDSET_TYPE_LINE ); @@ -1526,7 +1534,7 @@ static inline void statsd_private_chart_counter_or_meter(STATSD_METRIC *m, const , context // context , title // title , "events/s" // units - , STATSD_CHART_PRIORITY + , NETDATA_CHART_PRIO_STATSD_PRIVATE , statsd.update_every , RRDSET_TYPE_AREA ); @@ -1568,7 +1576,7 @@ static inline void statsd_private_chart_set(STATSD_METRIC *m) { , context // context , title // title , "entries" // units - , STATSD_CHART_PRIORITY + , NETDATA_CHART_PRIO_STATSD_PRIVATE , statsd.update_every , RRDSET_TYPE_LINE ); @@ -1610,7 +1618,7 @@ static inline void statsd_private_chart_timer_or_histogram(STATSD_METRIC *m, con , context // context , title // title , units // units - , STATSD_CHART_PRIORITY + , NETDATA_CHART_PRIO_STATSD_PRIVATE , statsd.update_every , RRDSET_TYPE_AREA ); @@ -1649,14 +1657,14 @@ static inline void statsd_flush_gauge(STATSD_METRIC *m) { debug(D_STATSD, "flushing gauge metric '%s'", m->name); int updated = 0; - if(m->count && !m->reset) { + if(unlikely(!m->reset && m->count)) { m->last = (collected_number) (m->gauge.value * statsd.decimal_detail); m->reset = 1; updated = 1; } - if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED))) + if(unlikely(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))) statsd_private_chart_gauge(m); } @@ -1664,14 +1672,14 @@ static inline void statsd_flush_counter_or_meter(STATSD_METRIC *m, const char *d debug(D_STATSD, "flushing %s metric '%s'", dim, m->name); int updated = 0; - if(m->count && !m->reset) { + if(unlikely(!m->reset && m->count)) { m->last = m->counter.value; m->reset = 1; updated = 1; } - if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED))) + if(unlikely(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))) statsd_private_chart_counter_or_meter(m, dim, family); } @@ -1687,40 +1695,27 @@ static inline void statsd_flush_set(STATSD_METRIC *m) { debug(D_STATSD, "flushing set metric '%s'", m->name); int updated = 0; - if(m->count && !m->reset) { + if(unlikely(!m->reset && m->count)) { m->last = (collected_number)m->set.unique; m->reset = 1; updated = 1; } + else { + m->last = 0; + } - if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED))) + if(unlikely(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))) statsd_private_chart_set(m); } static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char *dim, const char *family, const char *units) { debug(D_STATSD, "flushing %s metric '%s'", dim, m->name); - netdata_mutex_lock(&m->histogram.ext->mutex); - - if(unlikely(!m->histogram.ext->zeroed)) { - // reset the metrics - // if we collected anything, they will be updated below - // this ensures that we report zeros if nothing is collected - - m->histogram.ext->last_min = 0; - m->histogram.ext->last_max = 0; - m->last = 0; - m->histogram.ext->last_median = 0; - m->histogram.ext->last_stddev = 0; - m->histogram.ext->last_sum = 0; - m->histogram.ext->last_percentile = 0; - - m->histogram.ext->zeroed = 1; - } - int updated = 0; - if(m->count && !m->reset && m->histogram.ext->used > 0) { + if(unlikely(!m->reset && m->count && m->histogram.ext->used > 0)) { + netdata_mutex_lock(&m->histogram.ext->mutex); + size_t len = m->histogram.ext->used; LONG_DOUBLE *series = m->histogram.ext->values; sort_series(series, len); @@ -1738,6 +1733,8 @@ static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char else m->histogram.ext->last_percentile = (collected_number)roundl(series[pct_len - 1] * statsd.decimal_detail); + netdata_mutex_unlock(&m->histogram.ext->mutex); + debug(D_STATSD, "STATSD %s metric %s: min " COLLECTED_NUMBER_FORMAT ", max " COLLECTED_NUMBER_FORMAT ", last " COLLECTED_NUMBER_FORMAT ", pcent " COLLECTED_NUMBER_FORMAT ", median " COLLECTED_NUMBER_FORMAT ", stddev " COLLECTED_NUMBER_FORMAT ", sum " COLLECTED_NUMBER_FORMAT, dim, m->name, m->histogram.ext->last_min, m->histogram.ext->last_max, m->last, m->histogram.ext->last_percentile, m->histogram.ext->last_median, m->histogram.ext->last_stddev, m->histogram.ext->last_sum); @@ -1745,11 +1742,24 @@ static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char m->reset = 1; updated = 1; } + else if(unlikely(!m->histogram.ext->zeroed)) { + // reset the metrics + // if we collected anything, they will be updated below + // this ensures that we report zeros if nothing is collected - if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED))) - statsd_private_chart_timer_or_histogram(m, dim, family, units); + m->histogram.ext->last_min = 0; + m->histogram.ext->last_max = 0; + m->last = 0; + m->histogram.ext->last_median = 0; + m->histogram.ext->last_stddev = 0; + m->histogram.ext->last_sum = 0; + m->histogram.ext->last_percentile = 0; - netdata_mutex_unlock(&m->histogram.ext->mutex); + m->histogram.ext->zeroed = 1; + } + + if(unlikely(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))) + statsd_private_chart_timer_or_histogram(m, dim, family, units); } static inline void statsd_flush_timer(STATSD_METRIC *m) { @@ -1837,6 +1847,7 @@ static inline void link_metric_to_app_dimension(STATSD_APP *app, STATSD_METRIC * } chart->dimensions_linked_count++; + m->options |= STATSD_METRIC_OPTION_USED_IN_APPS; debug(D_STATSD, "metric '%s' of type %u linked with app '%s', chart '%s', dimension '%s', algorithm '%s'", m->name, m->type, app->name, chart->id, dim->name, rrd_algorithm_name(dim->algorithm)); } @@ -1980,7 +1991,7 @@ static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *ch , chart->context // context , chart->title // title , chart->units // units - , "statsd" // plugin + , PLUGIN_STATSD_NAME // plugin , chart->source // module , chart->priority // priority , statsd.update_every // update every @@ -2043,7 +2054,13 @@ const char *statsd_metric_type_string(STATSD_METRIC_TYPE type) { static inline void statsd_flush_index_metrics(STATSD_INDEX *index, void (*flush_metric)(STATSD_METRIC *)) { STATSD_METRIC *m; + + // find the useful metrics (incremental = each time we are called, we check the new metrics only) for(m = index->first; m ; m = m->next) { + // since we add new metrics at the beginning + // check for useful charts, until the point we last checked + if(unlikely(is_metric_checked(m))) break; + if(unlikely(!(m->options & STATSD_METRIC_OPTION_CHECKED_IN_APPS))) { log_access("NEW STATSD METRIC '%s': '%s'", statsd_metric_type_string(m->type), m->name); check_if_metric_is_for_app(index, m); @@ -2051,7 +2068,7 @@ static inline void statsd_flush_index_metrics(STATSD_INDEX *index, void (*flush_ } if(unlikely(!(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED))) { - if(statsd.private_charts >= statsd.max_private_charts_hard) { + if(unlikely(statsd.private_charts >= statsd.max_private_charts_hard)) { debug(D_STATSD, "STATSD: metric '%s' will not be charted, because the hard limit of the maximum number of charts has been reached.", m->name); info("STATSD: metric '%s' will not be charted, because the hard limit of the maximum number of charts (%zu) has been reached. Increase the number of charts by editing netdata.conf, [statsd] section.", m->name, statsd.max_private_charts); m->options &= ~STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED; @@ -2069,6 +2086,20 @@ static inline void statsd_flush_index_metrics(STATSD_INDEX *index, void (*flush_ m->options |= STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED; } + // mark it as checked + m->options |= STATSD_METRIC_OPTION_CHECKED; + + // check if it is used in charts + if((m->options & (STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED|STATSD_METRIC_OPTION_USED_IN_APPS)) && !(m->options & STATSD_METRIC_OPTION_USEFUL)) { + m->options |= STATSD_METRIC_OPTION_USEFUL; + index->useful++; + m->next_useful = index->first_useful; + index->first_useful = m; + } + } + + // flush all the useful metrics + for(m = index->first_useful; m ; m = m->next_useful) { flush_metric(m); } } @@ -2130,9 +2161,9 @@ void *statsd_main(void *ptr) { statsd.max_private_charts_hard = (size_t)config_get_number(CONFIG_SECTION_STATSD, "max private charts hard limit", (long long)statsd.max_private_charts * 5); statsd.private_charts_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_STATSD, "private charts memory mode", rrd_memory_mode_name(default_rrd_memory_mode))); statsd.private_charts_rrd_history_entries = (int)config_get_number(CONFIG_SECTION_STATSD, "private charts history", default_rrd_history_entries); - statsd.decimal_detail = (size_t)config_get_number(CONFIG_SECTION_STATSD, "decimal detail", (long long int)statsd.decimal_detail); + statsd.decimal_detail = (collected_number)config_get_number(CONFIG_SECTION_STATSD, "decimal detail", (long long int)statsd.decimal_detail); statsd.tcp_idle_timeout = (size_t) config_get_number(CONFIG_SECTION_STATSD, "disconnect idle tcp clients after seconds", (long long int)statsd.tcp_idle_timeout); - statsd.private_charts_hidden = (int)config_get_boolean(CONFIG_SECTION_STATSD, "private charts hidden", statsd.private_charts_hidden); + statsd.private_charts_hidden = (unsigned int)config_get_boolean(CONFIG_SECTION_STATSD, "private charts hidden", statsd.private_charts_hidden); statsd.histogram_percentile = (double)config_get_float(CONFIG_SECTION_STATSD, "histograms and timers percentile (percentThreshold)", statsd.histogram_percentile); if(isless(statsd.histogram_percentile, 0) || isgreater(statsd.histogram_percentile, 100)) { @@ -2186,11 +2217,7 @@ void *statsd_main(void *ptr) { #endif // read custom application definitions - { - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/statsd.d", netdata_configured_config_dir); - statsd_readdir(filename); - } + statsd_readdir(netdata_configured_user_config_dir, netdata_configured_stock_config_dir, "statsd.d"); // ---------------------------------------------------------------------------------------------------------------- // statsd setup @@ -2224,7 +2251,7 @@ void *statsd_main(void *ptr) { , NULL , "Metrics in the netdata statsd database" , "metrics" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132010 , statsd.update_every @@ -2237,6 +2264,27 @@ void *statsd_main(void *ptr) { 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); + 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); + RRDSET *st_events = rrdset_create_localhost( "netdata" , "statsd_events" @@ -2245,7 +2293,7 @@ void *statsd_main(void *ptr) { , NULL , "Events processed by the netdata statsd server" , "events/s" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132011 , statsd.update_every @@ -2268,7 +2316,7 @@ void *statsd_main(void *ptr) { , NULL , "Read operations made by the netdata statsd server" , "reads/s" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132012 , statsd.update_every @@ -2285,7 +2333,7 @@ void *statsd_main(void *ptr) { , NULL , "Bytes read by the netdata statsd server" , "kilobits/s" - , "netdata" + , PLUGIN_STATSD_NAME , "stats" , 132013 , statsd.update_every @@ -2302,7 +2350,7 @@ void *statsd_main(void *ptr) { , NULL , "Network packets processed by the netdata statsd server" , "packets/s" - , "netdata" + , PLUGIN_STATSD_NAME , "stats" , 132014 , statsd.update_every @@ -2319,7 +2367,7 @@ void *statsd_main(void *ptr) { , NULL , "statsd server TCP connects and disconnects" , "events" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132015 , statsd.update_every @@ -2336,7 +2384,7 @@ void *statsd_main(void *ptr) { , NULL , "statsd server TCP connected sockets" , "connected" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132016 , statsd.update_every @@ -2352,7 +2400,7 @@ void *statsd_main(void *ptr) { , NULL , "Private metric charts created by the netdata statsd server" , "charts" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132020 , statsd.update_every @@ -2368,7 +2416,7 @@ void *statsd_main(void *ptr) { , "netdata.statsd_cpu" , "NetData statsd charting thread CPU usage" , "milliseconds/s" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132001 , statsd.update_every @@ -2394,7 +2442,7 @@ void *statsd_main(void *ptr) { , "netdata.statsd_cpu" , title , "milliseconds/s" - , "statsd" + , PLUGIN_STATSD_NAME , "stats" , 132002 + i , statsd.update_every @@ -2430,6 +2478,7 @@ void *statsd_main(void *ptr) { 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); @@ -2450,6 +2499,14 @@ void *statsd_main(void *ptr) { rrddim_set_by_pointer(st_metrics, rd_metrics_set, (collected_number)statsd.sets.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); + 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); diff --git a/src/plugin_tc.c b/collectors/tc.plugin/plugin_tc.c index 4b6d84e1..083cc298 100644 --- a/src/plugin_tc.c +++ b/collectors/tc.plugin/plugin_tc.c @@ -1,6 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_tc.h" #define RRD_TYPE_TC "tc" +#define PLUGIN_TC_NAME "tc.plugin" // ---------------------------------------------------------------------------- // /sbin/tc processor @@ -391,9 +394,9 @@ static inline void tc_device_commit(struct tc_device *d) { , RRD_TYPE_TC ".qos" , "Class Usage" , "kilobits/s" - , "tc" + , PLUGIN_TC_NAME , NULL - , 7000 + , NETDATA_CHART_PRIO_TC_QOS , localhost->rrd_update_every , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED ); @@ -402,7 +405,7 @@ static inline void tc_device_commit(struct tc_device *d) { rrdset_next(d->st_bytes); if(unlikely(d->name_updated)) rrdset_set_name(d->st_bytes, d->name); - // FIXME + // TODO // update the family } @@ -439,9 +442,9 @@ static inline void tc_device_commit(struct tc_device *d) { , RRD_TYPE_TC ".qos_packets" , "Class Packets" , "packets/s" - , "tc" + , PLUGIN_TC_NAME , NULL - , 7010 + , NETDATA_CHART_PRIO_TC_QOS_PACKETS , localhost->rrd_update_every , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED ); @@ -455,7 +458,7 @@ static inline void tc_device_commit(struct tc_device *d) { rrdset_set_name(d->st_packets, name); } - // FIXME + // TODO // update the family } @@ -492,9 +495,9 @@ static inline void tc_device_commit(struct tc_device *d) { , RRD_TYPE_TC ".qos_dropped" , "Class Dropped Packets" , "packets/s" - , "tc" + , PLUGIN_TC_NAME , NULL - , 7020 + , NETDATA_CHART_PRIO_TC_QOS_DROPPED , localhost->rrd_update_every , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED ); @@ -508,7 +511,7 @@ static inline void tc_device_commit(struct tc_device *d) { rrdset_set_name(d->st_dropped, name); } - // FIXME + // TODO // update the family } @@ -545,9 +548,9 @@ static inline void tc_device_commit(struct tc_device *d) { , RRD_TYPE_TC ".qos_tokens" , "Class Tokens" , "tokens" - , "tc" + , PLUGIN_TC_NAME , NULL - , 7030 + , NETDATA_CHART_PRIO_TC_QOS_TOCKENS , localhost->rrd_update_every , RRDSET_TYPE_LINE ); @@ -561,7 +564,7 @@ static inline void tc_device_commit(struct tc_device *d) { rrdset_set_name(d->st_tokens, name); } - // FIXME + // TODO // update the family } @@ -599,9 +602,9 @@ static inline void tc_device_commit(struct tc_device *d) { , RRD_TYPE_TC ".qos_ctokens" , "Class cTokens" , "ctokens" - , "tc" + , PLUGIN_TC_NAME , NULL - , 7040 + , NETDATA_CHART_PRIO_TC_QOS_CTOCKENS , localhost->rrd_update_every , RRDSET_TYPE_LINE ); @@ -616,7 +619,7 @@ static inline void tc_device_commit(struct tc_device *d) { rrdset_set_name(d->st_ctokens, name); } - // FIXME + // TODO // update the family } @@ -857,7 +860,7 @@ void *tc_main(void *ptr) { struct rusage thread; - char buffer[TC_LINE_MAX+1] = ""; + char command[FILENAME_MAX + 1]; char *words[PLUGINSD_MAX_WORDS] = { NULL }; uint32_t BEGIN_HASH = simple_hash("BEGIN"); @@ -876,23 +879,24 @@ void *tc_main(void *ptr) { #endif uint32_t first_hash; - snprintfz(buffer, TC_LINE_MAX, "%s/tc-qos-helper.sh", netdata_configured_plugins_dir); - char *tc_script = config_get("plugin:tc", "script to run to get tc values", buffer); + snprintfz(command, TC_LINE_MAX, "%s/tc-qos-helper.sh", netdata_configured_plugins_dir); + char *tc_script = config_get("plugin:tc", "script to run to get tc values", command); while(!netdata_exit) { FILE *fp; struct tc_device *device = NULL; struct tc_class *class = NULL; - snprintfz(buffer, TC_LINE_MAX, "exec %s %d", tc_script, localhost->rrd_update_every); - debug(D_TC_LOOP, "executing '%s'", buffer); + snprintfz(command, TC_LINE_MAX, "exec %s %d", tc_script, localhost->rrd_update_every); + debug(D_TC_LOOP, "executing '%s'", command); - fp = mypopen(buffer, (pid_t *)&tc_child_pid); + fp = mypopen(command, (pid_t *)&tc_child_pid); if(unlikely(!fp)) { - error("TC: Cannot popen(\"%s\", \"r\").", buffer); + error("TC: Cannot popen(\"%s\", \"r\").", command); goto cleanup; } + char buffer[TC_LINE_MAX+1] = ""; while(fgets(buffer, TC_LINE_MAX, fp) != NULL) { if(unlikely(netdata_exit)) break; @@ -1074,9 +1078,9 @@ void *tc_main(void *ptr) { , NULL , "NetData TC CPU usage" , "milliseconds/s" - , "tc" + , PLUGIN_TC_NAME , NULL - , 135000 + , NETDATA_CHART_PRIO_NETDATA_TC_CPU , localhost->rrd_update_every , RRDSET_TYPE_STACKED ); @@ -1101,9 +1105,9 @@ void *tc_main(void *ptr) { , NULL , "NetData TC script execution" , "milliseconds/run" - , "tc" + , PLUGIN_TC_NAME , NULL - , 135001 + , NETDATA_CHART_PRIO_NETDATA_TC_TIME , localhost->rrd_update_every , RRDSET_TYPE_AREA ); diff --git a/src/daemon.c b/daemon/daemon.c index 471c62c6..4ad082b9 100644 --- a/src/daemon.c +++ b/daemon/daemon.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #include "common.h" #include <sched.h> @@ -151,6 +153,10 @@ static void oom_score_adj(void) { s = config_get(CONFIG_SECTION_GLOBAL, "OOM score", s); if(s && *s && (isdigit(*s) || *s == '-' || *s == '+')) wanted_score = atoll(s); + else if(s && !strcmp(s, "keep")) { + info("Out-Of-Memory (OOM) kept as-is (running with %d)", (int) old_score); + return; + } else { info("Out-Of-Memory (OOM) score not changed due to non-numeric setting: '%s' (running with %d)", s, (int)old_score); return; @@ -202,8 +208,6 @@ static void process_nice_level(void) { #endif // HAVE_NICE }; -#ifdef HAVE_SCHED_SETSCHEDULER - #define SCHED_FLAG_NONE 0x00 #define SCHED_FLAG_PRIORITY_CONFIGURABLE 0x01 // the priority is user configurable #define SCHED_FLAG_KEEP_AS_IS 0x04 // do not attempt to set policy, priority or nice() @@ -227,8 +231,8 @@ struct sched_def { #endif #ifdef SCHED_OTHER - { "nice", SCHED_OTHER, 0, SCHED_FLAG_USE_NICE }, { "other", SCHED_OTHER, 0, SCHED_FLAG_USE_NICE }, + { "nice", SCHED_OTHER, 0, SCHED_FLAG_USE_NICE }, #endif #ifdef SCHED_RR @@ -251,6 +255,55 @@ struct sched_def { { NULL, 0, 0, 0 } }; + +#ifdef HAVE_SCHED_GETSCHEDULER +static void sched_getscheduler_report(void) { + int sched = sched_getscheduler(0); + if(sched == -1) { + error("Cannot get my current process scheduling policy."); + return; + } + else { + int i; + for(i = 0 ; scheduler_defaults[i].name ; i++) { + if(scheduler_defaults[i].policy == sched) { + if(scheduler_defaults[i].flags & SCHED_FLAG_PRIORITY_CONFIGURABLE) { + struct sched_param param; + if(sched_getparam(0, ¶m) == -1) { + error("Cannot get the process scheduling priority for my policy '%s'", scheduler_defaults[i].name); + return; + } + else { + info("Running with process scheduling policy '%s', priority %d", scheduler_defaults[i].name, param.sched_priority); + } + } + else if(scheduler_defaults[i].flags & SCHED_FLAG_USE_NICE) { + #ifdef HAVE_GETPRIORITY + int n = getpriority(PRIO_PROCESS, 0); + info("Running with process scheduling policy '%s', nice level %d", scheduler_defaults[i].name, n); + #else // !HAVE_GETPRIORITY + info("Running with process scheduling policy '%s'", scheduler_defaults[i].name); + #endif // !HAVE_GETPRIORITY + } + else { + info("Running with process scheduling policy '%s'", scheduler_defaults[i].name); + } + + return; + } + } + } +} +#else // !HAVE_SCHED_GETSCHEDULER +static void sched_getscheduler_report(void) { +#ifdef HAVE_GETPRIORITY + info("Running with priority %d", getpriority(PRIO_PROCESS, 0)); +#endif // HAVE_GETPRIORITY +} +#endif // !HAVE_SCHED_GETSCHEDULER + +#ifdef HAVE_SCHED_SETSCHEDULER + static void sched_setscheduler_set(void) { if(scheduler_defaults[0].name) { @@ -270,7 +323,7 @@ static void sched_setscheduler_set(void) { flags = scheduler_defaults[i].flags; if(flags & SCHED_FLAG_KEEP_AS_IS) - return; + goto report; if(flags & SCHED_FLAG_PRIORITY_CONFIGURABLE) priority = (int)config_get_number(CONFIG_SECTION_GLOBAL, "process scheduling priority", priority); @@ -310,18 +363,21 @@ static void sched_setscheduler_set(void) { else { info("Adjusted netdata scheduling policy to %s (%d), with priority %d.", name, policy, priority); if(!(flags & SCHED_FLAG_USE_NICE)) - return; + goto report; } } fallback: process_nice_level(); + +report: + sched_getscheduler_report(); } -#else +#else // !HAVE_SCHED_SETSCHEDULER static void sched_setscheduler_set(void) { process_nice_level(); } -#endif +#endif // !HAVE_SCHED_SETSCHEDULER int become_daemon(int dont_fork, const char *user) { diff --git a/src/daemon.h b/daemon/daemon.h index 150d74e3..41269110 100644 --- a/src/daemon.h +++ b/daemon/daemon.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_DAEMON_H #define NETDATA_DAEMON_H 1 diff --git a/src/global_statistics.c b/daemon/global_statistics.c index 4f34e92d..68933e19 100644 --- a/src/global_statistics.c +++ b/daemon/global_statistics.c @@ -1,6 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #include "common.h" -volatile struct global_statistics global_statistics = { +#define GLOBAL_STATS_RESET_WEB_USEC_MAX 0x01 + + +static struct global_statistics { + volatile uint16_t connected_clients; + + volatile uint64_t web_requests; + volatile uint64_t web_usec; + volatile uint64_t web_usec_max; + volatile uint64_t bytes_received; + volatile uint64_t bytes_sent; + volatile uint64_t content_size; + volatile uint64_t compressed_content_size; + + volatile uint64_t web_client_count; + + volatile uint64_t rrdr_queries_made; + volatile uint64_t rrdr_db_points_read; + volatile uint64_t rrdr_result_points_generated; +} global_statistics = { .connected_clients = 0, .web_requests = 0, .web_usec = 0, @@ -8,18 +29,45 @@ volatile struct global_statistics global_statistics = { .bytes_sent = 0, .content_size = 0, .compressed_content_size = 0, - .web_client_count = 1 + .web_client_count = 1, + + .rrdr_queries_made = 0, + .rrdr_db_points_read = 0, + .rrdr_result_points_generated = 0, }; +#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) +#else netdata_mutex_t global_statistics_mutex = NETDATA_MUTEX_INITIALIZER; -inline void global_statistics_lock(void) { +static inline void global_statistics_lock(void) { netdata_mutex_lock(&global_statistics_mutex); } -inline void global_statistics_unlock(void) { +static inline void global_statistics_unlock(void) { netdata_mutex_unlock(&global_statistics_mutex); } +#endif + + +void rrdr_query_completed(uint64_t db_points_read, uint64_t result_points_generated) { +#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) + __atomic_fetch_add(&global_statistics.rrdr_queries_made, 1, __ATOMIC_SEQ_CST); + __atomic_fetch_add(&global_statistics.rrdr_db_points_read, db_points_read, __ATOMIC_SEQ_CST); + __atomic_fetch_add(&global_statistics.rrdr_result_points_generated, result_points_generated, __ATOMIC_SEQ_CST); +#else + #warning NOT using atomic operations - using locks for global statistics + if (web_server_is_multithreaded) + global_statistics_lock(); + + global_statistics.rrdr_queries_made++; + global_statistics.rrdr_db_points_read += db_points_read; + global_statistics.rrdr_result_points_generated += result_points_generated; + + if (web_server_is_multithreaded) + global_statistics_unlock(); +#endif +} void finished_web_request_statistics(uint64_t dt, uint64_t bytes_received, @@ -90,17 +138,21 @@ void web_client_disconnected(void) { } -inline void global_statistics_copy(struct global_statistics *gs, uint8_t options) { +static inline void global_statistics_copy(struct global_statistics *gs, uint8_t options) { #if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) - gs->connected_clients = __atomic_fetch_add(&global_statistics.connected_clients, 0, __ATOMIC_SEQ_CST); - gs->web_requests = __atomic_fetch_add(&global_statistics.web_requests, 0, __ATOMIC_SEQ_CST); - gs->web_usec = __atomic_fetch_add(&global_statistics.web_usec, 0, __ATOMIC_SEQ_CST); - gs->web_usec_max = __atomic_fetch_add(&global_statistics.web_usec_max, 0, __ATOMIC_SEQ_CST); - gs->bytes_received = __atomic_fetch_add(&global_statistics.bytes_received, 0, __ATOMIC_SEQ_CST); - gs->bytes_sent = __atomic_fetch_add(&global_statistics.bytes_sent, 0, __ATOMIC_SEQ_CST); - gs->content_size = __atomic_fetch_add(&global_statistics.content_size, 0, __ATOMIC_SEQ_CST); - gs->compressed_content_size = __atomic_fetch_add(&global_statistics.compressed_content_size, 0, __ATOMIC_SEQ_CST); - gs->web_client_count = __atomic_fetch_add(&global_statistics.web_client_count, 0, __ATOMIC_SEQ_CST); + gs->connected_clients = __atomic_fetch_add(&global_statistics.connected_clients, 0, __ATOMIC_SEQ_CST); + gs->web_requests = __atomic_fetch_add(&global_statistics.web_requests, 0, __ATOMIC_SEQ_CST); + gs->web_usec = __atomic_fetch_add(&global_statistics.web_usec, 0, __ATOMIC_SEQ_CST); + gs->web_usec_max = __atomic_fetch_add(&global_statistics.web_usec_max, 0, __ATOMIC_SEQ_CST); + gs->bytes_received = __atomic_fetch_add(&global_statistics.bytes_received, 0, __ATOMIC_SEQ_CST); + gs->bytes_sent = __atomic_fetch_add(&global_statistics.bytes_sent, 0, __ATOMIC_SEQ_CST); + gs->content_size = __atomic_fetch_add(&global_statistics.content_size, 0, __ATOMIC_SEQ_CST); + gs->compressed_content_size = __atomic_fetch_add(&global_statistics.compressed_content_size, 0, __ATOMIC_SEQ_CST); + gs->web_client_count = __atomic_fetch_add(&global_statistics.web_client_count, 0, __ATOMIC_SEQ_CST); + + gs->rrdr_queries_made = __atomic_fetch_add(&global_statistics.rrdr_queries_made, 0, __ATOMIC_SEQ_CST); + gs->rrdr_db_points_read = __atomic_fetch_add(&global_statistics.rrdr_db_points_read, 0, __ATOMIC_SEQ_CST); + gs->rrdr_result_points_generated = __atomic_fetch_add(&global_statistics.rrdr_result_points_generated, 0, __ATOMIC_SEQ_CST); if(options & GLOBAL_STATS_RESET_WEB_USEC_MAX) { uint64_t n = 0; @@ -411,4 +463,71 @@ void global_statistics_charts(void) { rrdset_done(st_compression); } + + // ---------------------------------------------------------------- + + if(gs.rrdr_queries_made) { + static RRDSET *st_rrdr_queries = NULL; + static RRDDIM *rd_queries = NULL; + + if (unlikely(!st_rrdr_queries)) { + st_rrdr_queries = rrdset_create_localhost( + "netdata" + , "queries" + , NULL + , "queries" + , NULL + , "NetData API Queries" + , "queries/s" + , "netdata" + , "stats" + , 130500 + , localhost->rrd_update_every + , RRDSET_TYPE_LINE + ); + + rd_queries = rrddim_add(st_rrdr_queries, "queries", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_rrdr_queries); + + rrddim_set_by_pointer(st_rrdr_queries, rd_queries, (collected_number)gs.rrdr_queries_made); + + rrdset_done(st_rrdr_queries); + } + + // ---------------------------------------------------------------- + + if(gs.rrdr_db_points_read || gs.rrdr_result_points_generated) { + static RRDSET *st_rrdr_points = NULL; + static RRDDIM *rd_points_read = NULL; + static RRDDIM *rd_points_generated = NULL; + + if (unlikely(!st_rrdr_points)) { + st_rrdr_points = rrdset_create_localhost( + "netdata" + , "db_points" + , NULL + , "queries" + , NULL + , "NetData API Points" + , "points/s" + , "netdata" + , "stats" + , 130501 + , localhost->rrd_update_every + , RRDSET_TYPE_AREA + ); + + rd_points_read = rrddim_add(st_rrdr_points, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rd_points_generated = rrddim_add(st_rrdr_points, "generated", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st_rrdr_points); + + rrddim_set_by_pointer(st_rrdr_points, rd_points_read, (collected_number)gs.rrdr_db_points_read); + rrddim_set_by_pointer(st_rrdr_points, rd_points_generated, (collected_number)gs.rrdr_result_points_generated); + + rrdset_done(st_rrdr_points); + } } diff --git a/src/global_statistics.h b/daemon/global_statistics.h index 62fee6e3..9dd7db51 100644 --- a/src/global_statistics.h +++ b/daemon/global_statistics.h @@ -1,27 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_GLOBAL_STATISTICS_H #define NETDATA_GLOBAL_STATISTICS_H 1 +#include "common.h" + // ---------------------------------------------------------------------------- // global statistics -struct global_statistics { - volatile uint16_t connected_clients; - - volatile uint64_t web_requests; - volatile uint64_t web_usec; - volatile uint64_t web_usec_max; - volatile uint64_t bytes_received; - volatile uint64_t bytes_sent; - volatile uint64_t content_size; - volatile uint64_t compressed_content_size; +extern void rrdr_query_completed(uint64_t db_points_read, uint64_t result_points_generated); - volatile uint64_t web_client_count; -}; - -extern volatile struct global_statistics global_statistics; - -extern void global_statistics_lock(void); -extern void global_statistics_unlock(void); extern void finished_web_request_statistics(uint64_t dt, uint64_t bytes_received, uint64_t bytes_sent, @@ -30,9 +18,6 @@ extern void finished_web_request_statistics(uint64_t dt, extern uint64_t web_client_connected(void); extern void web_client_disconnected(void); - -#define GLOBAL_STATS_RESET_WEB_USEC_MAX 0x01 -extern void global_statistics_copy(struct global_statistics *gs, uint8_t options); extern void global_statistics_charts(void); #endif /* NETDATA_GLOBAL_STATISTICS_H */ diff --git a/src/main.c b/daemon/main.c index 798c7f0f..b2c4c80b 100644 --- a/src/main.c +++ b/daemon/main.c @@ -1,6 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #include "common.h" -extern void *cgroups_main(void *ptr); +struct config netdata_config = { + .sections = NULL, + .mutex = NETDATA_MUTEX_INITIALIZER, + .index = { + .avl_tree = { + .root = NULL, + .compar = appconfig_section_compare + }, + .rwlock = AVL_LOCK_INITIALIZER + } +}; void netdata_cleanup_and_exit(int ret) { // enabling this, is wrong @@ -39,43 +51,31 @@ void netdata_cleanup_and_exit(int ret) { struct netdata_static_thread static_threads[] = { -#ifdef INTERNAL_PLUGIN_NFACCT - // nfacct requires root access - // so, we build it as an external plugin with setuid to root - {"PLUGIN[nfacct]", CONFIG_SECTION_PLUGINS, "nfacct", 1, NULL, NULL, nfacct_main}, -#endif - -#ifdef NETDATA_INTERNAL_CHECKS - // debugging plugin - {"PLUGIN[check]", CONFIG_SECTION_PLUGINS, "checks", 0, NULL, NULL, checks_main}, -#endif + NETDATA_PLUGIN_HOOK_CHECKS + NETDATA_PLUGIN_HOOK_FREEBSD + NETDATA_PLUGIN_HOOK_MACOS -#if defined(__FreeBSD__) - // FreeBSD internal plugins - {"PLUGIN[freebsd]", CONFIG_SECTION_PLUGINS, "freebsd", 1, NULL, NULL, freebsd_main}, -#elif defined(__APPLE__) - // macOS internal plugins - {"PLUGIN[macos]", CONFIG_SECTION_PLUGINS, "macos", 1, NULL, NULL, macos_main}, -#else // linux internal plugins - {"PLUGIN[proc]", CONFIG_SECTION_PLUGINS, "proc", 1, NULL, NULL, proc_main}, - {"PLUGIN[diskspace]", CONFIG_SECTION_PLUGINS, "diskspace", 1, NULL, NULL, proc_diskspace_main}, - {"PLUGIN[cgroup]", CONFIG_SECTION_PLUGINS, "cgroups", 1, NULL, NULL, cgroups_main}, - {"PLUGIN[tc]", CONFIG_SECTION_PLUGINS, "tc", 1, NULL, NULL, tc_main}, -#endif /* __FreeBSD__, __APPLE__*/ - - // common plugins for all systems - {"PLUGIN[idlejitter]", CONFIG_SECTION_PLUGINS, "idlejitter", 1, NULL, NULL, cpuidlejitter_main}, - {"BACKENDS", NULL, NULL, 1, NULL, NULL, backends_main}, - {"HEALTH", NULL, NULL, 1, NULL, NULL, health_main}, - {"PLUGINSD", NULL, NULL, 1, NULL, NULL, pluginsd_main}, - {"WEB_SERVER[multi]", NULL, NULL, 1, NULL, NULL, socket_listen_main_multi_threaded}, - {"WEB_SERVER[single]", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded}, - {"WEB_SERVER[static1]", NULL, NULL, 0, NULL, NULL, socket_listen_main_static_threaded}, - {"STREAM", NULL, NULL, 0, NULL, NULL, rrdpush_sender_thread}, - {"STATSD", NULL, NULL, 1, NULL, NULL, statsd_main}, - - {NULL, NULL, NULL, 0, NULL, NULL, NULL} + NETDATA_PLUGIN_HOOK_LINUX_NFACCT + NETDATA_PLUGIN_HOOK_LINUX_PROC + NETDATA_PLUGIN_HOOK_LINUX_DISKSPACE + NETDATA_PLUGIN_HOOK_LINUX_CGROUPS + NETDATA_PLUGIN_HOOK_LINUX_TC + + NETDATA_PLUGIN_HOOK_IDLEJITTER + NETDATA_PLUGIN_HOOK_STATSD + + // common plugins for all systems + {"BACKENDS", NULL, NULL, 1, NULL, NULL, backends_main}, + {"WEB_SERVER[multi]", NULL, NULL, 1, NULL, NULL, socket_listen_main_multi_threaded}, + {"WEB_SERVER[single]", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded}, + {"WEB_SERVER[static1]", NULL, NULL, 0, NULL, NULL, socket_listen_main_static_threaded}, + {"STREAM", NULL, NULL, 0, NULL, NULL, rrdpush_sender_thread}, + + NETDATA_PLUGIN_HOOK_PLUGINSD + NETDATA_PLUGIN_HOOK_HEALTH + + {NULL, NULL, NULL, 0, NULL, NULL, NULL} }; void web_server_threading_selection(void) { @@ -101,6 +101,7 @@ void web_server_threading_selection(void) { void web_server_config_options(void) { web_client_timeout = (int) config_get_number(CONFIG_SECTION_WEB, "disconnect idle clients after seconds", web_client_timeout); web_client_first_request_timeout = (int) config_get_number(CONFIG_SECTION_WEB, "timeout for first request", web_client_first_request_timeout); + web_client_streaming_rate_t = config_get_number(CONFIG_SECTION_WEB, "accept a streaming request every seconds", web_client_streaming_rate_t); respect_web_browser_do_not_track_policy = config_get_boolean(CONFIG_SECTION_WEB, "respect do not track policy", respect_web_browser_do_not_track_policy); web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", ""); @@ -145,7 +146,7 @@ void web_server_config_options(void) { } -int killpid(pid_t pid, int sig) +int killpid(pid_t pid, int signal) { int ret = -1; debug(D_EXIT, "Request to kill pid %d", pid); @@ -168,7 +169,7 @@ int killpid(pid_t pid, int sig) } else { errno = 0; - ret = kill(pid, sig); + ret = kill(pid, signal); if(ret == -1) { switch(errno) { case ESRCH: @@ -192,7 +193,8 @@ int killpid(pid_t pid, int sig) void cancel_main_threads() { error_log_limit_unlimited(); - int i, found = 0, max = 5 * USEC_PER_SEC, step = 100000; + int i, found = 0; + usec_t max = 5 * USEC_PER_SEC, step = 100000; for (i = 0; static_threads[i].name != NULL ; i++) { if(static_threads[i].enabled == NETDATA_MAIN_THREAD_RUNNING) { info("EXIT: Stopping master thread: %s", static_threads[i].name); @@ -226,6 +228,7 @@ struct option_def option_definitions[] = { // opt description arg name default value { 'c', "Configuration file to load.", "filename", CONFIG_DIR "/" CONFIG_FILENAME}, { 'D', "Do not fork. Run in the foreground.", NULL, "run in the background"}, + { 'd', "Fork. Run in the background.", NULL, "run in the background"}, { 'h', "Display this help message.", NULL, NULL}, { 'P', "File to save a pid while running.", "filename", "do not save pid to a file"}, { 'i', "The IP address to listen to.", "IP", "all IP addresses IPv4 and IPv6"}, @@ -271,16 +274,14 @@ int help(int exitcode) { " All rights reserved.\n" "\n" " Home Page : https://my-netdata.io\n" - " Source Code: https://github.com/firehol/netdata\n" - " Wiki / Docs: https://github.com/firehol/netdata/wiki\n" - " Support : https://github.com/firehol/netdata/issues\n" - " License : https://github.com/firehol/netdata/blob/master/LICENSE.md\n" + " Source Code: https://github.com/netdata/netdata\n" + " Wiki / Docs: https://github.com/netdata/netdata/wiki\n" + " Support : https://github.com/netdata/netdata/issues\n" + " License : https://github.com/netdata/netdata/blob/master/LICENSE.md\n" "\n" " Twitter : https://twitter.com/linuxnetdata\n" " Facebook : https://www.facebook.com/linuxnetdata/\n" "\n" - " netdata is a https://firehol.org project.\n" - "\n" "\n" ); @@ -322,7 +323,8 @@ int help(int exitcode) { // TODO: Remove this function with the nix major release. void remove_option(int opt_index, int *argc, char **argv) { - int i = opt_index; + int i; + // remove the options. do { *argc = *argc - 1; @@ -356,9 +358,9 @@ void log_init(void) { snprintfz(filename, FILENAME_MAX, "%s/access.log", netdata_configured_log_dir); stdaccess_filename = config_get(CONFIG_SECTION_GLOBAL, "access log", filename); - error_log_throttle_period_backup = error_log_throttle_period = config_get_number(CONFIG_SECTION_GLOBAL, "errors flood protection period", error_log_throttle_period); error_log_errors_per_period = (unsigned long)config_get_number(CONFIG_SECTION_GLOBAL, "errors to trigger flood protection", (long long int)error_log_errors_per_period); + error_log_errors_per_period_backup = error_log_errors_per_period; setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get(CONFIG_SECTION_GLOBAL, "errors flood protection period" , ""), 1); setenv("NETDATA_ERRORS_PER_PERIOD", config_get(CONFIG_SECTION_GLOBAL, "errors to trigger flood protection", ""), 1); @@ -457,12 +459,13 @@ static void get_netdata_configured_variables() { // ------------------------------------------------------------------------ // get system paths - netdata_configured_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", CONFIG_DIR); - netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", LOG_DIR); - netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR); - netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", CACHE_DIR); - netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", VARLIB_DIR); - netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", CACHE_DIR); + netdata_configured_user_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", netdata_configured_user_config_dir); + netdata_configured_stock_config_dir = config_get(CONFIG_SECTION_GLOBAL, "stock config directory", netdata_configured_stock_config_dir); + netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", netdata_configured_log_dir); + netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", netdata_configured_web_dir); + netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", netdata_configured_cache_dir); + netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", netdata_configured_varlib_dir); + netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", netdata_configured_home_dir); { char plugins_dirs[(FILENAME_MAX * 2) + 1]; @@ -480,6 +483,7 @@ static void get_netdata_configured_variables() { // ------------------------------------------------------------------------ netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", ""); + verify_netdata_host_prefix(); // -------------------------------------------------------------------- // get KSM settings @@ -592,15 +596,17 @@ void set_global_environment() { setenv("NETDATA_UPDATE_EVERY", b, 1); } - setenv("NETDATA_HOSTNAME" , netdata_configured_hostname, 1); - setenv("NETDATA_CONFIG_DIR" , verify_required_directory(netdata_configured_config_dir), 1); - setenv("NETDATA_PLUGINS_DIR", verify_required_directory(netdata_configured_plugins_dir), 1); - setenv("NETDATA_WEB_DIR" , verify_required_directory(netdata_configured_web_dir), 1); - setenv("NETDATA_CACHE_DIR" , verify_required_directory(netdata_configured_cache_dir), 1); - setenv("NETDATA_LIB_DIR" , verify_required_directory(netdata_configured_varlib_dir), 1); - setenv("NETDATA_LOG_DIR" , verify_required_directory(netdata_configured_log_dir), 1); - setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1); - setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1); + setenv("NETDATA_HOSTNAME" , netdata_configured_hostname, 1); + setenv("NETDATA_CONFIG_DIR" , verify_required_directory(netdata_configured_user_config_dir), 1); + setenv("NETDATA_USER_CONFIG_DIR" , verify_required_directory(netdata_configured_user_config_dir), 1); + setenv("NETDATA_STOCK_CONFIG_DIR" , verify_required_directory(netdata_configured_stock_config_dir), 1); + setenv("NETDATA_PLUGINS_DIR" , verify_required_directory(netdata_configured_plugins_dir), 1); + setenv("NETDATA_WEB_DIR" , verify_required_directory(netdata_configured_web_dir), 1); + setenv("NETDATA_CACHE_DIR" , verify_required_directory(netdata_configured_cache_dir), 1); + setenv("NETDATA_LIB_DIR" , verify_required_directory(netdata_configured_varlib_dir), 1); + setenv("NETDATA_LOG_DIR" , verify_required_directory(netdata_configured_log_dir), 1); + setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1); + setenv("NETDATA_HOST_PREFIX" , netdata_configured_host_prefix, 1); get_system_timezone(); @@ -622,6 +628,36 @@ void set_global_environment() { setenv("LC_ALL", "C", 1); } +static int load_netdata_conf(char *filename, char overwrite_used) { + errno = 0; + + int ret = 0; + + if(filename && *filename) { + ret = config_load(filename, overwrite_used); + if(!ret) + error("CONFIG: cannot load config file '%s'.", filename); + } + else { + filename = strdupz_path_subpath(netdata_configured_user_config_dir, "netdata.conf"); + + ret = config_load(filename, overwrite_used); + if(!ret) { + info("CONFIG: cannot load user config '%s'. Will try the stock version.", filename); + freez(filename); + + filename = strdupz_path_subpath(netdata_configured_stock_config_dir, "netdata.conf"); + ret = config_load(filename, overwrite_used); + if(!ret) + info("CONFIG: cannot load stock config '%s'. Running with internal defaults.", filename); + } + + freez(filename); + } + + return ret; +} + int main(int argc, char **argv) { int i; int config_loaded = 0; @@ -682,7 +718,7 @@ int main(int argc, char **argv) { while( (opt = getopt(argc, argv, optstring)) != -1 ) { switch(opt) { case 'c': - if(config_load(optarg, 1) != 1) { + if(load_netdata_conf(optarg, 1) != 1) { error("Cannot load configuration file %s.", optarg); return 1; } @@ -694,6 +730,9 @@ int main(int argc, char **argv) { case 'D': dont_fork = 1; break; + case 'd': + dont_fork = 0; + break; case 'h': return help(0); case 'i': @@ -727,9 +766,6 @@ int main(int argc, char **argv) { if(strcmp(optarg, "unittest") == 0) { if(unit_test_buffer()) return 1; if(unit_test_str2ld()) return 1; - //default_rrd_update_every = 1; - //default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; - //if(!config_loaded) config_load(NULL, 0); get_netdata_configured_variables(); default_rrd_update_every = 1; default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; @@ -837,7 +873,7 @@ int main(int argc, char **argv) { if(!config_loaded) { fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n"); - config_load(NULL, 0); + load_netdata_conf(NULL, 0); } backwards_compatible_config(); @@ -875,7 +911,7 @@ int main(int argc, char **argv) { #endif if(!config_loaded) - config_load(NULL, 0); + load_netdata_conf(NULL, 0); // ------------------------------------------------------------------------ // initialize netdata @@ -898,8 +934,8 @@ int main(int argc, char **argv) { // work while we are cd into config_dir // to allow the plugins refer to their config // files using relative filenames - if(chdir(netdata_configured_config_dir) == -1) - fatal("Cannot cd to '%s'", netdata_configured_config_dir); + if(chdir(netdata_configured_user_config_dir) == -1) + fatal("Cannot cd to '%s'", netdata_configured_user_config_dir); } char *user = NULL; @@ -933,15 +969,6 @@ int main(int argc, char **argv) { // -------------------------------------------------------------------- - // load stream.conf - { - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/stream.conf", netdata_configured_config_dir); - appconfig_load(&stream_config, filename, 0); - } - - - // -------------------------------------------------------------------- // setup process signals // block signals while initializing threads. @@ -1009,7 +1036,7 @@ int main(int argc, char **argv) { if(getrlimit(RLIMIT_NOFILE, &rlimit_nofile) != 0) error("getrlimit(RLIMIT_NOFILE) failed"); else - info("resources control: allowed file descriptors: soft = %zu, max = %zu", rlimit_nofile.rlim_cur, rlimit_nofile.rlim_max); + info("resources control: allowed file descriptors: soft = %zu, max = %zu", (size_t)rlimit_nofile.rlim_cur, (size_t)rlimit_nofile.rlim_max); // fork, switch user, create pid file, set process priority if(become_daemon(dont_fork, user) == -1) diff --git a/src/main.h b/daemon/main.h index d29bf74e..cb0bde6a 100644 --- a/src/main.h +++ b/daemon/main.h @@ -1,6 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_MAIN_H #define NETDATA_MAIN_H 1 +#include "common.h" + +extern struct config netdata_config; + #define NETDATA_MAIN_THREAD_RUNNING CONFIG_BOOLEAN_YES #define NETDATA_MAIN_THREAD_EXITING (CONFIG_BOOLEAN_YES + 1) #define NETDATA_MAIN_THREAD_EXITED CONFIG_BOOLEAN_NO @@ -21,17 +27,17 @@ struct option_def { }; struct netdata_static_thread { - char *name; + char *name; // the name of the thread as it should appear in the logs - char *config_section; - char *config_name; + char *config_section; // the section of netdata.conf to check if this is enabled or not + char *config_name; // the name of the config option to check if it is true or false - volatile sig_atomic_t enabled; + volatile sig_atomic_t enabled; // the current status of the thread - netdata_thread_t *thread; + netdata_thread_t *thread; // internal use, to maintain a pointer to the created thread - void (*init_routine) (void); - void *(*start_routine) (void *); + void (*init_routine) (void); // an initialization function to run before spawning the thread + void *(*start_routine) (void *); // the threaded worker }; extern void cancel_main_threads(void); diff --git a/src/signals.c b/daemon/signals.c index 331e8035..71f27188 100644 --- a/src/signals.c +++ b/daemon/signals.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #include "common.h" typedef enum signal_action { @@ -147,6 +149,7 @@ void signals_handle(void) { break; case NETDATA_SIGNAL_EXIT_CLEANLY: + error_log_limit_unlimited(); info("SIGNAL: Received %s. Cleaning up to exit...", name); netdata_cleanup_and_exit(0); exit(0); diff --git a/src/signals.h b/daemon/signals.h index 2fdd3655..e7e64365 100644 --- a/src/signals.h +++ b/daemon/signals.h @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_SIGNALS_H -#define NETDATA_SIGNALS_H +#define NETDATA_SIGNALS_H 1 extern void signals_init(void); extern void signals_block(void); diff --git a/src/unit_test.c b/daemon/unit_test.c index e3eb146a..9978647b 100644 --- a/src/unit_test.c +++ b/daemon/unit_test.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #include "common.h" static int check_number_printing(void) { @@ -1197,8 +1199,50 @@ static int test_variable_renames(void) { return 1; } +int check_strdupz_path_subpath() { + + struct strdupz_path_subpath_checks { + const char *path; + const char *subpath; + const char *result; + } checks[] = { + { "", "", "." }, + { "/", "", "/" }, + { "/etc/netdata", "", "/etc/netdata" }, + { "/etc/netdata///", "", "/etc/netdata" }, + { "/etc/netdata///", "health.d", "/etc/netdata/health.d" }, + { "/etc/netdata///", "///health.d", "/etc/netdata/health.d" }, + { "/etc/netdata", "///health.d", "/etc/netdata/health.d" }, + { "", "///health.d", "./health.d" }, + { "/", "///health.d", "/health.d" }, + + // terminator + { NULL, NULL, NULL } + }; + + size_t i; + for(i = 0; checks[i].result ; i++) { + char *s = strdupz_path_subpath(checks[i].path, checks[i].subpath); + fprintf(stderr, "strdupz_path_subpath(\"%s\", \"%s\") = \"%s\": ", checks[i].path, checks[i].subpath, s); + if(!s || strcmp(s, checks[i].result) != 0) { + freez(s); + fprintf(stderr, "FAILED\n"); + return 1; + } + else { + freez(s); + fprintf(stderr, "OK\n"); + } + } + + return 0; +} + int run_all_mockup_tests(void) { + if(check_strdupz_path_subpath()) + return 1; + if(check_number_printing()) return 1; diff --git a/src/unit_test.h b/daemon/unit_test.h index 68ed61fc..0023c8de 100644 --- a/src/unit_test.h +++ b/daemon/unit_test.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_UNIT_TEST_H #define NETDATA_UNIT_TEST_H 1 diff --git a/src/rrd.c b/database/rrd.c index 3be2d8e4..119efa62 100644 --- a/src/rrd.c +++ b/database/rrd.c @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later #define NETDATA_RRD_INTERNALS 1 -#include "common.h" + +#include "rrd.h" // ---------------------------------------------------------------------------- // globals diff --git a/src/rrd.h b/database/rrd.h index d17daacd..19eb100c 100644 --- a/src/rrd.h +++ b/database/rrd.h @@ -1,6 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_RRD_H #define NETDATA_RRD_H 1 +// forward typedefs +typedef struct rrdhost RRDHOST; +typedef struct rrddim RRDDIM; +typedef struct rrdset RRDSET; +typedef struct rrdvar RRDVAR; +typedef struct rrdsetvar RRDSETVAR; +typedef struct rrddimvar RRDDIMVAR; +typedef struct rrdcalc RRDCALC; +typedef struct rrdcalctemplate RRDCALCTEMPLATE; +typedef struct alarm_entry ALARM_ENTRY; + +#include "../daemon/common.h" +#include "web/api/queries/query.h" +#include "rrdvar.h" +#include "rrdsetvar.h" +#include "rrddimvar.h" +#include "rrdcalc.h" +#include "rrdcalctemplate.h" + #define UPDATE_EVERY 1 #define UPDATE_EVERY_MAX 3600 @@ -19,8 +40,6 @@ extern int gap_when_lost_iterations_above; typedef long long total_number; #define TOTAL_NUMBER_FORMAT "%lld" -typedef struct rrdhost RRDHOST; - // ---------------------------------------------------------------------------- // chart types @@ -103,8 +122,8 @@ typedef struct rrdfamily RRDFAMILY; typedef enum rrddim_flags { RRDDIM_FLAG_NONE = 0, - RRDDIM_FLAG_HIDDEN = 1 << 0, // this dimension will not be offered to callers - RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = 1 << 1 // do not offer RESET or OVERFLOW info to callers + RRDDIM_FLAG_HIDDEN = (1 << 0), // this dimension will not be offered to callers + RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = (1 << 1) // do not offer RESET or OVERFLOW info to callers } RRDDIM_FLAGS; #ifdef HAVE_C___ATOMIC @@ -159,8 +178,8 @@ struct rrddim { size_t collections_counter; // the number of times we added values to this rrdim size_t unused[10]; - int updated:1; // 1 when the dimension has been updated since the last processing - int exposed:1; // 1 when set what have sent this dimension to the central netdata + unsigned int updated:1; // 1 when the dimension has been updated since the last processing + unsigned int exposed:1; // 1 when set what have sent this dimension to the central netdata struct timeval last_collected_time; // when was this dimension last updated // this is actual date time we updated the last_collected_value @@ -202,7 +221,6 @@ struct rrddim { storage_number values[]; // the array of values - THIS HAS TO BE THE LAST MEMBER }; -typedef struct rrddim RRDDIM; // ---------------------------------------------------------------------------- // these loop macros make sure the linked list is accessed with the right lock @@ -222,18 +240,21 @@ typedef struct rrddim RRDDIM; // and may lead to missing information. typedef enum rrdset_flags { - RRDSET_FLAG_ENABLED = 1 << 0, // enables or disables a chart - RRDSET_FLAG_DETAIL = 1 << 1, // if set, the data set should be considered as a detail of another + RRDSET_FLAG_ENABLED = 1 << 0, // enables or disables a chart + RRDSET_FLAG_DETAIL = 1 << 1, // if set, the data set should be considered as a detail of another // (the master data set should be the one that has the same family and is not detail) - RRDSET_FLAG_DEBUG = 1 << 2, // enables or disables debugging for a chart - RRDSET_FLAG_OBSOLETE = 1 << 3, // this is marked by the collector/module as obsolete - RRDSET_FLAG_BACKEND_SEND = 1 << 4, // if set, this chart should be sent to backends - RRDSET_FLAG_BACKEND_IGNORE = 1 << 5, // if set, this chart should not be sent to backends - RRDSET_FLAG_EXPOSED_UPSTREAM = 1 << 6, // if set, we have sent this chart to netdata master (streaming) - RRDSET_FLAG_STORE_FIRST = 1 << 7, // if set, do not eliminate the first collection during interpolation - RRDSET_FLAG_HETEROGENEOUS = 1 << 8, // if set, the chart is not homogeneous (dimensions in it have multiple algorithms, multipliers or dividers) - RRDSET_FLAG_HOMEGENEOUS_CHECK= 1 << 9, // if set, the chart should be checked to determine if the dimensions as homogeneous - RRDSET_FLAG_HIDDEN = 1 << 10, // if set, do not show this chart on the dashboard, but use it for backends + RRDSET_FLAG_DEBUG = 1 << 2, // enables or disables debugging for a chart + RRDSET_FLAG_OBSOLETE = 1 << 3, // this is marked by the collector/module as obsolete + RRDSET_FLAG_BACKEND_SEND = 1 << 4, // if set, this chart should be sent to backends + RRDSET_FLAG_BACKEND_IGNORE = 1 << 5, // if set, this chart should not be sent to backends + RRDSET_FLAG_UPSTREAM_SEND = 1 << 6, // if set, this chart should be sent upstream (streaming) + RRDSET_FLAG_UPSTREAM_IGNORE = 1 << 7, // if set, this chart should not be sent upstream (streaming) + RRDSET_FLAG_UPSTREAM_EXPOSED = 1 << 8, // if set, we have sent this chart definition to netdata master (streaming) + RRDSET_FLAG_STORE_FIRST = 1 << 9, // if set, do not eliminate the first collection during interpolation + RRDSET_FLAG_HETEROGENEOUS = 1 << 10, // if set, the chart is not homogeneous (dimensions in it have multiple algorithms, multipliers or dividers) + RRDSET_FLAG_HOMEGENEOUS_CHECK = 1 << 11, // if set, the chart should be checked to determine if the dimensions as homogeneous + RRDSET_FLAG_HIDDEN = 1 << 12, // if set, do not show this chart on the dashboard, but use it for backends + RRDSET_FLAG_SYNC_CLOCK = 1 << 13, // if set, microseconds on next data collection will be ignored (the chart will be synced to now) } RRDSET_FLAGS; #ifdef HAVE_C___ATOMIC @@ -245,6 +266,7 @@ typedef enum rrdset_flags { #define rrdset_flag_set(st, flag) (st)->flags |= (flag) #define rrdset_flag_clear(st, flag) (st)->flags &= ~(flag) #endif +#define rrdset_flag_check_noatomic(st, flag) ((st)->flags & (flag)) struct rrdset { // ------------------------------------------------------------------------ @@ -282,7 +304,7 @@ struct rrdset { long current_entry; // the entry that is currently being updated // it goes around in a round-robin fashion - uint32_t flags; // configuration flags + RRDSET_FLAGS flags; // configuration flags int gap_when_lost_iterations_above; // after how many lost iterations a gap should be stored // netdata will interpolate values for gaps lower than this @@ -353,7 +375,6 @@ struct rrdset { RRDDIM *dimensions; // the actual data for every dimension }; -typedef struct rrdset RRDSET; #define rrdset_rdlock(st) netdata_rwlock_rdlock(&((st)->rrdset_rwlock)) #define rrdset_wrlock(st) netdata_rwlock_wrlock(&((st)->rrdset_rwlock)) @@ -401,6 +422,65 @@ typedef enum rrdhost_flags { #define rrdset_debug(st, fmt, args...) debug_dummy() #endif +// ---------------------------------------------------------------------------- +// Health data + +struct alarm_entry { + uint32_t unique_id; + uint32_t alarm_id; + uint32_t alarm_event_id; + + time_t when; + time_t duration; + time_t non_clear_duration; + + char *name; + uint32_t hash_name; + + char *chart; + uint32_t hash_chart; + + char *family; + + char *exec; + char *recipient; + time_t exec_run_timestamp; + int exec_code; + + char *source; + char *units; + char *info; + + calculated_number old_value; + calculated_number new_value; + + char *old_value_string; + char *new_value_string; + + RRDCALC_STATUS old_status; + RRDCALC_STATUS new_status; + + uint32_t flags; + + int delay; + time_t delay_up_to_timestamp; + + uint32_t updated_by_id; + uint32_t updates_id; + + struct alarm_entry *next; +}; + + +typedef struct alarm_log { + uint32_t next_log_id; + uint32_t next_alarm_id; + unsigned int count; + unsigned int max; + ALARM_ENTRY *alarms; + netdata_rwlock_t alarm_log_rwlock; +} ALARM_LOG; + // ---------------------------------------------------------------------------- // RRD HOST @@ -423,7 +503,7 @@ struct rrdhost { const char *tags; // tags for this host const char *timezone; // the timezone of the host - uint32_t flags; // flags about this RRDHOST + RRDHOST_FLAGS flags; // flags about this RRDHOST int rrd_update_every; // the update frequency of the host long rrd_history_entries; // the number of history entries for the host's charts @@ -438,20 +518,22 @@ struct rrdhost { // ------------------------------------------------------------------------ // streaming of data to remote hosts - rrdpush - int rrdpush_send_enabled:1; // 1 when this host sends metrics to another netdata + unsigned int rrdpush_send_enabled:1; // 1 when this host sends metrics to another netdata char *rrdpush_send_destination; // where to send metrics to char *rrdpush_send_api_key; // the api key at the receiving netdata // the following are state information for the threading // streaming metrics from this netdata to an upstream netdata - volatile int rrdpush_sender_spawn:1; // 1 when the sender thread has been spawn + volatile unsigned int rrdpush_sender_spawn:1; // 1 when the sender thread has been spawn netdata_thread_t rrdpush_sender_thread; // the sender thread - volatile int rrdpush_sender_connected:1; // 1 when the sender is ready to push metrics + volatile unsigned int rrdpush_sender_connected:1; // 1 when the sender is ready to push metrics int rrdpush_sender_socket; // the fd of the socket to the remote host, or -1 - volatile int rrdpush_sender_error_shown:1; // 1 when we have logged a communication error - volatile int rrdpush_sender_join:1; // 1 when we have to join the sending thread + volatile unsigned int rrdpush_sender_error_shown:1; // 1 when we have logged a communication error + volatile unsigned int rrdpush_sender_join:1; // 1 when we have to join the sending thread + + SIMPLE_PATTERN *rrdpush_send_charts_matching; // pattern to match the charts to be sent // metrics may be collected asynchronously // these synchronize all the threads willing the write to our sending buffer @@ -471,7 +553,7 @@ struct rrdhost { // ------------------------------------------------------------------------ // health monitoring options - int health_enabled:1; // 1 when this host has health enabled + unsigned int health_enabled:1; // 1 when this host has health enabled time_t health_delay_up_to; // a timestamp to delay alarms processing up to char *health_default_exec; // the full path of the alarms notifications program char *health_default_recipient; // the default recipient for all alarms @@ -564,10 +646,11 @@ extern RRDHOST *rrdhost_find_or_create( , int update_every , long history , RRD_MEMORY_MODE mode - , int health_enabled - , int rrdpush_enabled + , unsigned int health_enabled + , unsigned int rrdpush_enabled , char *rrdpush_destination , char *rrdpush_api_key + , char *rrdpush_send_charts_matching ); #if defined(NETDATA_INTERNAL_CHECKS) && defined(NETDATA_VERIFY_LOCKS) @@ -666,28 +749,84 @@ extern void rrdset_isnot_obsolete(RRDSET *st); #define rrdset_first_entry_t(st) ((time_t)(rrdset_last_entry_t(st) - rrdset_duration(st))) // get the last slot updated in the round robin database -#define rrdset_last_slot(st) ((unsigned long)(((st)->current_entry == 0) ? (st)->entries - 1 : (st)->current_entry - 1)) +#define rrdset_last_slot(st) ((size_t)(((st)->current_entry == 0) ? (st)->entries - 1 : (st)->current_entry - 1)) // get the first / oldest slot updated in the round robin database -#define rrdset_first_slot(st) ((unsigned long)( (((st)->counter >= ((unsigned long)(st)->entries)) ? (unsigned long)( ((unsigned long)(st)->current_entry > 0) ? ((unsigned long)(st)->current_entry) : ((unsigned long)(st)->entries) ) - 1 : 0) )) +// #define rrdset_first_slot(st) ((size_t)( (((st)->counter >= ((unsigned long)(st)->entries)) ? (unsigned long)( ((unsigned long)(st)->current_entry > 0) ? ((unsigned long)(st)->current_entry) : ((unsigned long)(st)->entries) ) - 1 : 0) )) + +// return the slot that has the oldest value + +static inline size_t rrdset_first_slot(RRDSET *st) { + if(st->counter >= (size_t)st->entries) { + // the database has been rotated at least once + // the oldest entry is the one that will be next + // overwritten by data collection + return (size_t)st->current_entry; + } + + // we do not have rotated the db yet + // so 0 is the first entry + return 0; +} // get the slot of the round robin database, for the given timestamp (t) // it always returns a valid slot, although may not be for the time requested if the time is outside the round robin database -#define rrdset_time2slot(st, t) ( \ - ( (time_t)(t) >= rrdset_last_entry_t(st)) ? ( rrdset_last_slot(st) ) : \ - ( ((time_t)(t) <= rrdset_first_entry_t(st)) ? rrdset_first_slot(st) : \ - ( (rrdset_last_slot(st) >= (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) ? \ - (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) : \ - (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) + (unsigned long)(st)->entries ) \ - ))) +static inline size_t rrdset_time2slot(RRDSET *st, time_t t) { + size_t ret = 0; + + if(t >= rrdset_last_entry_t(st)) { + // the requested time is after the last entry we have + ret = rrdset_last_slot(st); + } + else { + if(t <= rrdset_first_entry_t(st)) { + // the requested time is before the first entry we have + ret = rrdset_first_slot(st); + } + else { + if(rrdset_last_slot(st) >= ((rrdset_last_entry_t(st) - t) / (size_t)(st->update_every))) + ret = rrdset_last_slot(st) - ((rrdset_last_entry_t(st) - t) / (size_t)(st->update_every)); + else + ret = rrdset_last_slot(st) - ((rrdset_last_entry_t(st) - t) / (size_t)(st->update_every)) + (unsigned long)st->entries; + } + } + + if(unlikely(ret >= (size_t)st->entries)) { + error("INTERNAL ERROR: rrdset_time2slot() on %s returns values outside entries", st->name); + ret = (size_t)(st->entries - 1); + } + + return ret; +} // get the timestamp of a specific slot in the round robin database -#define rrdset_slot2time(st, slot) ( rrdset_last_entry_t(st) - \ - ((unsigned long)(st)->update_every * ( \ - ( (unsigned long)(slot) > rrdset_last_slot(st)) ? \ - ( (rrdset_last_slot(st) - (unsigned long)(slot) + (unsigned long)(st)->entries) ) : \ - ( (rrdset_last_slot(st) - (unsigned long)(slot)) )) \ - )) +static inline time_t rrdset_slot2time(RRDSET *st, size_t slot) { + time_t ret; + + if(slot >= (size_t)st->entries) { + error("INTERNAL ERROR: caller of rrdset_slot2time() gives invalid slot %zu", slot); + slot = (size_t)st->entries - 1; + } + + if(slot > rrdset_last_slot(st)) { + ret = rrdset_last_entry_t(st) - (size_t)st->update_every * (rrdset_last_slot(st) - slot + (size_t)st->entries); + } + else { + ret = rrdset_last_entry_t(st) - (size_t)st->update_every; + } + + if(unlikely(ret < rrdset_first_entry_t(st))) { + error("INTERNAL ERROR: rrdset_slot2time() on %s returns time too far in the past", st->name); + ret = rrdset_first_entry_t(st); + } + + if(unlikely(ret > rrdset_last_entry_t(st))) { + error("INTERNAL ERROR: rrdset_slot2time() on %s returns time into the future", st->name); + ret = rrdset_last_entry_t(st); + } + + return ret; +} // ---------------------------------------------------------------------------- // RRD DIMENSION functions diff --git a/src/rrdcalc.c b/database/rrdcalc.c index 4e41539e..7f6a896b 100644 --- a/src/rrdcalc.c +++ b/database/rrdcalc.c @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #define NETDATA_HEALTH_INTERNALS -#include "common.h" +#include "rrd.h" // ---------------------------------------------------------------------------- // RRDCALC management @@ -64,15 +66,18 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) { st->red = rc->red; } - rc->local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); - rc->family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_LOCAL_VAR, &rc->value); + rc->family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_FAMILY_VAR, &rc->value); char fullname[RRDVAR_MAX_LENGTH + 1]; snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rc->name); - rc->hostid = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->hostid = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_HOST_CHARTID_VAR, &rc->value); snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name); - rc->hostname = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->hostname = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_HOST_CHARTNAME_VAR, &rc->value); + + if(rc->hostid && !rc->hostname) + rc->hostid->options |= RRDVAR_OPTION_RRDCALC_HOST_CHARTNAME_VAR; if(!rc->units) rc->units = strdupz(st->units); @@ -358,7 +363,7 @@ inline RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *c (rc->recipient)?rc->recipient:"DEFAULT", rc->green, rc->red, - rc->group, + (int)rc->group, rc->after, rc->before, rc->options, diff --git a/src/rrdcalctemplate.c b/database/rrdcalctemplate.c index 75a7002b..ba7e7ec9 100644 --- a/src/rrdcalctemplate.c +++ b/database/rrdcalctemplate.c @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #define NETDATA_HEALTH_INTERNALS -#include "common.h" +#include "rrd.h" // ---------------------------------------------------------------------------- // RRDCALCTEMPLATE management diff --git a/src/rrddim.c b/database/rrddim.c index a54c6452..95e48510 100644 --- a/src/rrddim.c +++ b/database/rrddim.c @@ -1,5 +1,7 @@ -#define NETDATA_RRD_INTERNALS 1 -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#define NETDATA_RRD_INTERNALS +#include "rrd.h" // ---------------------------------------------------------------------------- // RRDDIM index @@ -47,6 +49,7 @@ inline int rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name) { rd->hash_name = simple_hash(rd->name); rrddimvar_rename_all(rd); rd->exposed = 0; + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); return 1; } @@ -58,6 +61,7 @@ inline int rrddim_set_algorithm(RRDSET *st, RRDDIM *rd, RRD_ALGORITHM algorithm) rd->algorithm = algorithm; rd->exposed = 0; rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); return 1; } @@ -69,6 +73,7 @@ inline int rrddim_set_multiplier(RRDSET *st, RRDDIM *rd, collected_number multip rd->multiplier = multiplier; rd->exposed = 0; rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); return 1; } @@ -80,6 +85,7 @@ inline int rrddim_set_divisor(RRDSET *st, RRDDIM *rd, collected_number divisor) rd->divisor = divisor; rd->exposed = 0; rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); return 1; } @@ -87,6 +93,11 @@ inline int rrddim_set_divisor(RRDSET *st, RRDDIM *rd, collected_number divisor) // RRDDIM create a dimension RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm, RRD_MEMORY_MODE memory_mode) { + rrdset_wrlock(st); + + rrdset_flag_set(st, RRDSET_FLAG_SYNC_CLOCK); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); + RRDDIM *rd = rrddim_find(st, id); if(unlikely(rd)) { debug(D_RRD_CALLS, "Cannot create rrd dimension '%s/%s', it already exists.", st->id, name?name:"<NONAME>"); @@ -96,6 +107,7 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte rrddim_set_multiplier(st, rd, multiplier); rrddim_set_divisor(st, rd, divisor); + rrdset_unlock(st); return rd; } @@ -236,7 +248,6 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte rd->rrdset = st; // append this dimension - rrdset_wrlock(st); if(!st->dimensions) st->dimensions = rd; else { @@ -268,11 +279,10 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT); } - rrdset_unlock(st); - if(unlikely(rrddim_index_add(st, rd) != rd)) error("RRDDIM: INTERNAL ERROR: attempt to index duplicate dimension '%s' on chart '%s'", rd->id, st->id); + rrdset_unlock(st); return(rd); } diff --git a/src/rrddimvar.c b/database/rrddimvar.c index 28a3e7fa..3c2ed75e 100644 --- a/src/rrddimvar.c +++ b/database/rrddimvar.c @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #define NETDATA_HEALTH_INTERNALS -#include "common.h" +#include "rrd.h" // ---------------------------------------------------------------------------- // RRDDIMVAR management @@ -117,8 +119,8 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { // - $id // - $name - rs->var_local_id = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_id, rs->type, rs->value); - rs->var_local_name = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_name, rs->type, rs->value); + rs->var_local_id = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_id, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); + rs->var_local_name = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_name, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); // FAMILY VARIABLES FOR THIS DIMENSION // ----------------------------------- @@ -129,10 +131,10 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { // - $chart-context.id // - $chart-context.name - rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_id, rs->type, rs->value); - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_name, rs->type, rs->value); - rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextid, rs->type, rs->value); - rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextname, rs->type, rs->value); + rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_id, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_name, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); + rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextid, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); + rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextname, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); // HOST VARIABLES FOR THIS DIMENSION // ----------------------------------- @@ -143,14 +145,15 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { // - $chart-name.id // - $chart-name.name - rs->var_host_chartidid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidid, rs->type, rs->value); - rs->var_host_chartidname = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidname, rs->type, rs->value); - rs->var_host_chartnameid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnameid, rs->type, rs->value); - rs->var_host_chartnamename = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnamename, rs->type, rs->value); + rs->var_host_chartidid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidid, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); + rs->var_host_chartidname = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidname, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); + rs->var_host_chartnameid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnameid, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); + rs->var_host_chartnamename = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnamename, rs->type, RRDVAR_OPTION_DEFAULT, rs->value); } RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, const char *suffix, void *value, RRDVAR_OPTIONS options) { RRDSET *st = rd->rrdset; + (void)st; debug(D_VARIABLES, "RRDDIMSET create for chart id '%s' name '%s', dimension id '%s', name '%s%s%s'", st->id, st->name, rd->id, (prefix)?prefix:"", rd->name, (suffix)?suffix:""); @@ -177,6 +180,8 @@ RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, co void rrddimvar_rename_all(RRDDIM *rd) { RRDSET *st = rd->rrdset; + (void)st; + debug(D_VARIABLES, "RRDDIMSET rename for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); RRDDIMVAR *rs, *next = rd->variables; diff --git a/src/rrdfamily.c b/database/rrdfamily.c index 905ae480..f75f0adc 100644 --- a/src/rrdfamily.c +++ b/database/rrdfamily.c @@ -1,5 +1,7 @@ -#define NETDATA_RRD_INTERNALS 1 -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#define NETDATA_RRD_INTERNALS +#include "rrd.h" // ---------------------------------------------------------------------------- // RRDFAMILY index diff --git a/src/rrdhost.c b/database/rrdhost.c index e62e61ae..43aa2daa 100644 --- a/src/rrdhost.c +++ b/database/rrdhost.c @@ -1,5 +1,7 @@ -#define NETDATA_RRD_INTERNALS 1 -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#define NETDATA_RRD_INTERNALS +#include "rrd.h" RRDHOST *localhost = NULL; size_t rrd_hosts_available = 0; @@ -116,10 +118,11 @@ RRDHOST *rrdhost_create(const char *hostname, int update_every, long entries, RRD_MEMORY_MODE memory_mode, - int health_enabled, - int rrdpush_enabled, + unsigned int health_enabled, + unsigned int rrdpush_enabled, char *rrdpush_destination, char *rrdpush_api_key, + char *rrdpush_send_charts_matching, int is_localhost ) { debug(D_RRDHOST, "Host '%s': adding with guid '%s'", hostname, guid); @@ -132,9 +135,10 @@ RRDHOST *rrdhost_create(const char *hostname, host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries); host->rrd_memory_mode = memory_mode; host->health_enabled = (memory_mode == RRD_MEMORY_MODE_NONE)? 0 : health_enabled; - host->rrdpush_send_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key); + host->rrdpush_send_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key) ? 1 : 0; host->rrdpush_send_destination = (host->rrdpush_send_enabled)?strdupz(rrdpush_destination):NULL; host->rrdpush_send_api_key = (host->rrdpush_send_enabled)?strdupz(rrdpush_api_key):NULL; + host->rrdpush_send_charts_matching = simple_pattern_create(rrdpush_send_charts_matching, NULL, SIMPLE_PATTERN_EXACT); host->rrdpush_sender_pipe[0] = -1; host->rrdpush_sender_pipe[1] = -1; @@ -227,7 +231,7 @@ RRDHOST *rrdhost_create(const char *hostname, snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir); host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename)); - host->health_default_recipient = strdup("root"); + host->health_default_recipient = strdupz("root"); // ------------------------------------------------------------------------ @@ -238,7 +242,7 @@ RRDHOST *rrdhost_create(const char *hostname, health_alarm_log_open(host); rrdhost_wrlock(host); - health_readdir(host, health_config_dir()); + health_readdir(host, health_user_config_dir(), health_stock_config_dir(), NULL); rrdhost_unlock(host); } @@ -323,10 +327,11 @@ RRDHOST *rrdhost_find_or_create( , int update_every , long history , RRD_MEMORY_MODE mode - , int health_enabled - , int rrdpush_enabled + , unsigned int health_enabled + , unsigned int rrdpush_enabled , char *rrdpush_destination , char *rrdpush_api_key + , char *rrdpush_send_charts_matching ) { debug(D_RRDHOST, "Searching for host '%s' with guid '%s'", hostname, guid); @@ -349,6 +354,7 @@ RRDHOST *rrdhost_find_or_create( , rrdpush_enabled , rrdpush_destination , rrdpush_api_key + , rrdpush_send_charts_matching , 0 ); } @@ -461,6 +467,7 @@ void rrd_init(char *hostname) { , default_rrdpush_enabled , default_rrdpush_destination , default_rrdpush_api_key + , default_rrdpush_send_charts_matching , 1 ); rrd_unlock(); @@ -574,6 +581,7 @@ void rrdhost_free(RRDHOST *host) { freez(host->health_log_filename); freez(host->hostname); freez(host->registry_hostname); + simple_pattern_free(host->rrdpush_send_charts_matching); rrdhost_unlock(host); netdata_rwlock_destroy(&host->health_log.alarm_log_rwlock); netdata_rwlock_destroy(&host->rrdhost_rwlock); diff --git a/src/rrdset.c b/database/rrdset.c index bbd0ae72..3f5ba73b 100644 --- a/src/rrdset.c +++ b/database/rrdset.c @@ -1,5 +1,7 @@ -#define NETDATA_RRD_INTERNALS 1 -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#define NETDATA_RRD_INTERNALS +#include "rrd.h" void __rrdset_check_rdlock(RRDSET *st, const char *file, const char *function, const unsigned long line) { debug(D_RRD_CALLS, "Checking read lock on chart '%s'", st->id); @@ -172,27 +174,30 @@ int rrdset_set_name(RRDSET *st, const char *name) { if(unlikely(rrdset_index_add_name(host, st) != st)) error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name); + rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_SEND); + rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_IGNORE); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_SEND); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_IGNORE); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); + return 1; } inline void rrdset_is_obsolete(RRDSET *st) { - RRDHOST *host = st->rrdhost; - if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) { rrdset_flag_set(st, RRDSET_FLAG_OBSOLETE); - rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); // the chart will not get more updates (data collection) // so, we have to push its definition now - if(unlikely(host->rrdpush_send_enabled)) - rrdset_push_chart_definition(st); + rrdset_push_chart_definition_now(st); } } inline void rrdset_isnot_obsolete(RRDSET *st) { if(unlikely((rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) { rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE); - rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); // the chart will be pushed upstream automatically // due to data collection @@ -201,6 +206,8 @@ inline void rrdset_isnot_obsolete(RRDSET *st) { inline void rrdset_update_heterogeneous_flag(RRDSET *st) { RRDHOST *host = st->rrdhost; + (void)host; + RRDDIM *rd; rrdset_flag_clear(st, RRDSET_FLAG_HOMEGENEOUS_CHECK); @@ -476,13 +483,19 @@ RRDSET *rrdset_create_custom( snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); RRDSET *st = rrdset_find_on_create(host, fullid); - if(st) return st; + if(st) { + rrdset_flag_set(st, RRDSET_FLAG_SYNC_CLOCK); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); + return st; + } rrdhost_wrlock(host); st = rrdset_find_on_create(host, fullid); if(st) { rrdhost_unlock(host); + rrdset_flag_set(st, RRDSET_FLAG_SYNC_CLOCK); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); return st; } @@ -581,8 +594,8 @@ RRDSET *rrdset_create_custom( memset(st, 0, size); } else if(st->last_updated.tv_sec > now + update_every) { - error("File %s refers to the future. Clearing it.", fullfilename); - memset(st, 0, size); + error("File %s refers to the future by %zd secs. Resetting it to now.", fullfilename, (ssize_t)(st->last_updated.tv_sec - now)); + st->last_updated.tv_sec = now; } // make sure the database is aligned @@ -603,10 +616,10 @@ RRDSET *rrdset_create_custom( st->rrd_memory_mode = (memory_mode == RRD_MEMORY_MODE_NONE) ? RRD_MEMORY_MODE_NONE : RRD_MEMORY_MODE_ALLOC; } - st->plugin_name = plugin?strdup(plugin):NULL; - st->module_name = module?strdup(module):NULL; + st->plugin_name = plugin?strdupz(plugin):NULL; + st->module_name = module?strdupz(module):NULL; - st->config_section = strdup(config_section); + st->config_section = strdupz(config_section); st->rrdhost = host; st->memsize = size; st->entries = entries; @@ -644,7 +657,12 @@ RRDSET *rrdset_create_custom( rrdset_flag_clear(st, RRDSET_FLAG_DETAIL); rrdset_flag_clear(st, RRDSET_FLAG_DEBUG); rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE); - rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM); + rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_SEND); + rrdset_flag_clear(st, RRDSET_FLAG_BACKEND_IGNORE); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_SEND); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_IGNORE); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); + rrdset_flag_set(st, RRDSET_FLAG_SYNC_CLOCK); // if(!strcmp(st->id, "disk_util.dm-0")) { // st->debug = 1; @@ -710,7 +728,7 @@ RRDSET *rrdset_create_custom( // RRDSET - data collection iteration control inline void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds) { - if(unlikely(!st->last_collected_time.tv_sec || !microseconds)) { + if(unlikely(!st->last_collected_time.tv_sec || !microseconds || (rrdset_flag_check_noatomic(st, RRDSET_FLAG_SYNC_CLOCK)))) { // call the full next_usec() function rrdset_next_usec(st, microseconds); return; @@ -723,13 +741,36 @@ inline void rrdset_next_usec(RRDSET *st, usec_t microseconds) { struct timeval now; now_realtime_timeval(&now); + #ifdef NETDATA_INTERNAL_CHECKS + char *discard_reason = NULL; + usec_t discarded = microseconds; + #endif + + if(unlikely(rrdset_flag_check_noatomic(st, RRDSET_FLAG_SYNC_CLOCK))) { + // the chart needs to be re-synced to current time + rrdset_flag_clear(st, RRDSET_FLAG_SYNC_CLOCK); + + // discard the microseconds supplied + microseconds = 0; + + #ifdef NETDATA_INTERNAL_CHECKS + if(!discard_reason) discard_reason = "SYNC CLOCK FLAG"; + #endif + } + if(unlikely(!st->last_collected_time.tv_sec)) { // the first entry microseconds = st->update_every * USEC_PER_SEC; + #ifdef NETDATA_INTERNAL_CHECKS + if(!discard_reason) discard_reason = "FIRST DATA COLLECTION"; + #endif } else if(unlikely(!microseconds)) { // no dt given by the plugin microseconds = dt_usec(&now, &st->last_collected_time); + #ifdef NETDATA_INTERNAL_CHECKS + if(!discard_reason) discard_reason = "NO USEC GIVEN BY COLLECTOR"; + #endif } else { // microseconds has the time since the last collection @@ -748,18 +789,52 @@ inline void rrdset_next_usec(RRDSET *st, usec_t microseconds) { last_updated_time_align(st); microseconds = st->update_every * USEC_PER_SEC; + #ifdef NETDATA_INTERNAL_CHECKS + if(!discard_reason) discard_reason = "COLLECTION TIME IN FUTURE"; + #endif } - else if(unlikely((usec_t)since_last_usec > (usec_t)(st->update_every * 10 * USEC_PER_SEC))) { + else if(unlikely((usec_t)since_last_usec > (usec_t)(st->update_every * 5 * USEC_PER_SEC))) { // oops! the database is too far behind info("RRD database for chart '%s' on host '%s' is %0.5" LONG_DOUBLE_MODIFIER " secs in the past (counter #%zu, update #%zu). Adjusting it to current time.", st->id, st->rrdhost->hostname, (LONG_DOUBLE)since_last_usec / USEC_PER_SEC, st->counter, st->counter_done); microseconds = (usec_t)since_last_usec; + #ifdef NETDATA_INTERNAL_CHECKS + if(!discard_reason) discard_reason = "COLLECTION TIME TOO FAR IN THE PAST"; + #endif + } + +#ifdef NETDATA_INTERNAL_CHECKS + if(since_last_usec > 0 && (susec_t)microseconds < since_last_usec) { + static __thread susec_t min_delta = USEC_PER_SEC * 3600, permanent_min_delta = 0; + static __thread time_t last_t = 0; + + // the first time initialize it so that it will make the check later + if(last_t == 0) last_t = now.tv_sec + 60; + + susec_t delta = since_last_usec - (susec_t)microseconds; + if(delta < min_delta) min_delta = delta; + + if(now.tv_sec >= last_t + 60) { + last_t = now.tv_sec; + + if(min_delta > permanent_min_delta) { + info("MINIMUM MICROSECONDS DELTA of thread %d increased from %lld to %lld (+%lld)", gettid(), permanent_min_delta, min_delta, min_delta - permanent_min_delta); + permanent_min_delta = min_delta; + } + + min_delta = USEC_PER_SEC * 3600; + } } +#endif } #ifdef NETDATA_INTERNAL_CHECKS debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds); rrdset_debug(st, "NEXT: %llu microseconds", microseconds); + + if(discarded && discarded != microseconds) + info("host '%s', chart '%s': discarded data collection time of %llu usec, replaced with %llu usec, reason: '%s'", st->rrdhost->hostname, st->id, discarded, microseconds, discard_reason?discard_reason:"UNDEFINED"); + #endif st->usec_since_last_update = microseconds; @@ -857,6 +932,8 @@ static inline size_t rrdset_done_interpolate( size_t stored_entries = 0; // the number of entries we have stored in the db, during this call to rrdset_done() usec_t first_ut = last_stored_ut, last_ut = 0; + (void)first_ut; + ssize_t iterations = (ssize_t)((now_collect_ut - last_stored_ut) / (update_every_ut)); if((now_collect_ut % (update_every_ut)) == 0) iterations++; diff --git a/src/rrdsetvar.c b/database/rrdsetvar.c index aec57efa..1bb883f0 100644 --- a/src/rrdsetvar.c +++ b/database/rrdsetvar.c @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #define NETDATA_HEALTH_INTERNALS -#include "common.h" +#include "rrd.h" // ---------------------------------------------------------------------------- // RRDSETVAR management @@ -43,6 +45,10 @@ static inline void rrdsetvar_create_variables(RRDSETVAR *rs) { RRDSET *st = rs->rrdset; RRDHOST *host = st->rrdhost; + RRDVAR_OPTIONS options = rs->options; + if(rs->options & RRDVAR_OPTION_ALLOCATED) + options &= ~ RRDVAR_OPTION_ALLOCATED; + // ------------------------------------------------------------------------ // free the old ones (if any) @@ -60,17 +66,17 @@ static inline void rrdsetvar_create_variables(RRDSETVAR *rs) { // ------------------------------------------------------------------------ // CHART - rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, rs->value); + rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, options, rs->value); // ------------------------------------------------------------------------ // FAMILY - rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, rs->value); - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, rs->value); + rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, options, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, options, rs->value); // ------------------------------------------------------------------------ // HOST - rs->var_host = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullid, rs->type, rs->value); - rs->var_host_name = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullname, rs->type, rs->value); + rs->var_host = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullid, rs->type, options, rs->value); + rs->var_host_name = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullname, rs->type, options, rs->value); } RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options) { @@ -143,7 +149,7 @@ RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name) for(rs = st->variables; rs ; rs = rs->next) { if(hash == rs->hash && strcmp(n, rs->variable) == 0) { rrdset_unlock(st); - if(rs->options & RRDVAR_OPTION_ALLOCATED) { + if(rs->options & RRDVAR_OPTION_CUSTOM_CHART_VAR) { free(n); return rs; } @@ -160,16 +166,16 @@ RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name) calculated_number *v = mallocz(sizeof(calculated_number)); *v = NAN; - rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED); + rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED|RRDVAR_OPTION_CUSTOM_CHART_VAR); rrdset_unlock(st); - free(n); + freez(n); return rs; } void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rs, calculated_number value) { - if(unlikely(!(rs->options & RRDVAR_OPTION_ALLOCATED))) { - error("RRDSETVAR: requested to set variable '%s' of chart '%s' on host '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rs->variable, rs->rrdset->id, rs->rrdset->rrdhost->hostname, value); + if(rs->type != RRDVAR_TYPE_CALCULATED || !(rs->options & RRDVAR_OPTION_CUSTOM_CHART_VAR) || !(rs->options & RRDVAR_OPTION_ALLOCATED)) { + error("RRDSETVAR: requested to set variable '%s' of chart '%s' on host '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom chart one.", rs->variable, rs->rrdset->id, rs->rrdset->rrdhost->hostname, value); } else { calculated_number *v = rs->value; @@ -177,7 +183,7 @@ void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rs, calculated_number value) *v = value; // mark the chart to be sent upstream - rrdset_flag_clear(rs->rrdset, RRDSET_FLAG_EXPOSED_UPSTREAM); + rrdset_flag_clear(rs->rrdset, RRDSET_FLAG_UPSTREAM_EXPOSED); } } } diff --git a/src/rrdvar.c b/database/rrdvar.c index 6936c36f..951a38ca 100644 --- a/src/rrdvar.c +++ b/database/rrdvar.c @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #define NETDATA_HEALTH_INTERNALS -#include "common.h" +#include "rrd.h" // ---------------------------------------------------------------------------- // RRDVAR management @@ -59,14 +61,14 @@ inline void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv) { error("RRDVAR: Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname); } - if(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED) + if(rv->options & RRDVAR_OPTION_ALLOCATED) freez(rv->value); freez(rv->name); freez(rv); } -inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value) { +inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, RRDVAR_OPTIONS options, void *value) { char *variable = strdupz(name); rrdvar_fix_name(variable); uint32_t hash = simple_hash(variable); @@ -79,7 +81,9 @@ inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, c rv->name = variable; rv->hash = hash; rv->type = type; + rv->options = options; rv->value = value; + rv->last_updated = now_realtime_sec(); RRDVAR *ret = rrdvar_index_add(tree, rv); if(unlikely(ret != rv)) { @@ -106,7 +110,7 @@ inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, c } void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock) { - // FIXME: this is not bullet proof - avl should support some means to destroy it + // This is not bullet proof - avl should support some means to destroy it // with a callback for each item already in the index RRDVAR *rv, *last = NULL; @@ -123,7 +127,7 @@ void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock) { // ---------------------------------------------------------------------------- // CUSTOM HOST VARIABLES -inline int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data) { +inline int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void * /*rrdvar*/, void * /*data*/), void *data) { return avl_traverse_lock(&host->rrdvar_root_index, callback, data); } @@ -131,7 +135,7 @@ static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *t calculated_number *v = callocz(1, sizeof(calculated_number)); *v = NAN; - RRDVAR *rv = rrdvar_create_and_index(scope, tree_lock, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v); + RRDVAR *rv = rrdvar_create_and_index(scope, tree_lock, name, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_CUSTOM_HOST_VAR|RRDVAR_OPTION_ALLOCATED, v); if(unlikely(!rv)) { free(v); debug(D_VARIABLES, "Requested variable '%s' already exists - possibly 2 plugins are updating it at the same time.", name); @@ -140,6 +144,7 @@ static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *t rrdvar_fix_name(variable); uint32_t hash = simple_hash(variable); + // find the existing one to return it rv = rrdvar_index_find(tree_lock, variable, hash); freez(variable); @@ -153,25 +158,30 @@ RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) { } void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value) { - if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) + if(rv->type != RRDVAR_TYPE_CALCULATED || !(rv->options & RRDVAR_OPTION_CUSTOM_HOST_VAR) || !(rv->options & RRDVAR_OPTION_ALLOCATED)) error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value); else { calculated_number *v = rv->value; if(*v != value) { *v = value; + rv->last_updated = now_realtime_sec(); + // if the host is streaming, send this variable upstream immediately rrdpush_sender_send_this_host_variable_now(host, rv); } } } +int foreach_host_variable_callback(RRDHOST *host, int (*callback)(RRDVAR * /*rv*/, void * /*data*/), void *data) { + return avl_traverse_lock(&host->rrdvar_root_index, (int (*)(void *, void *))callback, data); +} + // ---------------------------------------------------------------------------- // RRDVAR lookup -static calculated_number rrdvar2number(RRDVAR *rv) { +calculated_number rrdvar2number(RRDVAR *rv) { switch(rv->type) { - case RRDVAR_TYPE_CALCULATED_ALLOCATED: case RRDVAR_TYPE_CALCULATED: { calculated_number *n = (calculated_number *)rv->value; return *n; diff --git a/src/health.c b/health/health.c index 04e04f08..ae0c464b 100644 --- a/src/health.c +++ b/health/health.c @@ -1,21 +1,28 @@ -#define NETDATA_HEALTH_INTERNALS -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later -int default_health_enabled = 1; +#include "health.h" + +unsigned int default_health_enabled = 1; // ---------------------------------------------------------------------------- // health initialization -inline char *health_config_dir(void) { +inline char *health_user_config_dir(void) { char buffer[FILENAME_MAX + 1]; - snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_config_dir); + snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_user_config_dir); return config_get(CONFIG_SECTION_HEALTH, "health configuration directory", buffer); } +inline char *health_stock_config_dir(void) { + char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_stock_config_dir); + return config_get(CONFIG_SECTION_HEALTH, "stock health configuration directory", buffer); +} + void health_init(void) { debug(D_HEALTH, "Health configuration initializing"); - if(!(default_health_enabled = config_get_boolean(CONFIG_SECTION_HEALTH, "enabled", 1))) { + if(!(default_health_enabled = (unsigned int)config_get_boolean(CONFIG_SECTION_HEALTH, "enabled", default_health_enabled))) { debug(D_HEALTH, "Health is disabled."); return; } @@ -28,7 +35,8 @@ void health_reload_host(RRDHOST *host) { if(unlikely(!host->health_enabled)) return; - char *path = health_config_dir(); + char *user_path = health_user_config_dir(); + char *stock_path = health_stock_config_dir(); // free all running alarms rrdhost_wrlock(host); @@ -59,7 +67,7 @@ void health_reload_host(RRDHOST *host) { // load the new alarms rrdhost_wrlock(host); - health_readdir(host, path); + health_readdir(host, user_path, stock_path, NULL); // link the loaded alarms to their charts rrdset_foreach_write(st, host) { @@ -178,9 +186,9 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { error("HEALTH: Cannot popen(\"%s\", \"r\").", command_to_run); goto done; } - debug(D_HEALTH, "HEALTH reading from command"); - char *s = fgets(command_to_run, FILENAME_MAX, fp); - (void)s; + debug(D_HEALTH, "HEALTH reading from command (discarding command's output)"); + char buffer[100 + 1]; + while(fgets(buffer, 100, fp) != NULL) ; ae->exec_code = mypclose(fp, command_pid); debug(D_HEALTH, "done executing command - returned with code %d", ae->exec_code); @@ -521,6 +529,11 @@ void *health_main(void *ptr) { ); rc->value = rc->calculation->result; + + if(rc->local) rc->local->last_updated = now; + if(rc->family) rc->family->last_updated = now; + if(rc->hostid) rc->hostid->last_updated = now; + if(rc->hostname) rc->hostname->last_updated = now; } } } diff --git a/src/health_config.c b/health/health_config.c index a25ee722..d4af9776 100644 --- a/src/health_config.c +++ b/health/health_config.c @@ -1,5 +1,6 @@ -#define NETDATA_HEALTH_INTERNALS -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "health.h" #define HEALTH_CONF_MAX_LINE 4096 @@ -52,7 +53,7 @@ static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) { (rc->recipient)?rc->recipient:"DEFAULT", rc->green, rc->red, - rc->group, + (int)rc->group, rc->after, rc->before, rc->options, @@ -106,7 +107,7 @@ static inline int rrdcalctemplate_add_template_from_config(RRDHOST *host, RRDCAL (rt->recipient)?rt->recipient:"DEFAULT", rt->green, rt->red, - rt->group, + (int)rt->group, rt->after, rt->before, rt->options, @@ -176,7 +177,7 @@ static inline int health_parse_duration(char *string, int *result) { } static inline int health_parse_delay( - size_t line, const char *path, const char *file, char *string, + size_t line, const char *filename, char *string, int *delay_up_duration, int *delay_down_duration, int *delay_max_duration, @@ -202,36 +203,36 @@ static inline int health_parse_delay( if(!strcasecmp(key, "up")) { if (!health_parse_duration(value, delay_up_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_up = 1; } else if(!strcasecmp(key, "down")) { if (!health_parse_duration(value, delay_down_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_down = 1; } else if(!strcasecmp(key, "multiplier")) { *delay_multiplier = strtof(value, NULL); if(isnan(*delay_multiplier) || isinf(*delay_multiplier) || islessequal(*delay_multiplier, 0)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_multiplier = 1; } else if(!strcasecmp(key, "max")) { if (!health_parse_duration(value, delay_max_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_max = 1; } else { - error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", - line, path, file, key); + error("Health configuration at line %zu of file '%s': unknown keyword '%s'", + line, filename, key); } } @@ -285,11 +286,11 @@ static inline uint32_t health_parse_options(const char *s) { } static inline int health_parse_db_lookup( - size_t line, const char *path, const char *file, char *string, - int *group_method, int *after, int *before, int *every, + size_t line, const char *filename, char *string, + RRDR_GROUPING *group_method, int *after, int *before, int *every, uint32_t *options, char **dimensions ) { - debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s/%s: %s", line, path, file, string); + debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s: %s", line, filename, string); if(*dimensions) freez(*dimensions); *dimensions = NULL; @@ -305,14 +306,14 @@ static inline int health_parse_db_lookup( while(*s && !isspace(*s)) s++; while(*s && isspace(*s)) *s++ = '\0'; if(!*s) { - error("Health configuration invalid chart calculation at line %zu of file '%s/%s': expected group method followed by the 'after' time, but got '%s'", - line, path, file, key); + error("Health configuration invalid chart calculation at line %zu of file '%s': expected group method followed by the 'after' time, but got '%s'", + line, filename, key); return 0; } - if((*group_method = web_client_api_request_v1_data_group(key, -1)) == -1) { - error("Health configuration at line %zu of file '%s/%s': invalid group method '%s'", - line, path, file, key); + if((*group_method = web_client_api_request_v1_data_group(key, RRDR_GROUPING_UNDEFINED)) == RRDR_GROUPING_UNDEFINED) { + error("Health configuration at line %zu of file '%s': invalid group method '%s'", + line, filename, key); return 0; } @@ -322,8 +323,8 @@ static inline int health_parse_db_lookup( while(*s && isspace(*s)) *s++ = '\0'; if(!health_parse_duration(key, after)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' after group method", - line, path, file, key); + error("Health configuration at line %zu of file '%s': invalid duration '%s' after group method", + line, filename, key); return 0; } @@ -343,8 +344,8 @@ static inline int health_parse_db_lookup( while(*s && isspace(*s)) *s++ = '\0'; if (!health_parse_duration(value, before)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid duration '%s' for '%s' keyword", + line, filename, value, key); } } else if(!strcasecmp(key, HEALTH_EVERY_KEY)) { @@ -353,8 +354,8 @@ static inline int health_parse_db_lookup( while(*s && isspace(*s)) *s++ = '\0'; if (!health_parse_duration(value, every)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid duration '%s' for '%s' keyword", + line, filename, value, key); } } else if(!strcasecmp(key, "absolute") || !strcasecmp(key, "abs") || !strcasecmp(key, "absolute_sum")) { @@ -384,17 +385,17 @@ static inline int health_parse_db_lookup( break; } else { - error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", - line, path, file, key); + error("Health configuration at line %zu of file '%s': unknown keyword '%s'", + line, filename, key); } } return 1; } -static inline char *health_source_file(size_t line, const char *path, const char *filename) { +static inline char *health_source_file(size_t line, const char *file) { char buffer[FILENAME_MAX + 1]; - snprintfz(buffer, FILENAME_MAX, "%zu@%s/%s", line, path, filename); + snprintfz(buffer, FILENAME_MAX, "%zu@%s", line, file); return strdupz(buffer); } @@ -405,8 +406,10 @@ static inline void strip_quotes(char *s) { } } -int health_readfile(RRDHOST *host, const char *path, const char *filename) { - debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename); +static int health_readfile(const char *filename, void *data) { + RRDHOST *host = (RRDHOST *)data; + + debug(D_HEALTH, "Health configuration reading file '%s'", filename); static uint32_t hash_alarm = 0, @@ -453,10 +456,9 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { hash_options = simple_uhash(HEALTH_OPTIONS_KEY); } - snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename); - FILE *fp = fopen(buffer, "r"); + FILE *fp = fopen(filename, "r"); if(!fp) { - error("Health configuration cannot read file '%s'.", buffer); + error("Health configuration cannot read file '%s'.", filename); return 0; } @@ -479,7 +481,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(append < HEALTH_CONF_MAX_LINE) continue; else { - error("Health configuration has too long muli-line at line %zu of file '%s/%s'.", line, path, filename); + error("Health configuration has too long muli-line at line %zu of file '%s'.", line, filename); } } append = 0; @@ -487,7 +489,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { char *key = s; while(*s && *s != ':') s++; if(!*s) { - error("Health configuration has invalid line %zu of file '%s/%s'. It does not contain a ':'. Ignoring it.", line, path, filename); + error("Health configuration has invalid line %zu of file '%s'. It does not contain a ':'. Ignoring it.", line, filename); continue; } *s = '\0'; @@ -498,12 +500,12 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { value = trim_all(value); if(!key) { - error("Health configuration has invalid line %zu of file '%s/%s'. Keyword is empty. Ignoring it.", line, path, filename); + error("Health configuration has invalid line %zu of file '%s'. Keyword is empty. Ignoring it.", line, filename); continue; } if(!value) { - error("Health configuration has invalid line %zu of file '%s/%s'. value is empty. Ignoring it.", line, path, filename); + error("Health configuration has invalid line %zu of file '%s'. value is empty. Ignoring it.", line, filename); continue; } @@ -524,7 +526,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { rc->next_event_id = 1; rc->name = strdupz(value); rc->hash = simple_hash(rc->name); - rc->source = health_source_file(line, path, filename); + rc->source = health_source_file(line, filename); rc->green = NAN; rc->red = NAN; rc->value = NAN; @@ -550,7 +552,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { rt = callocz(1, sizeof(RRDCALCTEMPLATE)); rt->name = strdupz(value); rt->hash_name = simple_hash(rt->name); - rt->source = health_source_file(line, path, filename); + rt->source = health_source_file(line, filename); rt->green = NAN; rt->red = NAN; rt->delay_multiplier = 1.0; @@ -566,10 +568,10 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(!simple_pattern_matches(os_pattern, host->os)) { if(rc) - debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rc->name, line, path, filename, os_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rc->name, line, filename, os_match); if(rt) - debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rt->name, line, path, filename, os_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rt->name, line, filename, os_match); ignore_this = 1; } @@ -582,10 +584,10 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(!simple_pattern_matches(host_pattern, host->hostname)) { if(rc) - debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rc->name, line, path, filename, host_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rc->name, line, filename, host_match); if(rt) - debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rt->name, line, path, filename, host_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rt->name, line, filename, host_match); ignore_this = 1; } @@ -596,8 +598,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { if(rc->chart) { if(strcmp(rc->chart, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->chart, value, value); + error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rc->name, key, rc->chart, value, value); freez(rc->chart); } @@ -605,29 +607,29 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { rc->hash_chart = simple_hash(rc->chart); } else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { - health_parse_db_lookup(line, path, filename, value, &rc->group, &rc->after, &rc->before, + health_parse_db_lookup(line, filename, value, &rc->group, &rc->after, &rc->before, &rc->update_every, &rc->options, &rc->dimensions); } else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { if(!health_parse_duration(value, &rc->update_every)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.", - line, path, filename, rc->name, key, value); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.", + line, filename, rc->name, key, value); } else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { char *e; rc->green = str2ld(value, &e); if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rc->name, key, e); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", + line, filename, rc->name, key, e); } } else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { char *e; rc->red = str2ld(value, &e); if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rc->name, key, e); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", + line, filename, rc->name, key, e); } } else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { @@ -635,8 +637,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rc->calculation = expression_parse(value, &failed_at, &error); if(!rc->calculation) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { @@ -644,8 +646,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rc->warning = expression_parse(value, &failed_at, &error); if(!rc->warning) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { @@ -653,15 +655,15 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rc->critical = expression_parse(value, &failed_at, &error); if(!rc->critical) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { if(rc->exec) { if(strcmp(rc->exec, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->exec, value, value); + error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rc->name, key, rc->exec, value, value); freez(rc->exec); } @@ -670,8 +672,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { if(rc->recipient) { if(strcmp(rc->recipient, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->recipient, value, value); + error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rc->name, key, rc->recipient, value, value); freez(rc->recipient); } @@ -680,8 +682,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { if(rc->units) { if(strcmp(rc->units, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->units, value, value); + error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rc->name, key, rc->units, value, value); freez(rc->units); } @@ -691,8 +693,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { if(rc->info) { if(strcmp(rc->info, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->info, value, value); + error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rc->name, key, rc->info, value, value); freez(rc->info); } @@ -700,22 +702,22 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { strip_quotes(rc->info); } else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { - health_parse_delay(line, path, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier); + health_parse_delay(line, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier); } else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { rc->options |= health_parse_options(value); } else { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has unknown key '%s'.", - line, path, filename, rc->name, key); + error("Health configuration at line %zu of file '%s' for alarm '%s' has unknown key '%s'.", + line, filename, rc->name, key); } } else if(rt) { if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { if(rt->context) { if(strcmp(rt->context, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->context, value, value); + error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rt->name, key, rt->context, value, value); freez(rt->context); } @@ -730,28 +732,28 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { rt->family_pattern = simple_pattern_create(rt->family_match, NULL, SIMPLE_PATTERN_EXACT); } else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { - health_parse_db_lookup(line, path, filename, value, &rt->group, &rt->after, &rt->before, + health_parse_db_lookup(line, filename, value, &rt->group, &rt->after, &rt->before, &rt->update_every, &rt->options, &rt->dimensions); } else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { if(!health_parse_duration(value, &rt->update_every)) - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' cannot parse duration: '%s'.", - line, path, filename, rt->name, key, value); + error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' cannot parse duration: '%s'.", + line, filename, rt->name, key, value); } else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { char *e; rt->green = str2ld(value, &e); if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rt->name, key, e); + error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", + line, filename, rt->name, key, e); } } else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { char *e; rt->red = str2ld(value, &e); if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rt->name, key, e); + error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", + line, filename, rt->name, key, e); } } else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { @@ -759,8 +761,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rt->calculation = expression_parse(value, &failed_at, &error); if(!rt->calculation) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rt->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { @@ -768,8 +770,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rt->warning = expression_parse(value, &failed_at, &error); if(!rt->warning) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rt->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { @@ -777,15 +779,15 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rt->critical = expression_parse(value, &failed_at, &error); if(!rt->critical) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rt->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { if(rt->exec) { if(strcmp(rt->exec, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->exec, value, value); + error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rt->name, key, rt->exec, value, value); freez(rt->exec); } @@ -794,8 +796,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { if(rt->recipient) { if(strcmp(rt->recipient, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->recipient, value, value); + error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rt->name, key, rt->recipient, value, value); freez(rt->recipient); } @@ -804,8 +806,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { if(rt->units) { if(strcmp(rt->units, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->units, value, value); + error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rt->name, key, rt->units, value, value); freez(rt->units); } @@ -815,8 +817,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { if(rt->info) { if(strcmp(rt->info, value) != 0) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->info, value, value); + error("Health configuration at line %zu of file '%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rt->name, key, rt->info, value, value); freez(rt->info); } @@ -824,19 +826,19 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { strip_quotes(rt->info); } else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { - health_parse_delay(line, path, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier); + health_parse_delay(line, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier); } else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { rt->options |= health_parse_options(value); } else { - error("Health configuration at line %zu of file '%s/%s' for template '%s' has unknown key '%s'.", - line, path, filename, rt->name, key); + error("Health configuration at line %zu of file '%s' for template '%s' has unknown key '%s'.", + line, filename, rt->name, key); } } else { - error("Health configuration at line %zu of file '%s/%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.", - line, path, filename, key); + error("Health configuration at line %zu of file '%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.", + line, filename, key); } } @@ -850,51 +852,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { return 1; } -void health_readdir(RRDHOST *host, const char *path) { - if(!host->health_enabled) return; - - size_t pathlen = strlen(path); - - debug(D_HEALTH, "Health configuration reading directory '%s'", path); - - DIR *dir = opendir(path); - if (!dir) { - error("Health configuration cannot open directory '%s'.", path); - return; - } - - struct dirent *de = NULL; - while ((de = readdir(dir))) { - size_t len = strlen(de->d_name); - - if(de->d_type == DT_DIR - && ( - (de->d_name[0] == '.' && de->d_name[1] == '\0') - || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') - )) { - debug(D_HEALTH, "Ignoring directory '%s'", de->d_name); - continue; - } - - else if(de->d_type == DT_DIR) { - char *s = mallocz(pathlen + strlen(de->d_name) + 2); - strcpy(s, path); - strcat(s, "/"); - strcat(s, de->d_name); - health_readdir(host, s); - freez(s); - continue; - } - - else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) && - len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { - health_readfile(host, path, de->d_name); - } - - else debug(D_HEALTH, "Ignoring file '%s'", de->d_name); - } - - closedir(dir); +void health_readdir(RRDHOST *host, const char *user_path, const char *stock_path, const char *subpath) { + if(unlikely(!host->health_enabled)) return; + recursive_config_double_dir_load(user_path, stock_path, subpath, health_readfile, (void *) host, 0); } - - diff --git a/src/health_json.c b/health/health_json.c index aba7425d..a049dc1b 100644 --- a/src/health_json.c +++ b/health/health_json.c @@ -1,5 +1,6 @@ -#define NETDATA_HEALTH_INTERNALS -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "health.h" static inline void health_string2json(BUFFER *wb, const char *prefix, const char *label, const char *value, const char *suffix) { if(value && *value) { diff --git a/src/health_log.c b/health/health_log.c index a44fbadb..dd51be2a 100644 --- a/src/health_log.c +++ b/health/health_log.c @@ -1,5 +1,6 @@ -#define NETDATA_HEALTH_INTERNALS -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "health.h" // ---------------------------------------------------------------------------- // health alarm log load/save diff --git a/src/adaptive_resortable_list.c b/libnetdata/adaptive_resortable_list/adaptive_resortable_list.c index c564efff..7f4c6c53 100644 --- a/src/adaptive_resortable_list.c +++ b/libnetdata/adaptive_resortable_list/adaptive_resortable_list.c @@ -1,4 +1,6 @@ -#include "adaptive_resortable_list.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" // the default processor() of the ARL // can be overwritten at arl_create() @@ -20,6 +22,15 @@ inline void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, cons // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, (unsigned long long)*d); } +inline void arl_callback_ssize_t(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; + (void)hash; + + register ssize_t *d = dst; + *d = (ssize_t)str2ll(value, NULL); + // fprintf(stderr, "name '%s' with hash %u and value '%s' is %zd\n", name, hash, value, *d); +} + // create a new ARL ARL_BASE *arl_create(const char *name, void (*processor)(const char *, uint32_t, const char *, void *), size_t rechecks) { ARL_BASE *base = callocz(1, sizeof(ARL_BASE)); diff --git a/src/adaptive_resortable_list.h b/libnetdata/adaptive_resortable_list/adaptive_resortable_list.h index d05a8ede..011ee73d 100644 --- a/src/adaptive_resortable_list.h +++ b/libnetdata/adaptive_resortable_list/adaptive_resortable_list.h @@ -1,43 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + #ifndef NETDATA_ADAPTIVE_RESORTABLE_LIST_H -#define NETDATA_ADAPTIVE_RESORTABLE_LIST_H - -/* - * ADAPTIVE RE-SORTABLE LIST - * This structure allows netdata to read a file of NAME VALUE lines - * in the fastest possible way. - * - * It maintains a linked list of all NAME (keywords), sorted in the - * same order as found in the source data file. - * The linked list is kept sorted at all times - the source file - * may change at any time, the list will adapt. - * - * The caller: - * - * 1. calls arl_create() to create a list - * - * 2. calls arl_expect() to register the expected keyword - * - * Then: - * - * 3. calls arl_begin() to initiate a data collection iteration. - * This is to be called just ONCE every time the source is re-scanned. - * - * 4. calls arl_check() for each line read from the file. - * - * Finally: - * - * 5. calls arl_free() to destroy this and free all memory. - * - * The program will call the processor() function, given to - * arl_create(), for each expected keyword found. - * The default processor() expects dst to be an unsigned long long *. - * - * LIMITATIONS - * DO NOT USE THIS IF THE A NAME/KEYWORD MAY APPEAR MORE THAN - * ONCE IN THE SOURCE DATA SET. - */ - -#include "common.h" +#define NETDATA_ADAPTIVE_RESORTABLE_LIST_H 1 #define ARL_ENTRY_FLAG_FOUND 0x01 // the entry has been found in the source data #define ARL_ENTRY_FLAG_EXPECTED 0x02 // the entry is expected by the program @@ -116,6 +82,7 @@ extern void arl_begin(ARL_BASE *base); extern void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst); extern void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, const char *value, void *dst); +extern void arl_callback_ssize_t(const char *name, uint32_t hash, const char *value, void *dst); // check a keyword against the ARL // this is to be called for each keyword read from source data diff --git a/src/avl.c b/libnetdata/avl/avl.c index a2c6911e..c44bef30 100644 --- a/src/avl.c +++ b/libnetdata/avl/avl.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "../libnetdata.h" /* ------------------------------------------------------------------------- */ /* @@ -10,7 +12,6 @@ * libavl - library for manipulation of binary trees. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software * Foundation, Inc. - * GNU Lesser General Public License */ @@ -44,7 +45,7 @@ avl *avl_insert(avl_tree *tree, avl *item) { avl *p, *q; /* Iterator, and parent. */ avl *n; /* Newly inserted node. */ avl *w; /* New root of rebalanced subtree. */ - int dir; /* Direction to descend. */ + unsigned char dir; /* Direction to descend. */ unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */ int k = 0; /* Number of cached results. */ @@ -61,7 +62,7 @@ avl *avl_insert(avl_tree *tree, avl *item) { if (p->avl_balance != 0) z = q, y = p, k = 0; - da[k++] = dir = (cmp > 0); + da[k++] = dir = (unsigned char)(cmp > 0); } n = q->avl_link[dir] = item; @@ -149,7 +150,7 @@ avl *avl_remove(avl_tree *tree, avl *item) { k = 0; p = (avl *) &tree->root; for(cmp = -1; cmp != 0; cmp = tree->compar(item, p)) { - int dir = (cmp > 0); + unsigned char dir = (unsigned char)(cmp > 0); pa[k] = p; da[k++] = dir; @@ -283,7 +284,7 @@ avl *avl_remove(avl_tree *tree, avl *item) { // --------------------------- // traversing -int avl_walker(avl *node, int (*callback)(void *entry, void *data), void *data) { +int avl_walker(avl *node, int (*callback)(void * /*entry*/, void * /*data*/), void *data) { int total = 0, ret = 0; if(node->avl_link[0]) { @@ -305,9 +306,9 @@ int avl_walker(avl *node, int (*callback)(void *entry, void *data), void *data) return total; } -int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *data) { - if(t->root) - return avl_walker(t->root, callback, data); +int avl_traverse(avl_tree *tree, int (*callback)(void * /*entry*/, void * /*data*/), void *data) { + if(tree->root) + return avl_walker(tree->root, callback, data); else return 0; } @@ -348,16 +349,16 @@ void avl_unlock(avl_tree_lock *t) { // --------------------------- // operations with locking -void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)) { - avl_init(&t->avl_tree, compar); +void avl_init_lock(avl_tree_lock *tree, int (*compar)(void * /*a*/, void * /*b*/)) { + avl_init(&tree->avl_tree, compar); #ifndef AVL_WITHOUT_PTHREADS int lock; #ifdef AVL_LOCK_WITH_MUTEX - lock = netdata_mutex_init(&t->mutex, NULL); + lock = netdata_mutex_init(&tree->mutex, NULL); #else - lock = netdata_rwlock_init(&t->rwlock); + lock = netdata_rwlock_init(&tree->rwlock); #endif if(lock != 0) @@ -366,38 +367,38 @@ void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)) { #endif /* AVL_WITHOUT_PTHREADS */ } -avl *avl_search_lock(avl_tree_lock *t, avl *a) { - avl_read_lock(t); - avl *ret = avl_search(&t->avl_tree, a); - avl_unlock(t); +avl *avl_search_lock(avl_tree_lock *tree, avl *item) { + avl_read_lock(tree); + avl *ret = avl_search(&tree->avl_tree, item); + avl_unlock(tree); return ret; } -avl * avl_remove_lock(avl_tree_lock *t, avl *a) { - avl_write_lock(t); - avl *ret = avl_remove(&t->avl_tree, a); - avl_unlock(t); +avl * avl_remove_lock(avl_tree_lock *tree, avl *item) { + avl_write_lock(tree); + avl *ret = avl_remove(&tree->avl_tree, item); + avl_unlock(tree); return ret; } -avl *avl_insert_lock(avl_tree_lock *t, avl *a) { - avl_write_lock(t); - avl * ret = avl_insert(&t->avl_tree, a); - avl_unlock(t); +avl *avl_insert_lock(avl_tree_lock *tree, avl *item) { + avl_write_lock(tree); + avl * ret = avl_insert(&tree->avl_tree, item); + avl_unlock(tree); return ret; } -int avl_traverse_lock(avl_tree_lock *t, int (*callback)(void *entry, void *data), void *data) { +int avl_traverse_lock(avl_tree_lock *tree, int (*callback)(void * /*entry*/, void * /*data*/), void *data) { int ret; - avl_read_lock(t); - ret = avl_traverse(&t->avl_tree, callback, data); - avl_unlock(t); + avl_read_lock(tree); + ret = avl_traverse(&tree->avl_tree, callback, data); + avl_unlock(tree); return ret; } -void avl_init(avl_tree *t, int (*compar)(void *a, void *b)) { - t->root = NULL; - t->compar = compar; +void avl_init(avl_tree *tree, int (*compar)(void * /*a*/, void * /*b*/)) { + tree->root = NULL; + tree->compar = compar; } -// ------------------
\ No newline at end of file +// ------------------ diff --git a/src/avl.h b/libnetdata/avl/avl.h index 19648cd1..070bb3d3 100644 --- a/src/avl.h +++ b/libnetdata/avl/avl.h @@ -1,7 +1,10 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later #ifndef _AVL_H #define _AVL_H 1 +#include "../libnetdata.h" + /* Maximum AVL tree height. */ #ifndef AVL_MAX_HEIGHT #define AVL_MAX_HEIGHT 92 @@ -56,31 +59,31 @@ typedef struct avl_tree_lock { * a is linked directly to the tree, so it has to * be properly allocated by the caller. */ -avl *avl_insert_lock(avl_tree_lock *t, avl *a) NEVERNULL WARNUNUSED; -avl *avl_insert(avl_tree *t, avl *a) NEVERNULL WARNUNUSED; +avl *avl_insert_lock(avl_tree_lock *tree, avl *item) NEVERNULL WARNUNUSED; +avl *avl_insert(avl_tree *tree, avl *item) NEVERNULL WARNUNUSED; /* Remove an element a from the AVL tree t * returns a pointer to the removed element * or NULL if an element equal to a is not found * (equal as returned by t->compar()) */ -avl *avl_remove_lock(avl_tree_lock *t, avl *a) WARNUNUSED; -avl *avl_remove(avl_tree *t, avl *a) WARNUNUSED; +avl *avl_remove_lock(avl_tree_lock *tree, avl *item) WARNUNUSED; +avl *avl_remove(avl_tree *tree, avl *item) WARNUNUSED; /* Find the element into the tree that equal to a * (equal as returned by t->compar()) * returns NULL is no element is equal to a */ -avl *avl_search_lock(avl_tree_lock *t, avl *a); -avl *avl_search(avl_tree *t, avl *a); +avl *avl_search_lock(avl_tree_lock *tree, avl *item); +avl *avl_search(avl_tree *tree, avl *item); /* Initialize the avl_tree_lock */ -void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)); -void avl_init(avl_tree *t, int (*compar)(void *a, void *b)); +void avl_init_lock(avl_tree_lock *tree, int (*compar)(void *a, void *b)); +void avl_init(avl_tree *tree, int (*compar)(void *a, void *b)); -int avl_traverse_lock(avl_tree_lock *t, int (*callback)(void *entry, void *data), void *data); -int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *data); +int avl_traverse_lock(avl_tree_lock *tree, int (*callback)(void *entry, void *data), void *data); +int avl_traverse(avl_tree *tree, int (*callback)(void *entry, void *data), void *data); #endif /* avl.h */ diff --git a/src/web_buffer.c b/libnetdata/buffer/buffer.c index 50c76f6d..50672324 100644 --- a/src/web_buffer.c +++ b/libnetdata/buffer/buffer.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" #define BUFFER_OVERFLOW_EOF "EOF" @@ -379,8 +381,7 @@ void buffer_free(BUFFER *b) { freez(b); } -void buffer_increase(BUFFER *b, size_t free_size_required) -{ +void buffer_increase(BUFFER *b, size_t free_size_required) { buffer_overflow_check(b); size_t left = b->size - b->len; diff --git a/src/web_buffer.h b/libnetdata/buffer/buffer.h index 694c9d4c..8e431bfd 100644 --- a/src/web_buffer.h +++ b/libnetdata/buffer/buffer.h @@ -1,6 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_WEB_BUFFER_H #define NETDATA_WEB_BUFFER_H 1 +#include "../libnetdata.h" + #define WEB_DATA_LENGTH_INCREASE_STEP 1024 typedef struct web_buffer { diff --git a/src/clocks.h b/libnetdata/clocks/clocks.h index ca571525..d576d86b 100644 --- a/src/clocks.h +++ b/libnetdata/clocks/clocks.h @@ -1,6 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_CLOCKS_H #define NETDATA_CLOCKS_H 1 +#include "../libnetdata.h" + #ifndef HAVE_STRUCT_TIMESPEC struct timespec { time_t tv_sec; /* seconds */ @@ -17,7 +21,10 @@ typedef unsigned long long msec_t; typedef unsigned long long usec_t; typedef long long susec_t; -typedef usec_t heartbeat_t; +typedef struct heartbeat { + usec_t monotonic; + usec_t realtime; +} heartbeat_t; /* Linux value is as good as any other */ #ifndef CLOCK_REALTIME @@ -105,7 +112,7 @@ extern time_t now_boottime_sec(void); extern usec_t now_boottime_usec(void); -extern usec_t timeval_usec(struct timeval *ts); +extern usec_t timeval_usec(struct timeval *tv); extern msec_t timeval_msec(struct timeval *tv); extern usec_t dt_usec(struct timeval *now, struct timeval *old); @@ -119,6 +126,8 @@ extern void heartbeat_init(heartbeat_t *hb); extern usec_t heartbeat_next(heartbeat_t *hb, usec_t tick); /* Returns elapsed time in microseconds since last heartbeat */ -extern usec_t heartbeat_dt_usec(heartbeat_t *hb); +extern usec_t heartbeat_monotonic_dt_to_now_usec(heartbeat_t *hb); + +extern int sleep_usec(usec_t usec); #endif /* NETDATA_CLOCKS_H */ diff --git a/src/appconfig.c b/libnetdata/config/appconfig.c index 2424864b..41153844 100644 --- a/src/appconfig.c +++ b/libnetdata/config/appconfig.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" #define CONFIG_FILE_LINE_MAX ((CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 1024) * 2) @@ -7,11 +9,11 @@ #define CONFIG_VALUE_LOADED 0x01 // has been loaded from the config #define CONFIG_VALUE_USED 0x02 // has been accessed from the program -#define CONFIG_VALUE_CHANGED 0x04 // has been changed from the loaded value +#define CONFIG_VALUE_CHANGED 0x04 // has been changed from the loaded value or the internal default value #define CONFIG_VALUE_CHECKED 0x08 // has been checked if the value is different from the default struct config_option { - avl avl; // the index - this has to be first! + avl avl; // the index entry of this entry - this has to be first! uint8_t flags; uint32_t hash; // a simple hash to speed up searching @@ -24,7 +26,7 @@ struct config_option { }; struct section { - avl avl; + avl avl; // the index entry of this section - this has to be first! uint32_t hash; // a simple hash to speed up searching // we first compare hashes, and only if the hashes are equal we do string comparisons @@ -40,25 +42,6 @@ struct section { // readers are protected using the rwlock in avl_tree_lock }; -static int appconfig_section_compare(void *a, void *b); - -struct config netdata_config = { - .sections = NULL, - .mutex = NETDATA_MUTEX_INITIALIZER, - .index = { - { NULL, appconfig_section_compare }, - AVL_LOCK_INITIALIZER - } -}; - -struct config stream_config = { - .sections = NULL, - .mutex = NETDATA_MUTEX_INITIALIZER, - .index = { - { NULL, appconfig_section_compare }, - AVL_LOCK_INITIALIZER - } -}; // ---------------------------------------------------------------------------- // locking @@ -104,7 +87,7 @@ static struct config_option *appconfig_option_index_find(struct section *co, con // ---------------------------------------------------------------------------- // config sections index -static int appconfig_section_compare(void *a, void *b) { +int appconfig_section_compare(void *a, void *b) { if(((struct section *)a)->hash < ((struct section *)b)->hash) return -1; else if(((struct section *)a)->hash > ((struct section *)b)->hash) return 1; else return strcmp(((struct section *)a)->name, ((struct section *)b)->name); @@ -445,7 +428,7 @@ int appconfig_load(struct config *root, char *filename, int overwrite_used) FILE *fp = fopen(filename, "r"); if(!fp) { - error("CONFIG: cannot open file '%s'", filename); + // info("CONFIG: cannot open file '%s'. Using internal defaults.", filename); return 0; } @@ -493,10 +476,8 @@ int appconfig_load(struct config *root, char *filename, int overwrite_used) error("CONFIG: ignoring line %d of file '%s', name is empty.", line, filename); continue; } - if(!value) { - debug(D_CONFIG, "CONFIG: ignoring line %d of file '%s', value is empty.", line, filename); - continue; - } + + if(!value) value = ""; struct config_option *cv = appconfig_option_index_find(co, name, 0); diff --git a/src/dictionary.c b/libnetdata/dictionary/dictionary.c index 512b4bbe..dd94a801 100644 --- a/src/dictionary.c +++ b/libnetdata/dictionary/dictionary.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" // ---------------------------------------------------------------------------- // dictionary statistics diff --git a/src/dictionary.h b/libnetdata/dictionary/dictionary.h index f028dbb3..61b9bfc6 100644 --- a/src/dictionary.h +++ b/libnetdata/dictionary/dictionary.h @@ -1,6 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_DICTIONARY_H #define NETDATA_DICTIONARY_H 1 +#include "../libnetdata.h" + struct dictionary_stats { unsigned long long inserts; unsigned long long deletes; @@ -35,7 +39,7 @@ typedef struct dictionary { extern DICTIONARY *dictionary_create(uint8_t flags); extern void dictionary_destroy(DICTIONARY *dict); -extern void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len); +extern void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len) NEVERNULL; extern void *dictionary_get(DICTIONARY *dict, const char *name); extern int dictionary_del(DICTIONARY *dict, const char *name); diff --git a/src/eval.c b/libnetdata/eval/eval.c index 84369f6d..0316edac 100644 --- a/src/eval.c +++ b/libnetdata/eval/eval.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" // ---------------------------------------------------------------------------- // data structures for storing the parsed expression in memory @@ -1057,33 +1059,33 @@ static inline EVAL_NODE *parse_full_expression(const char **string, int *error) // ---------------------------------------------------------------------------- // public API -int expression_evaluate(EVAL_EXPRESSION *exp) { - exp->error = EVAL_ERROR_OK; +int expression_evaluate(EVAL_EXPRESSION *expression) { + expression->error = EVAL_ERROR_OK; - buffer_reset(exp->error_msg); - exp->result = eval_node(exp, (EVAL_NODE *)exp->nodes, &exp->error); + buffer_reset(expression->error_msg); + expression->result = eval_node(expression, (EVAL_NODE *)expression->nodes, &expression->error); - if(unlikely(isnan(exp->result))) { - if(exp->error == EVAL_ERROR_OK) - exp->error = EVAL_ERROR_VALUE_IS_NAN; + if(unlikely(isnan(expression->result))) { + if(expression->error == EVAL_ERROR_OK) + expression->error = EVAL_ERROR_VALUE_IS_NAN; } - else if(unlikely(isinf(exp->result))) { - if(exp->error == EVAL_ERROR_OK) - exp->error = EVAL_ERROR_VALUE_IS_INFINITE; + else if(unlikely(isinf(expression->result))) { + if(expression->error == EVAL_ERROR_OK) + expression->error = EVAL_ERROR_VALUE_IS_INFINITE; } - else if(unlikely(exp->error == EVAL_ERROR_UNKNOWN_VARIABLE)) { + else if(unlikely(expression->error == EVAL_ERROR_UNKNOWN_VARIABLE)) { // although there is an unknown variable // the expression was evaluated successfully - exp->error = EVAL_ERROR_OK; + expression->error = EVAL_ERROR_OK; } - if(exp->error != EVAL_ERROR_OK) { - exp->result = NAN; + if(expression->error != EVAL_ERROR_OK) { + expression->result = NAN; - if(buffer_strlen(exp->error_msg)) - buffer_strcat(exp->error_msg, "; "); + if(buffer_strlen(expression->error_msg)) + buffer_strcat(expression->error_msg, "; "); - buffer_sprintf(exp->error_msg, "failed to evaluate expression with error %d (%s)", exp->error, expression_strerror(exp->error)); + buffer_sprintf(expression->error_msg, "failed to evaluate expression with error %d (%s)", expression->error, expression_strerror(expression->error)); return 0; } @@ -1134,14 +1136,14 @@ EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, in return exp; } -void expression_free(EVAL_EXPRESSION *exp) { - if(!exp) return; +void expression_free(EVAL_EXPRESSION *expression) { + if(!expression) return; - if(exp->nodes) eval_node_free((EVAL_NODE *)exp->nodes); - freez((void *)exp->source); - freez((void *)exp->parsed_as); - buffer_free(exp->error_msg); - freez(exp); + if(expression->nodes) eval_node_free((EVAL_NODE *)expression->nodes); + freez((void *)expression->source); + freez((void *)expression->parsed_as); + buffer_free(expression->error_msg); + freez(expression); } const char *expression_strerror(int error) { diff --git a/src/eval.h b/libnetdata/eval/eval.h index 6a5562fd..57dae9d0 100644 --- a/src/eval.h +++ b/libnetdata/eval/eval.h @@ -1,8 +1,22 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_EVAL_H -#define NETDATA_EVAL_H +#define NETDATA_EVAL_H 1 + +#include "../libnetdata.h" #define EVAL_MAX_VARIABLE_NAME_LENGTH 300 +typedef enum rrdcalc_status { + RRDCALC_STATUS_REMOVED = -2, + RRDCALC_STATUS_UNDEFINED = -1, + RRDCALC_STATUS_UNINITIALIZED = 0, + RRDCALC_STATUS_CLEAR = 1, + RRDCALC_STATUS_RAISED = 2, + RRDCALC_STATUS_WARNING = 3, + RRDCALC_STATUS_CRITICAL = 4 +} RRDCALC_STATUS; + typedef struct eval_variable { char *name; uint32_t hash; @@ -59,7 +73,7 @@ typedef struct eval_expression { extern EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, int *error); // free all resources allocated for an expression -extern void expression_free(EVAL_EXPRESSION *op); +extern void expression_free(EVAL_EXPRESSION *expression); // convert an error code to a message extern const char *expression_strerror(int error); @@ -69,4 +83,6 @@ extern const char *expression_strerror(int error); // 2 = FAILED, the error message is in: buffer_tostring(expression->error_msg) extern int expression_evaluate(EVAL_EXPRESSION *expression); +extern int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result); + #endif //NETDATA_EVAL_H diff --git a/src/inlined.h b/libnetdata/inlined.h index 9ab2dca7..6a5994c1 100644 --- a/src/inlined.h +++ b/libnetdata/inlined.h @@ -1,7 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_INLINED_H -#define NETDATA_INLINED_H +#define NETDATA_INLINED_H 1 -#include "common.h" +#include "libnetdata.h" #ifdef KERNEL_32BIT typedef uint32_t kernel_uint_t; @@ -245,12 +247,17 @@ static inline char *strncpyz(char *dst, const char *src, size_t n) { } static inline int read_file(const char *filename, char *buffer, size_t size) { + if(unlikely(!size)) return 3; + int fd = open(filename, O_RDONLY, 0666); - if(unlikely(fd == -1)) + if(unlikely(fd == -1)) { + buffer[0] = '\0'; return 1; + } ssize_t r = read(fd, buffer, size); if(unlikely(r == -1)) { + buffer[0] = '\0'; close(fd); return 2; } diff --git a/src/common.c b/libnetdata/libnetdata.c index 94fd5e42..de330cae 100644 --- a/src/common.c +++ b/libnetdata/libnetdata.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "libnetdata.h" #ifdef __APPLE__ #define INHERIT_NONE 0 @@ -8,17 +10,6 @@ # define MADV_DONTFORK INHERIT_NONE #endif /* __FreeBSD__ || __APPLE__*/ -char *netdata_configured_hostname = NULL; -char *netdata_configured_config_dir = NULL; -char *netdata_configured_log_dir = NULL; -char *netdata_configured_plugins_dir = NULL; -char *netdata_configured_web_dir = NULL; -char *netdata_configured_cache_dir = NULL; -char *netdata_configured_varlib_dir = NULL; -char *netdata_configured_home_dir = NULL; -char *netdata_configured_host_prefix = NULL; -char *netdata_configured_timezone = NULL; - struct rlimit rlimit_nofile = { .rlim_cur = 1024, .rlim_max = 1024 }; int enable_ksm = 1; @@ -36,182 +27,172 @@ const char *program_version = VERSION; // routines. #ifdef NETDATA_LOG_ALLOCATIONS -static struct memory_statistics { - volatile size_t malloc_calls_made; - volatile size_t calloc_calls_made; - volatile size_t realloc_calls_made; - volatile size_t strdup_calls_made; - volatile size_t free_calls_made; - volatile size_t memory_calls_made; - volatile size_t allocated_memory; - volatile size_t mmapped_memory; -} memory_statistics; - -static inline void print_allocations(const char *file, const char *function, const unsigned long line) { - static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - //if(unlikely(!(memory_statistics.memory_calls_made % 5))) { - fprintf(stderr, "(%04lu@%-10.10s:%-15.15s): Allocated %zu KB (+%zu B), mmapped %zu KB (+%zu B): malloc %zu (+%zu), calloc %zu (+%zu), realloc %zu (+%zu), strdup %zu (+%zu), free %zu (+%zu)\n", - line, file, function, - (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory, - (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory, - memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made, - memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made, - memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made, - memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made, - memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made - ); - - memcpy(&old, &memory_statistics, sizeof(struct memory_statistics)); - //} +static __thread struct memory_statistics { + volatile ssize_t malloc_calls_made; + volatile ssize_t calloc_calls_made; + volatile ssize_t realloc_calls_made; + volatile ssize_t strdup_calls_made; + volatile ssize_t free_calls_made; + volatile ssize_t memory_calls_made; + volatile ssize_t allocated_memory; + volatile ssize_t mmapped_memory; +} memory_statistics = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +__thread size_t log_thread_memory_allocations = 0; + +static inline void print_allocations(const char *file, const char *function, const unsigned long line, const char *type, size_t size) { + static __thread struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + fprintf(stderr, "%s iteration %zu MEMORY TRACE: %lu@%s : %s : %s : %zu\n", + netdata_thread_tag(), + log_thread_memory_allocations, + line, file, function, + type, size + ); + + fprintf(stderr, "%s iteration %zu MEMORY ALLOCATIONS: (%04lu@%-40.40s:%-40.40s): Allocated %zd KB (%+zd B), mmapped %zd KB (%+zd B): %s : malloc %zd (%+zd), calloc %zd (%+zd), realloc %zd (%+zd), strdup %zd (%+zd), free %zd (%+zd)\n", + netdata_thread_tag(), + log_thread_memory_allocations, + line, file, function, + (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory, + (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory, + type, + memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made, + memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made, + memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made, + memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made, + memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made + ); + + memcpy(&old, &memory_statistics, sizeof(struct memory_statistics)); } -static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) { -#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) - __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST); -#else - // this is for debugging - we don't care locking it - memory_statistics.memory_calls_made++; - memory_statistics.malloc_calls_made++; - memory_statistics.allocated_memory += size; -#endif - print_allocations(file, function, line); +static inline void mmap_accounting(size_t size) { + if(log_thread_memory_allocations) { + memory_statistics.memory_calls_made++; + memory_statistics.mmapped_memory += size; + } } -static inline void mmap_accounting(size_t size) { -#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) - __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.mmapped_memory, size, __ATOMIC_SEQ_CST); -#else - // this is for debugging - we don't care locking it - memory_statistics.memory_calls_made++; - memory_statistics.mmapped_memory += size; -#endif +void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) { + if(log_thread_memory_allocations) { + memory_statistics.memory_calls_made++; + memory_statistics.malloc_calls_made++; + memory_statistics.allocated_memory += size; + print_allocations(file, function, line, "malloc()", size); + } + + size_t *n = (size_t *)malloc(sizeof(size_t) + size); + if (unlikely(!n)) fatal("mallocz() cannot allocate %zu bytes of memory.", size); + *n = size; + return (void *)&n[1]; } -static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) { -#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) - __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.calloc_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST); -#else - // this is for debugging - we don't care locking it - memory_statistics.memory_calls_made++; - memory_statistics.calloc_calls_made++; - memory_statistics.allocated_memory += size; -#endif - print_allocations(file, function, line); +void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) { + size = nmemb * size; + + if(log_thread_memory_allocations) { + memory_statistics.memory_calls_made++; + memory_statistics.calloc_calls_made++; + memory_statistics.allocated_memory += size; + print_allocations(file, function, line, "calloc()", size); + } + + size_t *n = (size_t *)calloc(1, sizeof(size_t) + size); + if (unlikely(!n)) fatal("callocz() cannot allocate %zu bytes of memory.", size); + *n = size; + return (void *)&n[1]; } -static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) { - (void)ptr; +void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) { + if(!ptr) return mallocz_int(file, function, line, size); -#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) - __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.realloc_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST); -#else - // this is for debugging - we don't care locking it - memory_statistics.memory_calls_made++; - memory_statistics.realloc_calls_made++; - memory_statistics.allocated_memory += size; -#endif - print_allocations(file, function, line); + size_t *n = (size_t *)ptr; + n--; + size_t old_size = *n; + + n = realloc(n, sizeof(size_t) + size); + if (unlikely(!n)) fatal("reallocz() cannot allocate %zu bytes of memory (from %zu bytes).", size, old_size); + + if(log_thread_memory_allocations) { + memory_statistics.memory_calls_made++; + memory_statistics.realloc_calls_made++; + memory_statistics.allocated_memory += (size - old_size); + print_allocations(file, function, line, "realloc()", size - old_size); + } + + *n = size; + return (void *)&n[1]; } -static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) { +char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) { size_t size = strlen(s) + 1; -#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) - __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.strdup_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST); -#else - // this is for debugging - we don't care locking it - memory_statistics.memory_calls_made++; - memory_statistics.strdup_calls_made++; - memory_statistics.allocated_memory += size; -#endif - print_allocations(file, function, line); + if(log_thread_memory_allocations) { + memory_statistics.memory_calls_made++; + memory_statistics.strdup_calls_made++; + memory_statistics.allocated_memory += size; + print_allocations(file, function, line, "strdup()", size); + } + + size_t *n = (size_t *)malloc(sizeof(size_t) + size); + if (unlikely(!n)) fatal("strdupz() cannot allocate %zu bytes of memory.", size); + + *n = size; + char *t = (char *)&n[1]; + strcpy(t, s); + return t; } -static inline void free_accounting(const char *file, const char *function, const unsigned long line, void *ptr) { - (void)file; - (void)function; - (void)line; +void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) { + if(unlikely(!ptr)) return; - if(likely(ptr)) { -#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS) - __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST); - __atomic_fetch_add(&memory_statistics.free_calls_made, 1, __ATOMIC_SEQ_CST); -#else - // this is for debugging - we don't care locking it + size_t *n = (size_t *)ptr; + n--; + size_t size = *n; + + if(log_thread_memory_allocations) { memory_statistics.memory_calls_made++; memory_statistics.free_calls_made++; -#endif + memory_statistics.allocated_memory -= size; + print_allocations(file, function, line, "free()", size); } -} -#endif -#ifdef NETDATA_LOG_ALLOCATIONS -char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) { - strdup_accounting(file, function, line, s); + free(n); +} #else -char *strdupz(const char *s) { -#endif +char *strdupz(const char *s) { char *t = strdup(s); if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s); return t; } -#ifdef NETDATA_LOG_ALLOCATIONS -void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) { - malloc_accounting(file, function, line, size); -#else -void *mallocz(size_t size) { -#endif +void freez(void *ptr) { + free(ptr); +} +void *mallocz(size_t size) { void *p = malloc(size); if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size); return p; } -#ifdef NETDATA_LOG_ALLOCATIONS -void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) { - calloc_accounting(file, function, line, nmemb * size); -#else void *callocz(size_t nmemb, size_t size) { -#endif - void *p = calloc(nmemb, size); if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size); return p; } -#ifdef NETDATA_LOG_ALLOCATIONS -void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) { - realloc_accounting(file, function, line, ptr, size); -#else void *reallocz(void *ptr, size_t size) { -#endif - void *p = realloc(ptr, size); if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size); return p; } -#ifdef NETDATA_LOG_ALLOCATIONS -void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) { - free_accounting(file, function, line, ptr); -#else -void freez(void *ptr) { #endif - free(ptr); -} +// -------------------------------------------------------------------------------------------------------------------- void json_escape_string(char *dst, const char *src, size_t size) { const char *t; @@ -244,52 +225,6 @@ void json_fix_string(char *s) { } } -int sleep_usec(usec_t usec) { - -#ifndef NETDATA_WITH_USLEEP - // we expect microseconds (1.000.000 per second) - // but timespec is nanoseconds (1.000.000.000 per second) - struct timespec rem, req = { - .tv_sec = (time_t) (usec / 1000000), - .tv_nsec = (suseconds_t) ((usec % 1000000) * 1000) - }; - - while (nanosleep(&req, &rem) == -1) { - if (likely(errno == EINTR)) { - debug(D_SYSTEM, "nanosleep() interrupted (while sleeping for %llu microseconds).", usec); - req.tv_sec = rem.tv_sec; - req.tv_nsec = rem.tv_nsec; - } else { - error("Cannot nanosleep() for %llu microseconds.", usec); - break; - } - } - - return 0; -#else - int ret = usleep(usec); - if(unlikely(ret == -1 && errno == EINVAL)) { - // on certain systems, usec has to be up to 999999 - if(usec > 999999) { - int counter = usec / 999999; - while(counter--) - usleep(999999); - - usleep(usec % 999999); - } - else { - error("Cannot usleep() for %llu microseconds.", usec); - return ret; - } - } - - if(ret != 0) - error("usleep() failed for %llu microseconds.", usec); - - return ret; -#endif -} - unsigned char netdata_map_chart_names[256] = { [0] = '\0', // [1] = '_', // @@ -1183,124 +1118,6 @@ int snprintfz(char *dst, size_t n, const char *fmt, ...) { return ret; } -// ---------------------------------------------------------------------------- -// system functions -// to retrieve settings of the system - -int processors = 1; -long get_system_cpus(void) { - processors = 1; - - #ifdef __APPLE__ - int32_t tmp_processors; - - if (unlikely(GETSYSCTL_BY_NAME("hw.logicalcpu", tmp_processors))) { - error("Assuming system has %d processors.", processors); - } else { - processors = tmp_processors; - } - - return processors; - #elif __FreeBSD__ - int32_t tmp_processors; - - if (unlikely(GETSYSCTL_BY_NAME("hw.ncpu", tmp_processors))) { - error("Assuming system has %d processors.", processors); - } else { - processors = tmp_processors; - } - - return processors; - #else - - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix); - - procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); - if(!ff) { - error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors); - return processors; - } - - ff = procfile_readall(ff); - if(!ff) { - error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors); - return processors; - } - - processors = 0; - unsigned int i; - for(i = 0; i < procfile_lines(ff); i++) { - if(!procfile_linewords(ff, i)) continue; - - if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++; - } - processors--; - if(processors < 1) processors = 1; - - procfile_close(ff); - - debug(D_SYSTEM, "System has %d processors.", processors); - return processors; - - #endif /* __APPLE__, __FreeBSD__ */ -} - -pid_t pid_max = 32768; -pid_t get_system_pid_max(void) { - #ifdef __APPLE__ - // As we currently do not know a solution to query pid_max from the os - // we use the number defined in bsd/sys/proc_internal.h in XNU sources - pid_max = 99999; - return pid_max; - #elif __FreeBSD__ - int32_t tmp_pid_max; - - if (unlikely(GETSYSCTL_BY_NAME("kern.pid_max", tmp_pid_max))) { - pid_max = 99999; - error("Assuming system's maximum pid is %d.", pid_max); - } else { - pid_max = tmp_pid_max; - } - - return pid_max; - #else - - static char read = 0; - if(unlikely(read)) return pid_max; - read = 1; - - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", netdata_configured_host_prefix); - - unsigned long long max = 0; - if(read_single_number_file(filename, &max) != 0) { - error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max); - return pid_max; - } - - if(!max) { - error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max); - return pid_max; - } - - pid_max = (pid_t) max; - return pid_max; - - #endif /* __APPLE__, __FreeBSD__ */ -} - -unsigned int hz; -void get_system_HZ(void) { - long ticks; - - if ((ticks = sysconf(_SC_CLK_TCK)) == -1) { - error("Cannot get system clock ticks"); - } - - hz = (unsigned int) ticks; -} - /* // poor man cycle counting static unsigned long tsc; @@ -1359,3 +1176,272 @@ int recursively_delete_dir(const char *path, const char *reason) { return ret; } + +static int is_virtual_filesystem(const char *path, char **reason) { + +#if defined(__APPLE__) || defined(__FreeBSD__) + (void)path; + (void)reason; +#else + struct statfs stat; + // stat.f_fsid.__val[0] is a file system id + // stat.f_fsid.__val[1] is the inode + // so their combination uniquely identifies the file/dir + + if (statfs(path, &stat) == -1) { + if(reason) *reason = "failed to statfs()"; + return -1; + } + + if(stat.f_fsid.__val[0] != 0 || stat.f_fsid.__val[1] != 0) { + errno = EINVAL; + if(reason) *reason = "is not a virtual file system"; + return -1; + } +#endif + + return 0; +} + +int verify_netdata_host_prefix() { + if(!netdata_configured_host_prefix) + netdata_configured_host_prefix = ""; + + if(!*netdata_configured_host_prefix) + return 0; + + char buffer[FILENAME_MAX + 1]; + char *path = netdata_configured_host_prefix; + char *reason = "unknown reason"; + errno = 0; + + struct stat sb; + if (stat(path, &sb) == -1) { + reason = "failed to stat()"; + goto failed; + } + + if((sb.st_mode & S_IFMT) != S_IFDIR) { + errno = EINVAL; + reason = "is not a directory"; + goto failed; + } + + path = buffer; + snprintfz(path, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix); + if(is_virtual_filesystem(path, &reason) == -1) + goto failed; + + snprintfz(path, FILENAME_MAX, "%s/sys", netdata_configured_host_prefix); + if(is_virtual_filesystem(path, &reason) == -1) + goto failed; + + if(netdata_configured_host_prefix && *netdata_configured_host_prefix) + info("Using host prefix directory '%s'", netdata_configured_host_prefix); + + return 0; + +failed: + error("Ignoring host prefix '%s': path '%s' %s", netdata_configured_host_prefix, path, reason); + netdata_configured_host_prefix = ""; + return -1; +} + +char *strdupz_path_subpath(const char *path, const char *subpath) { + if(unlikely(!path || !*path)) path = "."; + if(unlikely(!subpath)) subpath = ""; + + // skip trailing slashes in path + size_t len = strlen(path); + while(len > 0 && path[len - 1] == '/') len--; + + // skip leading slashes in subpath + while(subpath[0] == '/') subpath++; + + // if the last character in path is / and (there is a subpath or path is now empty) + // keep the trailing slash in path and remove the additional slash + char *slash = "/"; + if(path[len] == '/' && (*subpath || len == 0)) { + slash = ""; + len++; + } + else if(!*subpath) { + // there is no subpath + // no need for trailing slash + slash = ""; + } + + char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%.*s%s%s", (int)len, path, slash, subpath); + return strdupz(buffer); +} + +int path_is_dir(const char *path, const char *subpath) { + char *s = strdupz_path_subpath(path, subpath); + + size_t max_links = 100; + + int is_dir = 0; + struct stat statbuf; + while(max_links-- && stat(s, &statbuf) == 0) { + if((statbuf.st_mode & S_IFMT) == S_IFDIR) { + is_dir = 1; + break; + } + else if((statbuf.st_mode & S_IFMT) == S_IFLNK) { + char buffer[FILENAME_MAX + 1]; + ssize_t l = readlink(s, buffer, FILENAME_MAX); + if(l > 0) { + buffer[l] = '\0'; + freez(s); + s = strdupz(buffer); + continue; + } + else { + is_dir = 0; + break; + } + } + else { + is_dir = 0; + break; + } + } + + freez(s); + return is_dir; +} + +int path_is_file(const char *path, const char *subpath) { + char *s = strdupz_path_subpath(path, subpath); + + size_t max_links = 100; + + int is_file = 0; + struct stat statbuf; + while(max_links-- && stat(s, &statbuf) == 0) { + if((statbuf.st_mode & S_IFMT) == S_IFREG) { + is_file = 1; + break; + } + else if((statbuf.st_mode & S_IFMT) == S_IFLNK) { + char buffer[FILENAME_MAX + 1]; + ssize_t l = readlink(s, buffer, FILENAME_MAX); + if(l > 0) { + buffer[l] = '\0'; + freez(s); + s = strdupz(buffer); + continue; + } + else { + is_file = 0; + break; + } + } + else { + is_file = 0; + break; + } + } + + freez(s); + return is_file; +} + +void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath, int (*callback)(const char *filename, void *data), void *data, size_t depth) { + if(depth > 3) { + error("CONFIG: Max directory depth reached while reading user path '%s', stock path '%s', subpath '%s'", user_path, stock_path, subpath); + return; + } + + char *udir = strdupz_path_subpath(user_path, subpath); + char *sdir = strdupz_path_subpath(stock_path, subpath); + + debug(D_HEALTH, "CONFIG traversing user-config directory '%s', stock config directory '%s'", udir, sdir); + + DIR *dir = opendir(udir); + if (!dir) { + error("CONFIG cannot open user-config directory '%s'.", udir); + } + else { + struct dirent *de = NULL; + while((de = readdir(dir))) { + if(de->d_type == DT_DIR || de->d_type == DT_LNK) { + if( !de->d_name[0] || + (de->d_name[0] == '.' && de->d_name[1] == '\0') || + (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') + ) { + debug(D_HEALTH, "CONFIG ignoring user-config directory '%s/%s'", udir, de->d_name); + continue; + } + + if(path_is_dir(udir, de->d_name)) { + recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1); + continue; + } + } + + if(de->d_type == DT_REG || de->d_type == DT_LNK) { + size_t len = strlen(de->d_name); + if(path_is_file(udir, de->d_name) && + len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { + char *filename = strdupz_path_subpath(udir, de->d_name); + callback(filename, data); + freez(filename); + } + else + debug(D_HEALTH, "CONFIG ignoring user-config file '%s/%s'", udir, de->d_name); + } + } + + closedir(dir); + } + + debug(D_HEALTH, "CONFIG traversing stock config directory '%s', user config directory '%s'", sdir, udir); + + dir = opendir(sdir); + if (!dir) { + error("CONFIG cannot open stock config directory '%s'.", sdir); + } + else { + struct dirent *de = NULL; + while((de = readdir(dir))) { + if(de->d_type == DT_DIR || de->d_type == DT_LNK) { + if( !de->d_name[0] || + (de->d_name[0] == '.' && de->d_name[1] == '\0') || + (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') + ) { + debug(D_HEALTH, "CONFIG ignoring stock config directory '%s/%s'", sdir, de->d_name); + continue; + } + + if(path_is_dir(sdir, de->d_name)) { + // we recurse in stock subdirectory, only when there is no corresponding + // user subdirectory - to avoid reading the files twice + + if(!path_is_dir(udir, de->d_name)) + recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1); + + continue; + } + } + + if(de->d_type == DT_REG || de->d_type == DT_LNK) { + size_t len = strlen(de->d_name); + if(path_is_file(sdir, de->d_name) && !path_is_file(udir, de->d_name) && + len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { + char *filename = strdupz_path_subpath(sdir, de->d_name); + callback(filename, data); + freez(filename); + } + else + debug(D_HEALTH, "CONFIG ignoring stock config file '%s/%s'", sdir, de->d_name); + } + } + + closedir(dir); + } + + freez(udir); + freez(sdir); +} diff --git a/src/common.h b/libnetdata/libnetdata.h index 15fc50a6..0bac3dc8 100644 --- a/src/common.h +++ b/libnetdata/libnetdata.h @@ -1,10 +1,16 @@ -#ifndef NETDATA_COMMON_H -#define NETDATA_COMMON_H 1 +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_LIB_H +#define NETDATA_LIB_H 1 #ifdef HAVE_CONFIG_H #include <config.h> #endif +#define OS_LINUX 1 +#define OS_FREEBSD 2 +#define OS_MACOS 3 + // ---------------------------------------------------------------------------- // system include files for all netdata C programs @@ -14,9 +20,9 @@ #if defined(HAVE_JEMALLOC_JEMALLOC_H) #include <jemalloc/jemalloc.h> -#else +#else // !defined(HAVE_JEMALLOC_JEMALLOC_H) #include <malloc.h> -#endif +#endif // !defined(HAVE_JEMALLOC_JEMALLOC_H) #elif defined(ENABLE_TCMALLOC) @@ -28,7 +34,18 @@ #include <malloc.h> #endif /* __FreeBSD__ || __APPLE__ */ -#endif +#endif /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */ + +// ---------------------------------------------------------------------------- + +#if defined(__FreeBSD__) +#include <pthread_np.h> +#define NETDATA_OS_TYPE "freebsd" +#elif defined(__APPLE__) +#define NETDATA_OS_TYPE "macos" +#else +#define NETDATA_OS_TYPE "linux" +#endif /* __FreeBSD__, __APPLE__*/ #include <pthread.h> #include <errno.h> @@ -42,41 +59,20 @@ #include <arpa/inet.h> #include <netinet/tcp.h> #include <sys/ioctl.h> - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif - -#ifdef HAVE_RESOLV_H -#include <resolv.h> -#endif - +#include <libgen.h> #include <dirent.h> #include <fcntl.h> #include <getopt.h> #include <grp.h> #include <pwd.h> #include <locale.h> - -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif - #include <net/if.h> - #include <poll.h> #include <signal.h> #include <syslog.h> #include <sys/mman.h> - -#ifdef HAVE_SYS_PRCTL_H -#include <sys/prctl.h> -#endif - #include <sys/resource.h> #include <sys/socket.h> -#include <sys/stat.h> -#include <sys/statvfs.h> #include <sys/syscall.h> #include <sys/time.h> #include <sys/types.h> @@ -86,6 +82,42 @@ #include <unistd.h> #include <uuid/uuid.h> +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#ifdef HAVE_RESOLV_H +#include <resolv.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif + +#ifdef HAVE_SYS_STATFS_H +#include <sys/statfs.h> +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif + +#ifdef HAVE_SYS_STATVFS_H +#include <sys/statvfs.h> +#endif + // #1408 #ifdef MAJOR_IN_MKDEV #include <sys/mkdev.h> @@ -94,10 +126,6 @@ #include <sys/sysmacros.h> #endif -/* -#include <mntent.h> -*/ - #ifdef STORAGE_WITH_MATH #include <math.h> #include <float.h> @@ -117,27 +145,6 @@ #include <sys/capability.h> #endif -// ---------------------------------------------------------------------------- -// netdata chart priorities - -// This is a work in progress - to scope is to collect here all chart priorities. -// These should be based on the CONTEXT of the charts + the chart id when needed -// - for each SECTION +1000 (or +X000 for big sections) -// - for each FAMILY +100 -// - for each CHART +10 - -// Memory Section - 1xxx -#define NETDATA_CHART_PRIO_MEM_SYSTEM 1000 -#define NETDATA_CHART_PRIO_MEM_SYSTEM_AVAILABLE 1010 -#define NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED 1020 -#define NETDATA_CHART_PRIO_MEM_SYSTEM_PGFAULTS 1030 -#define NETDATA_CHART_PRIO_MEM_KERNEL 1100 -#define NETDATA_CHART_PRIO_MEM_SLAB 1200 -#define NETDATA_CHART_PRIO_MEM_HUGEPAGES 1250 -#define NETDATA_CHART_PRIO_MEM_KSM 1300 -#define NETDATA_CHART_PRIO_MEM_NUMA 1400 -#define NETDATA_CHART_PRIO_MEM_HW 1500 - // ---------------------------------------------------------------------------- // netdata common definitions @@ -197,92 +204,6 @@ #define GUID_LEN 36 -// ---------------------------------------------------------------------------- -// netdata include files - -#include "clocks.h" -#include "log.h" -#include "threads.h" -#include "locks.h" -#include "simple_pattern.h" -#include "avl.h" -#include "global_statistics.h" -#include "storage_number.h" -#include "web_buffer.h" -#include "web_buffer_svg.h" -#include "url.h" -#include "popen.h" - -#include "procfile.h" -#include "appconfig.h" -#include "dictionary.h" -#include "proc_self_mountinfo.h" -#include "plugin_checks.h" -#include "plugin_idlejitter.h" -#include "plugin_nfacct.h" - -#if defined(__FreeBSD__) -#include <pthread_np.h> -#include "plugin_freebsd.h" -#define NETDATA_OS_TYPE "freebsd" -#elif defined(__APPLE__) -#include "plugin_macos.h" -#define NETDATA_OS_TYPE "macos" -#else -#include "plugin_proc.h" -#include "plugin_proc_diskspace.h" -#define NETDATA_OS_TYPE "linux" -#endif /* __FreeBSD__, __APPLE__*/ - -typedef enum rrdcalc_status { - RRDCALC_STATUS_REMOVED = -2, - RRDCALC_STATUS_UNDEFINED = -1, - RRDCALC_STATUS_UNINITIALIZED = 0, - RRDCALC_STATUS_CLEAR = 1, - RRDCALC_STATUS_RAISED = 2, - RRDCALC_STATUS_WARNING = 3, - RRDCALC_STATUS_CRITICAL = 4 -} RRDCALC_STATUS; - -#include "eval.h" -#include "health.h" - -#include "statistical.h" -#include "socket.h" -#include "rrd.h" -#include "plugin_tc.h" -#include "plugins_d.h" -#include "statsd.h" -#include "rrd2json.h" -#include "rrd2json_api_old.h" -#include "web_client.h" -#include "web_server.h" -#include "registry.h" -#include "signals.h" -#include "daemon.h" -#include "main.h" -#include "unit_test.h" -#include "ipc.h" -#include "backends.h" -#include "backend_prometheus.h" -#include "inlined.h" -#include "adaptive_resortable_list.h" -#include "rrdpush.h" -#include "web_api_v1.h" -#include "web_api_old.h" - -extern char *netdata_configured_hostname; -extern char *netdata_configured_config_dir; -extern char *netdata_configured_log_dir; -extern char *netdata_configured_plugins_dir_base; -extern char *netdata_configured_plugins_dir; -extern char *netdata_configured_web_dir; -extern char *netdata_configured_cache_dir; -extern char *netdata_configured_varlib_dir; -extern char *netdata_configured_home_dir; -extern char *netdata_configured_host_prefix; -extern char *netdata_configured_timezone; - extern void netdata_fix_chart_id(char *s); extern void netdata_fix_chart_name(char *s); @@ -296,6 +217,7 @@ extern int snprintfz(char *dst, size_t n, const char *fmt, ...) PRINTFLIKE(3, 4 // memory allocation functions that handle failures #ifdef NETDATA_LOG_ALLOCATIONS +extern __thread size_t log_thread_memory_allocations; #define strdupz(s) strdupz_int(__FILE__, __FUNCTION__, __LINE__, s) #define callocz(nmemb, size) callocz_int(__FILE__, __FUNCTION__, __LINE__, nmemb, size) #define mallocz(size) mallocz_int(__FILE__, __FUNCTION__, __LINE__, size) @@ -307,13 +229,13 @@ extern void *callocz_int(const char *file, const char *function, const unsigned extern void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size); extern void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size); extern void freez_int(const char *file, const char *function, const unsigned long line, void *ptr); -#else +#else // NETDATA_LOG_ALLOCATIONS extern char *strdupz(const char *s) MALLOCLIKE NEVERNULL; extern void *callocz(size_t nmemb, size_t size) MALLOCLIKE NEVERNULL; extern void *mallocz(size_t size) MALLOCLIKE NEVERNULL; extern void *reallocz(void *ptr, size_t size) MALLOCLIKE NEVERNULL; extern void freez(void *ptr); -#endif +#endif // NETDATA_LOG_ALLOCATIONS extern void json_escape_string(char *dst, const char *src, size_t size); extern void json_fix_string(char *s); @@ -327,19 +249,9 @@ extern struct rlimit rlimit_nofile; extern int enable_ksm; -extern int sleep_usec(usec_t usec); - extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len); -extern int processors; -extern long get_system_cpus(void); - -extern pid_t pid_max; -extern pid_t get_system_pid_max(void); - -/* Number of ticks per second */ -extern unsigned int hz; -extern void get_system_HZ(void); +extern int verify_netdata_host_prefix(); extern int recursively_delete_dir(const char *path, const char *reason); @@ -348,6 +260,18 @@ extern const char *os_type; extern const char *program_version; +extern char *strdupz_path_subpath(const char *path, const char *subpath); +extern int path_is_dir(const char *path, const char *subpath); +extern int path_is_file(const char *path, const char *subpath); +extern void recursive_config_double_dir_load( + const char *user_path + , const char *stock_path + , const char *subpath + , int (*callback)(const char *filename, void *data) + , void *data + , size_t depth +); + /* fix for alpine linux */ #ifndef RUSAGE_THREAD #ifdef RUSAGE_CHILDREN @@ -357,4 +281,28 @@ extern const char *program_version; #define BITS_IN_A_KILOBIT 1000 -#endif /* NETDATA_COMMON_H */ + +extern void netdata_cleanup_and_exit(int ret) NORETURN; +extern char *netdata_configured_host_prefix; + +#include "os.h" +#include "storage_number/storage_number.h" +#include "threads/threads.h" +#include "buffer/buffer.h" +#include "locks/locks.h" +#include "avl/avl.h" +#include "inlined.h" +#include "clocks/clocks.h" +#include "popen/popen.h" +#include "simple_pattern/simple_pattern.h" +#include "socket/socket.h" +#include "config/appconfig.h" +#include "log/log.h" +#include "procfile/procfile.h" +#include "dictionary/dictionary.h" +#include "eval/eval.h" +#include "statistical/statistical.h" +#include "adaptive_resortable_list/adaptive_resortable_list.h" +#include "url/url.h" + +#endif // NETDATA_LIB_H diff --git a/src/locks.c b/libnetdata/locks/locks.c index c5b42c92..91e22690 100644 --- a/src/locks.c +++ b/libnetdata/locks/locks.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" // ---------------------------------------------------------------------------- // automatic thread cancelability management, based on locks @@ -82,6 +84,7 @@ int __netdata_mutex_unlock(netdata_mutex_t *mutex) { int netdata_mutex_init_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -97,6 +100,7 @@ int netdata_mutex_init_debug( const char *file, const char *function, const unsi int netdata_mutex_lock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -112,6 +116,7 @@ int netdata_mutex_lock_debug( const char *file, const char *function, const unsi int netdata_mutex_trylock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -127,6 +132,7 @@ int netdata_mutex_trylock_debug( const char *file, const char *function, const u int netdata_mutex_unlock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -215,6 +221,7 @@ int __netdata_rwlock_trywrlock(netdata_rwlock_t *rwlock) { int netdata_rwlock_destroy_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -230,6 +237,7 @@ int netdata_rwlock_destroy_debug( const char *file, const char *function, const int netdata_rwlock_init_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -245,6 +253,7 @@ int netdata_rwlock_init_debug( const char *file, const char *function, const uns int netdata_rwlock_rdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -260,6 +269,7 @@ int netdata_rwlock_rdlock_debug( const char *file, const char *function, const u int netdata_rwlock_wrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -275,6 +285,7 @@ int netdata_rwlock_wrlock_debug( const char *file, const char *function, const u int netdata_rwlock_unlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -290,6 +301,7 @@ int netdata_rwlock_unlock_debug( const char *file, const char *function, const u int netdata_rwlock_tryrdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); @@ -305,6 +317,7 @@ int netdata_rwlock_tryrdlock_debug( const char *file, const char *function, cons int netdata_rwlock_trywrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) { usec_t start = 0; + (void)start; if(unlikely(debug_flags & D_LOCKS)) { start = now_boottime_usec(); diff --git a/src/locks.h b/libnetdata/locks/locks.h index 36962fef..850dd7eb 100644 --- a/src/locks.h +++ b/libnetdata/locks/locks.h @@ -1,5 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_LOCKS_H -#define NETDATA_LOCKS_H +#define NETDATA_LOCKS_H 1 + +#include "../libnetdata.h" typedef pthread_mutex_t netdata_mutex_t; #define NETDATA_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER diff --git a/src/log.c b/libnetdata/log/log.c index edb4482a..198e98bd 100644 --- a/src/log.c +++ b/libnetdata/log/log.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" int web_server_is_multithreaded = 1; @@ -56,7 +58,7 @@ static inline void log_unlock() { netdata_mutex_unlock(&log_mutex); } -int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) { +static FILE *open_log_file(int fd, FILE *fp, const char *filename, int *enabled_syslog, int is_stdaccess, int *fd_ptr) { int f, devnull = 0; if(!filename || !*filename || !strcmp(filename, "none") || !strcmp(filename, "/dev/null")) { @@ -75,8 +77,10 @@ int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) // don't do anything if the user is willing // to have the standard one if(!strcmp(filename, "system")) { - if(fd != -1 && fp != &stdaccess) - return fd; + if(fd != -1 && !is_stdaccess) { + if(fd_ptr) *fd_ptr = fd; + return fp; + } filename = "stderr"; } @@ -91,19 +95,20 @@ int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) f = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0664); if(f == -1) { error("Cannot open file '%s'. Leaving %d to its default.", filename, fd); - return fd; + if(fd_ptr) *fd_ptr = fd; + return fp; } } - if(devnull && fp == &stdaccess) { - fd = -1; - *fp = NULL; - } - // if there is a level-2 file pointer // flush it before switching the level-1 fds - if(fp && *fp) - fflush(*fp); + if(fp) + fflush(fp); + + if(devnull && is_stdaccess) { + fd = -1; + fp = NULL; + } if(fd != f && fd != -1) { // it automatically closes @@ -111,57 +116,61 @@ int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) if (t == -1) { error("Cannot dup2() new fd %d to old fd %d for '%s'", f, fd, filename); close(f); - return fd; + if(fd_ptr) *fd_ptr = fd; + return fp; } // info("dup2() new fd %d to old fd %d for '%s'", f, fd, filename); close(f); } else fd = f; - if(fp && !*fp) { - *fp = fdopen(fd, "a"); - if (!*fp) + if(!fp) { + fp = fdopen(fd, "a"); + if (!fp) error("Cannot fdopen() fd %d ('%s')", fd, filename); else { - if (setvbuf(*fp, NULL, _IOLBF, 0) != 0) + if (setvbuf(fp, NULL, _IOLBF, 0) != 0) error("Cannot set line buffering on fd %d ('%s')", fd, filename); } } - return fd; + if(fd_ptr) *fd_ptr = fd; + return fp; } void reopen_all_log_files() { if(stdout_filename) - open_log_file(STDOUT_FILENO, (FILE **)&stdout, stdout_filename, &output_log_syslog); + open_log_file(STDOUT_FILENO, stdout, stdout_filename, &output_log_syslog, 0, NULL); if(stderr_filename) - open_log_file(STDERR_FILENO, (FILE **)&stderr, stderr_filename, &error_log_syslog); + open_log_file(STDERR_FILENO, stderr, stderr_filename, &error_log_syslog, 0, NULL); if(stdaccess_filename) - stdaccess_fd = open_log_file(stdaccess_fd, (FILE **)&stdaccess, stdaccess_filename, &access_log_syslog); + stdaccess = open_log_file(stdaccess_fd, stdaccess, stdaccess_filename, &access_log_syslog, 1, &stdaccess_fd); } void open_all_log_files() { // disable stdin - open_log_file(STDIN_FILENO, (FILE **)&stdin, "/dev/null", NULL); + open_log_file(STDIN_FILENO, stdin, "/dev/null", NULL, 0, NULL); - open_log_file(STDOUT_FILENO, (FILE **)&stdout, stdout_filename, &output_log_syslog); - open_log_file(STDERR_FILENO, (FILE **)&stderr, stderr_filename, &error_log_syslog); - stdaccess_fd = open_log_file(stdaccess_fd, (FILE **)&stdaccess, stdaccess_filename, &access_log_syslog); + open_log_file(STDOUT_FILENO, stdout, stdout_filename, &output_log_syslog, 0, NULL); + open_log_file(STDERR_FILENO, stderr, stderr_filename, &error_log_syslog, 0, NULL); + stdaccess = open_log_file(stdaccess_fd, stdaccess, stdaccess_filename, &access_log_syslog, 1, &stdaccess_fd); } // ---------------------------------------------------------------------------- // error log throttling -time_t error_log_throttle_period_backup = 0; time_t error_log_throttle_period = 1200; unsigned long error_log_errors_per_period = 200; +unsigned long error_log_errors_per_period_backup = 0; int error_log_limit(int reset) { static time_t start = 0; static unsigned long counter = 0, prevented = 0; + // fprintf(stderr, "FLOOD: counter=%lu, allowed=%lu, backup=%lu, period=%llu\n", counter, error_log_errors_per_period, error_log_errors_per_period_backup, (unsigned long long)error_log_throttle_period); + // do not throttle if the period is 0 if(error_log_throttle_period == 0) return 0; @@ -181,7 +190,7 @@ int error_log_limit(int reset) { if(prevented) { char date[LOG_DATE_LENGTH]; log_date(date, LOG_DATE_LENGTH); - fprintf(stderr, "%s: %s Resetting logging for process '%s' (prevented %lu logs in the last %ld seconds).\n" + fprintf(stderr, "%s: %s LOG FLOOD PROTECTION reset for process '%s' (prevented %lu logs in the last %ld seconds).\n" , date , program_name , program_name @@ -202,7 +211,7 @@ int error_log_limit(int reset) { if(prevented) { char date[LOG_DATE_LENGTH]; log_date(date, LOG_DATE_LENGTH); - fprintf(stderr, "%s: %s Resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n" + fprintf(stderr, "%s: %s LOG FLOOD PROTECTION resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n" , date , program_name , program_name @@ -224,7 +233,7 @@ int error_log_limit(int reset) { if(!prevented) { char date[LOG_DATE_LENGTH]; log_date(date, LOG_DATE_LENGTH); - fprintf(stderr, "%s: %s Too many logs (%lu logs in %ld seconds, threshold is set to %lu logs in %ld seconds). Preventing more logs from process '%s' for %ld seconds.\n" + fprintf(stderr, "%s: %s LOG FLOOD PROTECTION too many logs (%lu logs in %ld seconds, threshold is set to %lu logs in %ld seconds). Preventing more logs from process '%s' for %ld seconds.\n" , date , program_name , counter diff --git a/src/log.h b/libnetdata/log/log.h index 81c85481..48e1599a 100644 --- a/src/log.h +++ b/libnetdata/log/log.h @@ -1,6 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_LOG_H #define NETDATA_LOG_H 1 +#include "../libnetdata.h" + #define D_WEB_BUFFER 0x0000000000000001 #define D_WEB_CLIENT 0x0000000000000002 #define D_LISTENER 0x0000000000000004 @@ -55,8 +59,8 @@ extern int access_log_syslog; extern int error_log_syslog; extern int output_log_syslog; -extern time_t error_log_throttle_period, error_log_throttle_period_backup; -extern unsigned long error_log_errors_per_period; +extern time_t error_log_throttle_period; +extern unsigned long error_log_errors_per_period, error_log_errors_per_period_backup; extern int error_log_limit(int reset); extern void open_all_log_files(); @@ -64,8 +68,11 @@ extern void reopen_all_log_files(); static inline void debug_dummy(void) {} -#define error_log_limit_reset() do { error_log_throttle_period = error_log_throttle_period_backup; error_log_limit(1); } while(0) -#define error_log_limit_unlimited() do { error_log_throttle_period = 0; } while(0) +#define error_log_limit_reset() do { error_log_errors_per_period = error_log_errors_per_period_backup; error_log_limit(1); } while(0) +#define error_log_limit_unlimited() do { \ + error_log_limit_reset(); \ + error_log_errors_per_period = ((error_log_errors_per_period_backup * 10) < 10000) ? 10000 : (error_log_errors_per_period_backup * 10); \ + } while(0) #ifdef NETDATA_INTERNAL_CHECKS #define debug(type, args...) do { if(unlikely(debug_flags & type)) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args); } while(0) diff --git a/src/popen.c b/libnetdata/popen/popen.c index eda1c05b..845363fd 100644 --- a/src/popen.c +++ b/libnetdata/popen/popen.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" /* struct mypopen { @@ -67,7 +69,7 @@ FILE *mypopen(const char *command, volatile pid_t *pidptr) // close all files int i; - for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--) + for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i >= 0; i--) if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i); // move the pipe to stdout @@ -136,7 +138,7 @@ FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env) { // close all files int i; - for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--) + for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i >= 0; i--) if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i); // move the pipe to stdout diff --git a/src/popen.h b/libnetdata/popen/popen.h index 3dd79bb4..90d4b829 100644 --- a/src/popen.h +++ b/libnetdata/popen/popen.h @@ -1,6 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_POPEN_H #define NETDATA_POPEN_H 1 +#include "../libnetdata.h" + #define PIPE_READ 0 #define PIPE_WRITE 1 @@ -8,4 +12,7 @@ extern FILE *mypopen(const char *command, volatile pid_t *pidptr); extern FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env); extern int mypclose(FILE *fp, pid_t pid); +extern void signals_unblock(void); +extern void signals_reset(void); + #endif /* NETDATA_POPEN_H */ diff --git a/src/procfile.c b/libnetdata/procfile/procfile.c index 044f975b..4a812baa 100644 --- a/src/procfile.c +++ b/libnetdata/procfile/procfile.c @@ -1,5 +1,6 @@ -#include "common.h" -#include "procfile.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" #define PF_PREFIX "PROCFILE" @@ -7,6 +8,8 @@ #define PFLINES_INCREASE_STEP 10 #define PROCFILE_INCREMENT_BUFFER 512 +int procfile_open_flags = O_RDONLY; + int procfile_adaptive_initial_allocation = 0; // if adaptive allocation is set, these store the @@ -391,7 +394,7 @@ void procfile_set_open_close(procfile *ff, const char *open, const char *close) procfile *procfile_open(const char *filename, const char *separators, uint32_t flags) { debug(D_PROCFILE, PF_PREFIX ": Opening file '%s'", filename); - int fd = open(filename, O_RDONLY, 0666); + int fd = open(filename, procfile_open_flags, 0666); if(unlikely(fd == -1)) { if(unlikely(!(flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot open file '%s'", filename); return NULL; @@ -427,7 +430,7 @@ procfile *procfile_reopen(procfile *ff, const char *filename, const char *separa close(ff->fd); } - ff->fd = open(filename, O_RDONLY, 0666); + ff->fd = open(filename, procfile_open_flags, 0666); if(unlikely(ff->fd == -1)) { procfile_close(ff); return NULL; @@ -451,6 +454,7 @@ procfile *procfile_reopen(procfile *ff, const char *filename, const char *separa void procfile_print(procfile *ff) { size_t lines = procfile_lines(ff), l; char *s; + (void)s; debug(D_PROCFILE, "File '%s' with %zu lines and %zu words", procfile_filename(ff), ff->lines->len, ff->words->len); diff --git a/src/procfile.h b/libnetdata/procfile/procfile.h index 012c6efe..b107358a 100644 --- a/src/procfile.h +++ b/libnetdata/procfile/procfile.h @@ -1,31 +1,10 @@ -/* - * procfile is a library for reading kernel files from /proc - * - * The idea is this: - * - * - every file is opened once with procfile_open(). - * - * - to read updated contents, we rewind it (lseek() to 0) and read again - * with procfile_readall(). - * - * - for every file, we use a buffer that is adjusted to fit its entire - * contents in memory, allowing us to read it with a single read() call. - * (this provides atomicity / consistency on the data read from the kernel) - * - * - once the data are read, we update two arrays of pointers: - * - a words array, pointing to each word in the data read - * - a lines array, pointing to the first word for each line - * - * This is highly optimized. Both arrays are automatically adjusted to - * fit all contents and are updated in a single pass on the data: - * - a raspberry Pi can process 5.000+ files / sec. - * - a J1900 celeron processor can process 23.000+ files / sec. -*/ - +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef NETDATA_PROCFILE_H #define NETDATA_PROCFILE_H 1 +#include "../libnetdata.h" + // ---------------------------------------------------------------------------- // An array of words @@ -103,6 +82,9 @@ extern char *procfile_filename(procfile *ff); // ---------------------------------------------------------------------------- +// set to the O_XXXX flags, to have procfile_open and procfile_reopen use them when opening proc files +extern int procfile_open_flags; + // set this to 1, to have procfile adapt its initial buffer allocation to the max allocation used so far extern int procfile_adaptive_initial_allocation; diff --git a/src/simple_pattern.c b/libnetdata/simple_pattern/simple_pattern.c index 747b5150..57b0aecc 100644 --- a/src/simple_pattern.c +++ b/libnetdata/simple_pattern/simple_pattern.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" struct simple_pattern { const char *match; diff --git a/src/simple_pattern.h b/libnetdata/simple_pattern/simple_pattern.h index d0b75af7..b96a018e 100644 --- a/src/simple_pattern.h +++ b/libnetdata/simple_pattern/simple_pattern.h @@ -1,6 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_SIMPLE_PATTERN_H #define NETDATA_SIMPLE_PATTERN_H +#include "../libnetdata.h" + + typedef enum { SIMPLE_PATTERN_EXACT, SIMPLE_PATTERN_PREFIX, diff --git a/src/socket.c b/libnetdata/socket/socket.c index 8bede73f..c266efeb 100644 --- a/src/socket.c +++ b/libnetdata/socket/socket.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" // -------------------------------------------------------------------------------------------------------------------- // various library calls @@ -45,12 +47,14 @@ int sock_setreuse(int fd, int reuse) { } int sock_setreuse_port(int fd, int reuse) { - int ret = -1; + int ret; #ifdef SO_REUSEPORT ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)); if(ret == -1 && errno != ENOPROTOOPT) error("failed to set SO_REUSEPORT on socket %d", fd); +#else + ret = -1; #endif return ret; @@ -80,7 +84,7 @@ int sock_enlarge_out(int fd) { // -------------------------------------------------------------------------------------------------------------------- -char *strdup_client_description(int family, const char *protocol, const char *ip, int port) { +char *strdup_client_description(int family, const char *protocol, const char *ip, uint16_t port) { char buffer[100 + 1]; switch(family) { @@ -148,7 +152,7 @@ int create_listen_socket_unix(const char *path, int listen_backlog) { return sock; } -int create_listen_socket4(int socktype, const char *ip, int port, int listen_backlog) { +int create_listen_socket4(int socktype, const char *ip, uint16_t port, int listen_backlog) { int sock; debug(D_LISTENER, "LISTENER: IPv4 creating new listening socket on ip '%s' port %d, socktype %d", ip, port, socktype); @@ -244,7 +248,7 @@ int create_listen_socket6(int socktype, uint32_t scope_id, const char *ip, int p return sock; } -static inline int listen_sockets_add(LISTEN_SOCKETS *sockets, int fd, int family, int socktype, const char *protocol, const char *ip, int port) { +static inline int listen_sockets_add(LISTEN_SOCKETS *sockets, int fd, int family, int socktype, const char *protocol, const char *ip, uint16_t port) { if(sockets->opened >= MAX_LISTEN_FDS) { error("LISTENER: Too many listening sockets. Failed to add listening %s socket at ip '%s' port %d, protocol %s, socktype %d", protocol, ip, port, protocol, socktype); close(fd); @@ -296,7 +300,7 @@ void listen_sockets_close(LISTEN_SOCKETS *sockets) { sockets->failed = 0; } -static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, int default_port, int listen_backlog) { +static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, uint16_t default_port, int listen_backlog) { int added = 0; struct addrinfo hints; struct addrinfo *result = NULL, *rp = NULL; @@ -396,10 +400,10 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, for (rp = result; rp != NULL; rp = rp->ai_next) { int fd = -1; - int family = -1; + int family; char rip[INET_ADDRSTRLEN + INET6_ADDRSTRLEN] = "INVALID"; - int rport = default_port; + uint16_t rport = default_port; family = rp->ai_addr->sa_family; switch (family) { @@ -444,17 +448,19 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, int listen_sockets_setup(LISTEN_SOCKETS *sockets) { listen_sockets_init(sockets); - sockets->backlog = (int) config_get_number(sockets->config_section, "listen backlog", sockets->backlog); + sockets->backlog = (int) appconfig_get_number(sockets->config, sockets->config_section, "listen backlog", sockets->backlog); - int old_port = sockets->default_port; - sockets->default_port = (int) config_get_number(sockets->config_section, "default port", sockets->default_port); - if(sockets->default_port < 1 || sockets->default_port > 65535) { - error("LISTENER: Invalid listen port %d given. Defaulting to %d.", sockets->default_port, old_port); - sockets->default_port = (int) config_set_number(sockets->config_section, "default port", old_port); + long long int old_port = sockets->default_port; + long long int new_port = appconfig_get_number(sockets->config, sockets->config_section, "default port", sockets->default_port); + if(new_port < 1 || new_port > 65535) { + error("LISTENER: Invalid listen port %lld given. Defaulting to %lld.", new_port, old_port); + sockets->default_port = (uint16_t) appconfig_set_number(sockets->config, sockets->config_section, "default port", old_port); } + else sockets->default_port = (uint16_t)new_port; + debug(D_OPTIONS, "LISTENER: Default listen port set to %d.", sockets->default_port); - char *s = config_get(sockets->config_section, "bind to", sockets->default_bind_to); + char *s = appconfig_get(sockets->config, sockets->config_section, "bind to", sockets->default_bind_to); while(*s) { char *e = s; @@ -585,6 +591,8 @@ static inline int connect_to_this_ip46(int protocol, int socktype, const char *h switch (ai->ai_addr->sa_family) { case PF_INET: { struct sockaddr_in *pSadrIn = (struct sockaddr_in *)ai->ai_addr; + (void)pSadrIn; + debug(D_CONNECT_TO, "ai_addr = sin_family: %d (AF_INET = %d, AF_INET6 = %d), sin_addr: '%s', sin_port: '%s'", pSadrIn->sin_family, AF_INET, @@ -596,6 +604,8 @@ static inline int connect_to_this_ip46(int protocol, int socktype, const char *h case PF_INET6: { struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr; + (void)pSadrIn6; + debug(D_CONNECT_TO,"ai_addr = sin6_family: %d (AF_INET = %d, AF_INET6 = %d), sin6_addr: '%s', sin6_port: '%s', sin6_flowinfo: %u, sin6_scope_id: %u", pSadrIn6->sin6_family, AF_INET, @@ -968,10 +978,10 @@ inline POLLINFO *poll_add_fd(POLLJOB *p , uint32_t flags , const char *client_ip , const char *client_port - , void *(*add_callback)(POLLINFO *pi, short int *events, void *data) - , void (*del_callback)(POLLINFO *pi) - , int (*rcv_callback)(POLLINFO *pi, short int *events) - , int (*snd_callback)(POLLINFO *pi, short int *events) + , void *(*add_callback)(POLLINFO * /*pi*/, short int * /*events*/, void * /*data*/) + , void (*del_callback)(POLLINFO * /*pi*/) + , int (*rcv_callback)(POLLINFO * /*pi*/, short int * /*events*/) + , int (*snd_callback)(POLLINFO * /*pi*/, short int * /*events*/) , void *data ) { debug(D_POLLFD, "POLLFD: ADD: request to add fd %d, slots = %zu, used = %zu, min = %zu, max = %zu, next free = %zd", fd, p->slots, p->used, p->min, p->max, p->first_free?(ssize_t)p->first_free->slot:(ssize_t)-1); @@ -1286,7 +1296,9 @@ static void poll_events_process(POLLJOB *p, POLLINFO *pi, struct pollfd *pf, sho debug(D_POLLFD, "POLLFD: LISTENER: reading data from UDP slot %zu (fd %d)", i, fd); - // FIXME: access_list is not applied to UDP + // TODO: access_list is not applied to UDP + // but checking the access list on every UDP packet will destroy + // performance, especially for statsd. pf->events = 0; pi->rcv_callback(pi, &pf->events); @@ -1349,11 +1361,11 @@ static void poll_events_process(POLLJOB *p, POLLINFO *pi, struct pollfd *pf, sho } void poll_events(LISTEN_SOCKETS *sockets - , void *(*add_callback)(POLLINFO *pi, short int *events, void *data) - , void (*del_callback)(POLLINFO *pi) - , int (*rcv_callback)(POLLINFO *pi, short int *events) - , int (*snd_callback)(POLLINFO *pi, short int *events) - , void (*tmr_callback)(void *timer_data) + , void *(*add_callback)(POLLINFO * /*pi*/, short int * /*events*/, void * /*data*/) + , void (*del_callback)(POLLINFO * /*pi*/) + , int (*rcv_callback)(POLLINFO * /*pi*/, short int * /*events*/) + , int (*snd_callback)(POLLINFO * /*pi*/, short int * /*events*/) + , void (*tmr_callback)(void * /*timer_data*/) , SIMPLE_PATTERN *access_list , void *data , time_t tcp_request_timeout_seconds @@ -1423,6 +1435,8 @@ void poll_events(LISTEN_SOCKETS *sockets usec_t timer_usec = timer_milliseconds * USEC_PER_MS; usec_t now_usec = 0, next_timer_usec = 0, last_timer_usec = 0; + (void)last_timer_usec; + if(unlikely(timer_usec)) { now_usec = now_boottime_usec(); next_timer_usec = now_usec - (now_usec % timer_usec) + timer_usec; diff --git a/src/socket.h b/libnetdata/socket/socket.h index 7b3e726e..f5412b63 100644 --- a/src/socket.h +++ b/libnetdata/socket/socket.h @@ -1,14 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_SOCKET_H #define NETDATA_SOCKET_H +#include "../libnetdata.h" + #ifndef MAX_LISTEN_FDS #define MAX_LISTEN_FDS 50 #endif typedef struct listen_sockets { + struct config *config; // the config file to use const char *config_section; // the netdata configuration section to read settings from const char *default_bind_to; // the default bind to configuration string - int default_port; // the default port to use + uint16_t default_port; // the default port to use int backlog; // the default listen backlog to use size_t opened; // the number of sockets opened @@ -19,7 +24,7 @@ typedef struct listen_sockets { int fds_families[MAX_LISTEN_FDS]; // the family of the open sockets (AF_UNIX, AF_INET, AF_INET6) } LISTEN_SOCKETS; -extern char *strdup_client_description(int family, const char *protocol, const char *ip, int port); +extern char *strdup_client_description(int family, const char *protocol, const char *ip, uint16_t port); extern int listen_sockets_setup(LISTEN_SOCKETS *sockets); extern void listen_sockets_close(LISTEN_SOCKETS *sockets); diff --git a/src/statistical.c b/libnetdata/statistical/statistical.c index d4b33fd5..15792fd1 100644 --- a/src/statistical.c +++ b/libnetdata/statistical/statistical.c @@ -1,37 +1,36 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later -// -------------------------------------------------------------------------------------------------------------------- - -inline LONG_DOUBLE sum_and_count(const LONG_DOUBLE *series, size_t entries, size_t *count) { - if(unlikely(entries == 0)) { - if(likely(count)) - *count = 0; +#include "../libnetdata.h" - return NAN; - } +LONG_DOUBLE default_single_exponential_smoothing_alpha = 0.1; - if(unlikely(entries == 1)) { - if(likely(count)) - *count = (isnan(series[0])?0:1); +void log_series_to_stderr(LONG_DOUBLE *series, size_t entries, calculated_number result, const char *msg) { + const LONG_DOUBLE *value, *end = &series[entries]; - return series[0]; + fprintf(stderr, "%s of %zu entries [ ", msg, entries); + for(value = series; value < end ;value++) { + if(value != series) fprintf(stderr, ", "); + fprintf(stderr, "%" LONG_DOUBLE_MODIFIER, *value); } + fprintf(stderr, " ] results in " CALCULATED_NUMBER_FORMAT "\n", result); +} + +// -------------------------------------------------------------------------------------------------------------------- - size_t i, c = 0; +inline LONG_DOUBLE sum_and_count(const LONG_DOUBLE *series, size_t entries, size_t *count) { + const LONG_DOUBLE *value, *end = &series[entries]; LONG_DOUBLE sum = 0; + size_t c = 0; - for(i = 0; i < entries ; i++) { - LONG_DOUBLE value = series[i]; - if(unlikely(isnan(value) || isinf(value))) continue; - c++; - sum += value; + for(value = series; value < end ; value++) { + if(isnormal(*value)) { + sum += *value; + c++; + } } - if(likely(count)) - *count = c; - - if(unlikely(c == 0)) - return NAN; + if(unlikely(!c)) sum = NAN; + if(likely(count)) *count = c; return sum; } @@ -44,9 +43,7 @@ inline LONG_DOUBLE average(const LONG_DOUBLE *series, size_t entries) { size_t count = 0; LONG_DOUBLE sum = sum_and_count(series, entries, &count); - if(unlikely(count == 0)) - return NAN; - + if(unlikely(!count)) return NAN; return sum / (LONG_DOUBLE)count; } @@ -65,7 +62,7 @@ LONG_DOUBLE moving_average(const LONG_DOUBLE *series, size_t entries, size_t per for(i = 0, count = 0; i < entries; i++) { LONG_DOUBLE value = series[i]; - if(unlikely(isnan(value) || isinf(value))) continue; + if(unlikely(!isnormal(value))) continue; if(unlikely(count < period)) { sum += value; @@ -116,33 +113,25 @@ inline LONG_DOUBLE *copy_series(const LONG_DOUBLE *series, size_t entries) { } LONG_DOUBLE median_on_sorted_series(const LONG_DOUBLE *series, size_t entries) { - if(unlikely(entries == 0)) - return NAN; - - if(unlikely(entries == 1)) - return series[0]; - - if(unlikely(entries == 2)) - return (series[0] + series[1]) / 2; + if(unlikely(entries == 0)) return NAN; + if(unlikely(entries == 1)) return series[0]; + if(unlikely(entries == 2)) return (series[0] + series[1]) / 2; - LONG_DOUBLE avg; + LONG_DOUBLE average; if(entries % 2 == 0) { size_t m = entries / 2; - avg = (series[m] + series[m + 1]) / 2; + average = (series[m] + series[m + 1]) / 2; } else { - avg = series[entries / 2]; + average = series[entries / 2]; } - return avg; + return average; } LONG_DOUBLE median(const LONG_DOUBLE *series, size_t entries) { - if(unlikely(entries == 0)) - return NAN; - - if(unlikely(entries == 1)) - return series[0]; + if(unlikely(entries == 0)) return NAN; + if(unlikely(entries == 1)) return series[0]; if(unlikely(entries == 2)) return (series[0] + series[1]) / 2; @@ -184,7 +173,7 @@ LONG_DOUBLE running_median_estimate(const LONG_DOUBLE *series, size_t entries) { for(i = 0; i < entries ; i++) { LONG_DOUBLE value = series[i]; - if(unlikely(isnan(value) || isinf(value))) continue; + if(unlikely(!isnormal(value))) continue; average += ( value - average ) * 0.1f; // rough running average. median += copysignl( average * 0.01, value - median ); @@ -196,47 +185,36 @@ LONG_DOUBLE running_median_estimate(const LONG_DOUBLE *series, size_t entries) { // -------------------------------------------------------------------------------------------------------------------- LONG_DOUBLE standard_deviation(const LONG_DOUBLE *series, size_t entries) { - if(unlikely(entries < 1)) - return NAN; - - if(unlikely(entries == 1)) - return series[0]; - - size_t i, count = 0; - LONG_DOUBLE sum = 0; + if(unlikely(entries == 0)) return NAN; + if(unlikely(entries == 1)) return series[0]; - for(i = 0; i < entries ; i++) { - LONG_DOUBLE value = series[i]; - if(unlikely(isnan(value) || isinf(value))) continue; + const LONG_DOUBLE *value, *end = &series[entries]; + size_t count; + LONG_DOUBLE sum; - count++; - sum += value; + for(count = 0, sum = 0, value = series ; value < end ;value++) { + if(likely(isnormal(*value))) { + count++; + sum += *value; + } } - if(unlikely(count == 0)) - return NAN; - - if(unlikely(count == 1)) - return sum; + if(unlikely(count == 0)) return NAN; + if(unlikely(count == 1)) return sum; LONG_DOUBLE average = sum / (LONG_DOUBLE)count; - for(i = 0, count = 0, sum = 0; i < entries ; i++) { - LONG_DOUBLE value = series[i]; - if(unlikely(isnan(value) || isinf(value))) continue; - - count++; - sum += powl(value - average, 2); + for(count = 0, sum = 0, value = series ; value < end ;value++) { + if(isnormal(*value)) { + count++; + sum += powl(*value - average, 2); + } } - if(unlikely(count == 0)) - return NAN; - - if(unlikely(count == 1)) - return average; - - LONG_DOUBLE variance = sum / (LONG_DOUBLE)(count - 1); // remove -1 to have a population stddev + if(unlikely(count == 0)) return NAN; + if(unlikely(count == 1)) return average; + LONG_DOUBLE variance = sum / (LONG_DOUBLE)(count); // remove -1 from count to have a population stddev LONG_DOUBLE stddev = sqrtl(variance); return stddev; } @@ -244,21 +222,36 @@ LONG_DOUBLE standard_deviation(const LONG_DOUBLE *series, size_t entries) { // -------------------------------------------------------------------------------------------------------------------- LONG_DOUBLE single_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha) { - size_t i, count = 0; - LONG_DOUBLE level = 0, sum = 0; + if(unlikely(entries == 0)) + return NAN; if(unlikely(isnan(alpha))) - alpha = 0.3; + alpha = default_single_exponential_smoothing_alpha; - for(i = 0; i < entries ; i++) { - LONG_DOUBLE value = series[i]; - if(unlikely(isnan(value) || isinf(value))) continue; - count++; + const LONG_DOUBLE *value = series, *end = &series[entries]; + LONG_DOUBLE level = (1.0 - alpha) * (*value); + + for(value++ ; value < end; value++) { + if(likely(isnormal(*value))) + level = alpha * (*value) + (1.0 - alpha) * level; + } - sum += value; + return level; +} + +LONG_DOUBLE single_exponential_smoothing_reverse(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha) { + if(unlikely(entries == 0)) + return NAN; - LONG_DOUBLE last_level = level; - level = alpha * value + (1.0 - alpha) * last_level; + if(unlikely(isnan(alpha))) + alpha = default_single_exponential_smoothing_alpha; + + const LONG_DOUBLE *value = &series[entries -1]; + LONG_DOUBLE level = (1.0 - alpha) * (*value); + + for(value++ ; value >= series; value--) { + if(likely(isnormal(*value))) + level = alpha * (*value) + (1.0 - alpha) * level; } return level; @@ -268,8 +261,10 @@ LONG_DOUBLE single_exponential_smoothing(const LONG_DOUBLE *series, size_t entri // http://grisha.org/blog/2016/02/16/triple-exponential-smoothing-forecasting-part-ii/ LONG_DOUBLE double_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha, LONG_DOUBLE beta, LONG_DOUBLE *forecast) { - size_t i, count = 0; - LONG_DOUBLE level = series[0], trend, sum; + if(unlikely(entries == 0)) + return NAN; + + LONG_DOUBLE level, trend; if(unlikely(isnan(alpha))) alpha = 0.3; @@ -277,24 +272,22 @@ LONG_DOUBLE double_exponential_smoothing(const LONG_DOUBLE *series, size_t entri if(unlikely(isnan(beta))) beta = 0.05; + level = series[0]; + if(likely(entries > 1)) trend = series[1] - series[0]; else trend = 0; - sum = series[0]; - - for(i = 1; i < entries ; i++) { - LONG_DOUBLE value = series[i]; - if(unlikely(isnan(value) || isinf(value))) continue; - count++; + const LONG_DOUBLE *value = series; + for(value++ ; value >= series; value--) { + if(likely(isnormal(*value))) { - sum += value; + LONG_DOUBLE last_level = level; + level = alpha * *value + (1.0 - alpha) * (level + trend); + trend = beta * (level - last_level) + (1.0 - beta) * trend; - LONG_DOUBLE last_level = level; - - level = alpha * value + (1.0 - alpha) * (level + trend); - trend = beta * (level - last_level) + (1.0 - beta) * trend; + } } if(forecast) diff --git a/src/statistical.h b/libnetdata/statistical/statistical.h index 67538902..586c6b34 100644 --- a/src/statistical.h +++ b/libnetdata/statistical/statistical.h @@ -1,5 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_STATISTICAL_H -#define NETDATA_STATISTICAL_H +#define NETDATA_STATISTICAL_H 1 + +#include "../libnetdata.h" + +#ifndef isnormal +#define isnormal(x) (fpclassify(x) == FP_NORMAL) +#endif + +extern void log_series_to_stderr(LONG_DOUBLE *series, size_t entries, calculated_number result, const char *msg); extern LONG_DOUBLE average(const LONG_DOUBLE *series, size_t entries); extern LONG_DOUBLE moving_average(const LONG_DOUBLE *series, size_t entries, size_t period); @@ -8,6 +18,7 @@ extern LONG_DOUBLE moving_median(const LONG_DOUBLE *series, size_t entries, size extern LONG_DOUBLE running_median_estimate(const LONG_DOUBLE *series, size_t entries); extern LONG_DOUBLE standard_deviation(const LONG_DOUBLE *series, size_t entries); extern LONG_DOUBLE single_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha); +extern LONG_DOUBLE single_exponential_smoothing_reverse(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha); extern LONG_DOUBLE double_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha, LONG_DOUBLE beta, LONG_DOUBLE *forecast); extern LONG_DOUBLE holtwinters(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha, LONG_DOUBLE beta, LONG_DOUBLE gamma, LONG_DOUBLE *forecast); extern LONG_DOUBLE sum_and_count(const LONG_DOUBLE *series, size_t entries, size_t *count); diff --git a/src/storage_number.c b/libnetdata/storage_number/storage_number.c index c7bbaa8d..db4cb700 100644 --- a/src/storage_number.c +++ b/libnetdata/storage_number/storage_number.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" storage_number pack_storage_number(calculated_number value, uint32_t flags) { diff --git a/src/storage_number.h b/libnetdata/storage_number/storage_number.h index ef81863f..5353ab60 100644 --- a/src/storage_number.h +++ b/libnetdata/storage_number/storage_number.h @@ -1,5 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_STORAGE_NUMBER_H -#define NETDATA_STORAGE_NUMBER_H +#define NETDATA_STORAGE_NUMBER_H 1 + +#include "../libnetdata.h" #ifdef NETDATA_WITHOUT_LONG_DOUBLE diff --git a/src/threads.c b/libnetdata/threads/threads.c index b9ca3c08..133d9a54 100644 --- a/src/threads.c +++ b/libnetdata/threads/threads.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" static size_t default_stacksize = 0, wanted_stacksize = 0; static pthread_attr_t *attr = NULL; diff --git a/src/threads.h b/libnetdata/threads/threads.h index e2ed6a4f..eec6ad0e 100644 --- a/src/threads.h +++ b/libnetdata/threads/threads.h @@ -1,5 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_THREADS_H -#define NETDATA_THREADS_H +#define NETDATA_THREADS_H 1 + +#include "../libnetdata.h" extern pid_t gettid(void); diff --git a/src/url.c b/libnetdata/url/url.c index 6be4d964..07a9f806 100644 --- a/src/url.c +++ b/libnetdata/url/url.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" // ---------------------------------------------------------------------------- // URL encode / decode @@ -58,7 +60,9 @@ char *url_decode_r(char *to, char *url, size_t size) { while(*s && d < e) { if(unlikely(*s == '%')) { if(likely(s[1] && s[2])) { - *d++ = from_hex(s[1]) << 4 | from_hex(s[2]); + char t = from_hex(s[1]) << 4 | from_hex(s[2]); + // avoid HTTP header injection + *d++ = (char)((isprint(t))? t : ' '); s += 2; } } diff --git a/src/url.h b/libnetdata/url/url.h index fa44d49a..6cef6d7a 100644 --- a/src/url.h +++ b/libnetdata/url/url.h @@ -1,6 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_URL_H #define NETDATA_URL_H 1 +#include "../libnetdata.h" + // ---------------------------------------------------------------------------- // URL encode / decode // code from: http://www.geekhideout.com/urlcode.shtml diff --git a/src/registry.c b/registry/registry.c index bbc2ef36..4f97eb58 100644 --- a/src/registry.c +++ b/registry/registry.c @@ -1,5 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later +#include "../daemon/common.h" #include "registry_internals.h" #define REGISTRY_STATUS_OK "ok" diff --git a/src/registry.h b/registry/registry.h index 9aa24156..ab36de01 100644 --- a/src/registry.h +++ b/registry/registry.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0-or-later /* * netdata registry * @@ -45,10 +46,11 @@ // (i.e. start tracking them only when they access a non-demo machine) // - [DONE] do not track custom dashboards by default - #ifndef NETDATA_REGISTRY_H #define NETDATA_REGISTRY_H 1 +#include "../daemon/common.h" + #define NETDATA_REGISTRY_COOKIE_NAME "netdata_registry_id" // initialize the registry diff --git a/src/registry_db.c b/registry/registry_db.c index de6c634c..d8e2bbd8 100644 --- a/src/registry_db.c +++ b/registry/registry_db.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../daemon/common.h" #include "registry_internals.h" int registry_db_should_be_saved(void) { diff --git a/src/registry_init.c b/registry/registry_init.c index 654f66d1..d3e0420d 100644 --- a/src/registry_init.c +++ b/registry/registry_init.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../daemon/common.h" #include "registry_internals.h" int registry_init(void) { diff --git a/src/registry_internals.c b/registry/registry_internals.c index 44b0a151..b54b9014 100644 --- a/src/registry_internals.c +++ b/registry/registry_internals.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../daemon/common.h" #include "registry_internals.h" struct registry registry; diff --git a/src/registry_internals.h b/registry/registry_internals.h index cceaf292..baa2dc09 100644 --- a/src/registry_internals.h +++ b/registry/registry_internals.h @@ -1,7 +1,9 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef NETDATA_REGISTRY_INTERNALS_H_H -#define NETDATA_REGISTRY_INTERNALS_H_H +#define NETDATA_REGISTRY_INTERNALS_H_H 1 + +#include "registry.h" #define REGISTRY_URL_FLAGS_DEFAULT 0x00 #define REGISTRY_URL_FLAGS_EXPIRED 0x01 diff --git a/src/registry_log.c b/registry/registry_log.c index cca43b09..e0e58ede 100644 --- a/src/registry_log.c +++ b/registry/registry_log.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../daemon/common.h" #include "registry_internals.h" void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name) { diff --git a/src/registry_machine.c b/registry/registry_machine.c index 6dc8200d..8dbeb8ea 100644 --- a/src/registry_machine.c +++ b/registry/registry_machine.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../daemon/common.h" #include "registry_internals.h" // ---------------------------------------------------------------------------- diff --git a/src/registry_machine.h b/registry/registry_machine.h index be824d16..77ab5aaf 100644 --- a/src/registry_machine.h +++ b/registry/registry_machine.h @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_REGISTRY_MACHINE_H -#define NETDATA_REGISTRY_MACHINE_H +#define NETDATA_REGISTRY_MACHINE_H 1 #include "registry_internals.h" diff --git a/src/registry_person.c b/registry/registry_person.c index d8b6cd98..53e3f47f 100644 --- a/src/registry_person.c +++ b/registry/registry_person.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../daemon/common.h" #include "registry_internals.h" // ---------------------------------------------------------------------------- diff --git a/src/registry_person.h b/registry/registry_person.h index 5f6cc244..30e9cb51 100644 --- a/src/registry_person.h +++ b/registry/registry_person.h @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_REGISTRY_PERSON_H -#define NETDATA_REGISTRY_PERSON_H +#define NETDATA_REGISTRY_PERSON_H 1 #include "registry_internals.h" diff --git a/src/registry_url.c b/registry/registry_url.c index 52d36a89..6a710645 100644 --- a/src/registry_url.c +++ b/registry/registry_url.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../daemon/common.h" #include "registry_internals.h" // ---------------------------------------------------------------------------- diff --git a/src/registry_url.h b/registry/registry_url.h index 5ac52f5a..c684f1c3 100644 --- a/src/registry_url.h +++ b/registry/registry_url.h @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_REGISTRY_URL_H -#define NETDATA_REGISTRY_URL_H +#define NETDATA_REGISTRY_URL_H 1 #include "registry_internals.h" diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index df174cbd..00000000 --- a/src/Makefile.am +++ /dev/null @@ -1,307 +0,0 @@ -# -# Copyright (C) 2015 Alon Bar-Lev <alon.barlev@gmail.com> -# -MAINTAINERCLEANFILES= $(srcdir)/Makefile.in - -AM_CPPFLAGS = \ - -DVARLIB_DIR="\"$(varlibdir)\"" \ - -DCACHE_DIR="\"$(cachedir)\"" \ - -DCONFIG_DIR="\"$(configdir)\"" \ - -DLOG_DIR="\"$(logdir)\"" \ - -DPLUGINS_DIR="\"$(pluginsdir)\"" \ - -DRUN_DIR="\"$(localstatedir)/run/netdata\"" \ - -DWEB_DIR="\"$(webdir)\"" \ - $(NULL) - -AM_CFLAGS = \ - $(OPTIONAL_MATH_CFLAGS) \ - $(OPTIONAL_NFACCT_CLFAGS) \ - $(OPTIONAL_ZLIB_CFLAGS) \ - $(OPTIONAL_UUID_CFLAGS) \ - $(OPTIONAL_LIBCAP_CFLAGS) \ - $(OPTIONAL_IPMIMONITORING_CFLAGS)\ - $(NULL) - -sbin_PROGRAMS = netdata -dist_cache_DATA = .keep -dist_varlib_DATA = .keep -dist_registry_DATA = .keep -dist_log_DATA = .keep -plugins_PROGRAMS = - -if ENABLE_PLUGIN_APPS -plugins_PROGRAMS += apps.plugin -endif - -if ENABLE_PLUGIN_FREEIPMI -plugins_PROGRAMS += freeipmi.plugin -endif - -if ENABLE_PLUGIN_CGROUP_NETWORK -plugins_PROGRAMS += cgroup-network -endif - -netdata_SOURCES = \ - adaptive_resortable_list.c \ - adaptive_resortable_list.h \ - appconfig.c \ - appconfig.h \ - avl.c \ - avl.h \ - backend_prometheus.c \ - backend_prometheus.h \ - backends.c \ - backends.h \ - clocks.c \ - clocks.h \ - common.c \ - common.h \ - daemon.c \ - daemon.h \ - dictionary.c \ - dictionary.h \ - eval.c \ - eval.h \ - global_statistics.c \ - global_statistics.h \ - health.c \ - health.h \ - health_config.c \ - health_json.c \ - health_log.c \ - inlined.h \ - locks.c \ - locks.h \ - log.c \ - log.h \ - main.c \ - main.h \ - plugin_checks.c \ - plugin_checks.h \ - plugin_idlejitter.c \ - plugin_idlejitter.h \ - plugins_d.c \ - plugins_d.h \ - popen.c \ - popen.h \ - procfile.c \ - procfile.h \ - registry.c \ - registry.h \ - registry_db.c \ - registry_init.c \ - registry_internals.c \ - registry_internals.h \ - registry_log.c \ - registry_machine.c \ - registry_machine.h \ - registry_person.c \ - registry_person.h \ - registry_url.c \ - registry_url.h \ - rrd.c \ - rrd.h \ - rrd2json.c \ - rrd2json.h \ - rrd2json_api_old.c \ - rrd2json_api_old.h \ - rrdcalc.c \ - rrdcalctemplate.c \ - rrddim.c \ - rrddimvar.c \ - rrdfamily.c \ - rrdhost.c \ - rrdpush.c \ - rrdpush.h \ - rrdset.c \ - rrdsetvar.c \ - rrdvar.c \ - signals.c \ - signals.h \ - simple_pattern.c \ - simple_pattern.h \ - socket.c \ - socket.h \ - statistical.c \ - statistical.h \ - statsd.c \ - statsd.h \ - storage_number.c \ - storage_number.h \ - threads.c \ - threads.h \ - unit_test.c \ - unit_test.h \ - url.c \ - url.h \ - web_api_old.c \ - web_api_old.h \ - web_api_v1.c \ - web_api_v1.h \ - web_buffer.c \ - web_buffer.h \ - web_buffer_svg.c \ - web_buffer_svg.h \ - web_client.c \ - web_client.h \ - web_server.c \ - web_server.h \ - $(NULL) - -if FREEBSD -netdata_SOURCES += \ - plugin_freebsd.c \ - plugin_freebsd.h \ - freebsd_sysctl.c \ - freebsd_getmntinfo.c \ - freebsd_getifaddrs.c \ - freebsd_devstat.c \ - zfs_common.c \ - zfs_common.h \ - freebsd_kstat_zfs.c \ - freebsd_ipfw.c \ - $(NULL) -else -if MACOS -netdata_SOURCES += \ - plugin_macos.c \ - plugin_macos.h \ - macos_sysctl.c \ - macos_mach_smi.c \ - macos_fw.c \ - $(NULL) -else -netdata_SOURCES += \ - ipc.c \ - ipc.h \ - plugin_nfacct.c \ - plugin_nfacct.h \ - plugin_proc.c \ - plugin_proc.h \ - plugin_proc_diskspace.c \ - plugin_proc_diskspace.h \ - plugin_tc.c \ - plugin_tc.h \ - proc_diskstats.c \ - proc_interrupts.c \ - proc_softirqs.c \ - proc_loadavg.c \ - proc_meminfo.c \ - proc_net_dev.c \ - proc_net_ip_vs_stats.c \ - proc_net_netstat.c \ - proc_net_rpc_nfs.c \ - proc_net_rpc_nfsd.c \ - proc_net_snmp.c \ - proc_net_snmp6.c \ - proc_net_sockstat.c \ - proc_net_sockstat6.c \ - proc_net_softnet_stat.c \ - proc_net_stat_conntrack.c \ - proc_net_stat_synproxy.c \ - proc_self_mountinfo.c \ - proc_self_mountinfo.h \ - zfs_common.c \ - zfs_common.h \ - proc_spl_kstat_zfs.c \ - proc_stat.c \ - proc_sys_kernel_random_entropy_avail.c \ - proc_vmstat.c \ - proc_uptime.c \ - sys_kernel_mm_ksm.c \ - sys_devices_system_edac_mc.c \ - sys_devices_system_node.c \ - sys_fs_cgroup.c \ - sys_fs_btrfs.c \ - $(NULL) -endif -endif - -netdata_LDADD = \ - $(OPTIONAL_MATH_LIBS) \ - $(OPTIONAL_NFACCT_LIBS) \ - $(OPTIONAL_ZLIB_LIBS) \ - $(OPTIONAL_UUID_LIBS) \ - $(NULL) - -apps_plugin_SOURCES = \ - apps_plugin.c \ - avl.c \ - avl.h \ - clocks.c \ - clocks.h \ - common.c \ - common.h \ - inlined.h \ - locks.c \ - locks.h \ - log.c log.h \ - procfile.c \ - procfile.h \ - threads.c \ - threads.h \ - web_buffer.c \ - web_buffer.h \ - $(NULL) - -if FREEBSD -apps_plugin_SOURCES += \ - plugin_freebsd.h \ - $(NULL) -else -apps_plugin_SOURCES += \ - adaptive_resortable_list.c \ - adaptive_resortable_list.h \ - $(NULL) -endif - -apps_plugin_LDADD = \ - $(OPTIONAL_MATH_LIBS) \ - $(OPTIONAL_LIBCAP_LIBS) \ - $(NULL) - -freeipmi_plugin_SOURCES = \ - freeipmi_plugin.c \ - clocks.c \ - clocks.h \ - common.c \ - common.h \ - inlined.h \ - locks.c \ - locks.h \ - log.c log.h \ - procfile.c \ - procfile.h \ - threads.c \ - threads.h \ - $(NULL) - -freeipmi_plugin_LDADD = \ - $(OPTIONAL_IPMIMONITORING_LIBS) \ - $(NULL) - -cgroup_network_SOURCES = \ - cgroup-network.c \ - clocks.c \ - clocks.h \ - common.c \ - common.h \ - inlined.h \ - locks.c \ - locks.h \ - log.c \ - log.h \ - procfile.c \ - procfile.h \ - popen.c \ - popen.h \ - signals.c \ - signals.h \ - threads.c \ - threads.h \ - $(NULL) - -cgroup_network_LDADD = \ - $(OPTIONAL_MATH_LIBS) \ - $(OPTIONAL_LIBCAP_LIBS) \ - $(NULL) diff --git a/src/Makefile.in b/src/Makefile.in deleted file mode 100644 index 75f85632..00000000 --- a/src/Makefile.in +++ /dev/null @@ -1,1238 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -sbin_PROGRAMS = netdata$(EXEEXT) -plugins_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) -@ENABLE_PLUGIN_APPS_TRUE@am__append_1 = apps.plugin -@ENABLE_PLUGIN_FREEIPMI_TRUE@am__append_2 = freeipmi.plugin -@ENABLE_PLUGIN_CGROUP_NETWORK_TRUE@am__append_3 = cgroup-network -@FREEBSD_TRUE@am__append_4 = \ -@FREEBSD_TRUE@ plugin_freebsd.c \ -@FREEBSD_TRUE@ plugin_freebsd.h \ -@FREEBSD_TRUE@ freebsd_sysctl.c \ -@FREEBSD_TRUE@ freebsd_getmntinfo.c \ -@FREEBSD_TRUE@ freebsd_getifaddrs.c \ -@FREEBSD_TRUE@ freebsd_devstat.c \ -@FREEBSD_TRUE@ zfs_common.c \ -@FREEBSD_TRUE@ zfs_common.h \ -@FREEBSD_TRUE@ freebsd_kstat_zfs.c \ -@FREEBSD_TRUE@ freebsd_ipfw.c \ -@FREEBSD_TRUE@ $(NULL) - -@FREEBSD_FALSE@@MACOS_TRUE@am__append_5 = \ -@FREEBSD_FALSE@@MACOS_TRUE@ plugin_macos.c \ -@FREEBSD_FALSE@@MACOS_TRUE@ plugin_macos.h \ -@FREEBSD_FALSE@@MACOS_TRUE@ macos_sysctl.c \ -@FREEBSD_FALSE@@MACOS_TRUE@ macos_mach_smi.c \ -@FREEBSD_FALSE@@MACOS_TRUE@ macos_fw.c \ -@FREEBSD_FALSE@@MACOS_TRUE@ $(NULL) - -@FREEBSD_FALSE@@MACOS_FALSE@am__append_6 = \ -@FREEBSD_FALSE@@MACOS_FALSE@ ipc.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ ipc.h \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_nfacct.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_nfacct.h \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.h \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc_diskspace.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc_diskspace.h \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_tc.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_tc.h \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_diskstats.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_interrupts.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_softirqs.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_loadavg.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_meminfo.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_dev.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_ip_vs_stats.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_netstat.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfs.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfsd.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp6.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat6.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_softnet_stat.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_conntrack.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_synproxy.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_self_mountinfo.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_self_mountinfo.h \ -@FREEBSD_FALSE@@MACOS_FALSE@ zfs_common.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ zfs_common.h \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_spl_kstat_zfs.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_stat.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_sys_kernel_random_entropy_avail.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_vmstat.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_uptime.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_kernel_mm_ksm.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_edac_mc.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_node.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_cgroup.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_btrfs.c \ -@FREEBSD_FALSE@@MACOS_FALSE@ $(NULL) - -@FREEBSD_TRUE@am__append_7 = \ -@FREEBSD_TRUE@ plugin_freebsd.h \ -@FREEBSD_TRUE@ $(NULL) - -@FREEBSD_FALSE@am__append_8 = \ -@FREEBSD_FALSE@ adaptive_resortable_list.c \ -@FREEBSD_FALSE@ adaptive_resortable_list.h \ -@FREEBSD_FALSE@ $(NULL) - -subdir = src -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp $(dist_cache_DATA) $(dist_log_DATA) \ - $(dist_registry_DATA) $(dist_varlib_DATA) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___atomic.m4 \ - $(top_srcdir)/m4/ax_c__generic.m4 $(top_srcdir)/m4/ax_c_lto.m4 \ - $(top_srcdir)/m4/ax_c_mallinfo.m4 \ - $(top_srcdir)/m4/ax_c_mallopt.m4 \ - $(top_srcdir)/m4/ax_check_compile_flag.m4 \ - $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ - $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/jemalloc.m4 \ - $(top_srcdir)/m4/tcmalloc.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -@ENABLE_PLUGIN_APPS_TRUE@am__EXEEXT_1 = apps.plugin$(EXEEXT) -@ENABLE_PLUGIN_FREEIPMI_TRUE@am__EXEEXT_2 = freeipmi.plugin$(EXEEXT) -@ENABLE_PLUGIN_CGROUP_NETWORK_TRUE@am__EXEEXT_3 = \ -@ENABLE_PLUGIN_CGROUP_NETWORK_TRUE@ cgroup-network$(EXEEXT) -am__installdirs = "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(sbindir)" \ - "$(DESTDIR)$(cachedir)" "$(DESTDIR)$(logdir)" \ - "$(DESTDIR)$(registrydir)" "$(DESTDIR)$(varlibdir)" -PROGRAMS = $(plugins_PROGRAMS) $(sbin_PROGRAMS) -am__apps_plugin_SOURCES_DIST = apps_plugin.c avl.c avl.h clocks.c \ - clocks.h common.c common.h inlined.h locks.c locks.h log.c \ - log.h procfile.c procfile.h threads.c threads.h web_buffer.c \ - web_buffer.h plugin_freebsd.h adaptive_resortable_list.c \ - adaptive_resortable_list.h -am__objects_1 = -@FREEBSD_FALSE@am__objects_2 = adaptive_resortable_list.$(OBJEXT) -am_apps_plugin_OBJECTS = apps_plugin.$(OBJEXT) avl.$(OBJEXT) \ - clocks.$(OBJEXT) common.$(OBJEXT) locks.$(OBJEXT) \ - log.$(OBJEXT) procfile.$(OBJEXT) threads.$(OBJEXT) \ - web_buffer.$(OBJEXT) $(am__objects_1) $(am__objects_2) -apps_plugin_OBJECTS = $(am_apps_plugin_OBJECTS) -am__DEPENDENCIES_1 = -apps_plugin_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_cgroup_network_OBJECTS = cgroup-network.$(OBJEXT) clocks.$(OBJEXT) \ - common.$(OBJEXT) locks.$(OBJEXT) log.$(OBJEXT) \ - procfile.$(OBJEXT) popen.$(OBJEXT) signals.$(OBJEXT) \ - threads.$(OBJEXT) -cgroup_network_OBJECTS = $(am_cgroup_network_OBJECTS) -cgroup_network_DEPENDENCIES = $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -am_freeipmi_plugin_OBJECTS = freeipmi_plugin.$(OBJEXT) \ - clocks.$(OBJEXT) common.$(OBJEXT) locks.$(OBJEXT) \ - log.$(OBJEXT) procfile.$(OBJEXT) threads.$(OBJEXT) -freeipmi_plugin_OBJECTS = $(am_freeipmi_plugin_OBJECTS) -freeipmi_plugin_DEPENDENCIES = $(am__DEPENDENCIES_1) -am__netdata_SOURCES_DIST = adaptive_resortable_list.c \ - adaptive_resortable_list.h appconfig.c appconfig.h avl.c avl.h \ - backend_prometheus.c backend_prometheus.h backends.c \ - backends.h clocks.c clocks.h common.c common.h daemon.c \ - daemon.h dictionary.c dictionary.h eval.c eval.h \ - global_statistics.c global_statistics.h health.c health.h \ - health_config.c health_json.c health_log.c inlined.h locks.c \ - locks.h log.c log.h main.c main.h plugin_checks.c \ - plugin_checks.h plugin_idlejitter.c plugin_idlejitter.h \ - plugins_d.c plugins_d.h popen.c popen.h procfile.c procfile.h \ - registry.c registry.h registry_db.c registry_init.c \ - registry_internals.c registry_internals.h registry_log.c \ - registry_machine.c registry_machine.h registry_person.c \ - registry_person.h registry_url.c registry_url.h rrd.c rrd.h \ - rrd2json.c rrd2json.h rrd2json_api_old.c rrd2json_api_old.h \ - rrdcalc.c rrdcalctemplate.c rrddim.c rrddimvar.c rrdfamily.c \ - rrdhost.c rrdpush.c rrdpush.h rrdset.c rrdsetvar.c rrdvar.c \ - signals.c signals.h simple_pattern.c simple_pattern.h socket.c \ - socket.h statistical.c statistical.h statsd.c statsd.h \ - storage_number.c storage_number.h threads.c threads.h \ - unit_test.c unit_test.h url.c url.h web_api_old.c \ - web_api_old.h web_api_v1.c web_api_v1.h web_buffer.c \ - web_buffer.h web_buffer_svg.c web_buffer_svg.h web_client.c \ - web_client.h web_server.c web_server.h plugin_freebsd.c \ - plugin_freebsd.h freebsd_sysctl.c freebsd_getmntinfo.c \ - freebsd_getifaddrs.c freebsd_devstat.c zfs_common.c \ - zfs_common.h freebsd_kstat_zfs.c freebsd_ipfw.c plugin_macos.c \ - plugin_macos.h macos_sysctl.c macos_mach_smi.c macos_fw.c \ - ipc.c ipc.h plugin_nfacct.c plugin_nfacct.h plugin_proc.c \ - plugin_proc.h plugin_proc_diskspace.c plugin_proc_diskspace.h \ - plugin_tc.c plugin_tc.h proc_diskstats.c proc_interrupts.c \ - proc_softirqs.c proc_loadavg.c proc_meminfo.c proc_net_dev.c \ - proc_net_ip_vs_stats.c proc_net_netstat.c proc_net_rpc_nfs.c \ - proc_net_rpc_nfsd.c proc_net_snmp.c proc_net_snmp6.c \ - proc_net_sockstat.c proc_net_sockstat6.c \ - proc_net_softnet_stat.c proc_net_stat_conntrack.c \ - proc_net_stat_synproxy.c proc_self_mountinfo.c \ - proc_self_mountinfo.h proc_spl_kstat_zfs.c proc_stat.c \ - proc_sys_kernel_random_entropy_avail.c proc_vmstat.c \ - proc_uptime.c sys_kernel_mm_ksm.c sys_devices_system_edac_mc.c \ - sys_devices_system_node.c sys_fs_cgroup.c sys_fs_btrfs.c -@FREEBSD_TRUE@am__objects_3 = plugin_freebsd.$(OBJEXT) \ -@FREEBSD_TRUE@ freebsd_sysctl.$(OBJEXT) \ -@FREEBSD_TRUE@ freebsd_getmntinfo.$(OBJEXT) \ -@FREEBSD_TRUE@ freebsd_getifaddrs.$(OBJEXT) \ -@FREEBSD_TRUE@ freebsd_devstat.$(OBJEXT) zfs_common.$(OBJEXT) \ -@FREEBSD_TRUE@ freebsd_kstat_zfs.$(OBJEXT) \ -@FREEBSD_TRUE@ freebsd_ipfw.$(OBJEXT) -@FREEBSD_FALSE@@MACOS_TRUE@am__objects_4 = plugin_macos.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_TRUE@ macos_sysctl.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_TRUE@ macos_mach_smi.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_TRUE@ macos_fw.$(OBJEXT) -@FREEBSD_FALSE@@MACOS_FALSE@am__objects_5 = ipc.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_nfacct.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc_diskspace.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ plugin_tc.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_diskstats.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_interrupts.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_softirqs.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_loadavg.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_meminfo.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_dev.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_ip_vs_stats.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_netstat.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfs.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfsd.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp6.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat6.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_softnet_stat.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_conntrack.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_synproxy.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_self_mountinfo.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ zfs_common.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_spl_kstat_zfs.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_stat.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_sys_kernel_random_entropy_avail.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_vmstat.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ proc_uptime.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_kernel_mm_ksm.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_edac_mc.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_node.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_cgroup.$(OBJEXT) \ -@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_btrfs.$(OBJEXT) -am_netdata_OBJECTS = adaptive_resortable_list.$(OBJEXT) \ - appconfig.$(OBJEXT) avl.$(OBJEXT) backend_prometheus.$(OBJEXT) \ - backends.$(OBJEXT) clocks.$(OBJEXT) common.$(OBJEXT) \ - daemon.$(OBJEXT) dictionary.$(OBJEXT) eval.$(OBJEXT) \ - global_statistics.$(OBJEXT) health.$(OBJEXT) \ - health_config.$(OBJEXT) health_json.$(OBJEXT) \ - health_log.$(OBJEXT) locks.$(OBJEXT) log.$(OBJEXT) \ - main.$(OBJEXT) plugin_checks.$(OBJEXT) \ - plugin_idlejitter.$(OBJEXT) plugins_d.$(OBJEXT) \ - popen.$(OBJEXT) procfile.$(OBJEXT) registry.$(OBJEXT) \ - registry_db.$(OBJEXT) registry_init.$(OBJEXT) \ - registry_internals.$(OBJEXT) registry_log.$(OBJEXT) \ - registry_machine.$(OBJEXT) registry_person.$(OBJEXT) \ - registry_url.$(OBJEXT) rrd.$(OBJEXT) rrd2json.$(OBJEXT) \ - rrd2json_api_old.$(OBJEXT) rrdcalc.$(OBJEXT) \ - rrdcalctemplate.$(OBJEXT) rrddim.$(OBJEXT) rrddimvar.$(OBJEXT) \ - rrdfamily.$(OBJEXT) rrdhost.$(OBJEXT) rrdpush.$(OBJEXT) \ - rrdset.$(OBJEXT) rrdsetvar.$(OBJEXT) rrdvar.$(OBJEXT) \ - signals.$(OBJEXT) simple_pattern.$(OBJEXT) socket.$(OBJEXT) \ - statistical.$(OBJEXT) statsd.$(OBJEXT) \ - storage_number.$(OBJEXT) threads.$(OBJEXT) unit_test.$(OBJEXT) \ - url.$(OBJEXT) web_api_old.$(OBJEXT) web_api_v1.$(OBJEXT) \ - web_buffer.$(OBJEXT) web_buffer_svg.$(OBJEXT) \ - web_client.$(OBJEXT) web_server.$(OBJEXT) $(am__objects_3) \ - $(am__objects_4) $(am__objects_5) -netdata_OBJECTS = $(am_netdata_OBJECTS) -netdata_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(apps_plugin_SOURCES) $(cgroup_network_SOURCES) \ - $(freeipmi_plugin_SOURCES) $(netdata_SOURCES) -DIST_SOURCES = $(am__apps_plugin_SOURCES_DIST) \ - $(cgroup_network_SOURCES) $(freeipmi_plugin_SOURCES) \ - $(am__netdata_SOURCES_DIST) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -DATA = $(dist_cache_DATA) $(dist_log_DATA) $(dist_registry_DATA) \ - $(dist_varlib_DATA) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -IPMIMONITORING_CFLAGS = @IPMIMONITORING_CFLAGS@ -IPMIMONITORING_LIBS = @IPMIMONITORING_LIBS@ -LDFLAGS = @LDFLAGS@ -LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ -LIBCAP_LIBS = @LIBCAP_LIBS@ -LIBMNL_CFLAGS = @LIBMNL_CFLAGS@ -LIBMNL_LIBS = @LIBMNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MATH_CFLAGS = @MATH_CFLAGS@ -MATH_LIBS = @MATH_LIBS@ -MKDIR_P = @MKDIR_P@ -NFACCT_CFLAGS = @NFACCT_CFLAGS@ -NFACCT_LIBS = @NFACCT_LIBS@ -OBJEXT = @OBJEXT@ -OPTIONAL_IPMIMONITORING_CFLAGS = @OPTIONAL_IPMIMONITORING_CFLAGS@ -OPTIONAL_IPMIMONITORING_LIBS = @OPTIONAL_IPMIMONITORING_LIBS@ -OPTIONAL_LIBCAP_CFLAGS = @OPTIONAL_LIBCAP_CFLAGS@ -OPTIONAL_LIBCAP_LIBS = @OPTIONAL_LIBCAP_LIBS@ -OPTIONAL_MATH_CLFAGS = @OPTIONAL_MATH_CLFAGS@ -OPTIONAL_MATH_LIBS = @OPTIONAL_MATH_LIBS@ -OPTIONAL_NFACCT_CLFAGS = @OPTIONAL_NFACCT_CLFAGS@ -OPTIONAL_NFACCT_LIBS = @OPTIONAL_NFACCT_LIBS@ -OPTIONAL_UUID_CLFAGS = @OPTIONAL_UUID_CLFAGS@ -OPTIONAL_UUID_LIBS = @OPTIONAL_UUID_LIBS@ -OPTIONAL_ZLIB_CLFAGS = @OPTIONAL_ZLIB_CLFAGS@ -OPTIONAL_ZLIB_LIBS = @OPTIONAL_ZLIB_LIBS@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_RPM_RELEASE = @PACKAGE_RPM_RELEASE@ -PACKAGE_RPM_VERSION = @PACKAGE_RPM_VERSION@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -PTHREAD_CC = @PTHREAD_CC@ -PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ -PTHREAD_LIBS = @PTHREAD_LIBS@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SSE_CANDIDATE = @SSE_CANDIDATE@ -STRIP = @STRIP@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -ZLIB_CFLAGS = @ZLIB_CFLAGS@ -ZLIB_LIBS = @ZLIB_LIBS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -ax_pthread_config = @ax_pthread_config@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -cachedir = @cachedir@ -chartsdir = @chartsdir@ -configdir = @configdir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -has_jemalloc = @has_jemalloc@ -has_tcmalloc = @has_tcmalloc@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -logdir = @logdir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nodedir = @nodedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pluginsdir = @pluginsdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pythondir = @pythondir@ -registrydir = @registrydir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -varlibdir = @varlibdir@ -webdir = @webdir@ - -# -# Copyright (C) 2015 Alon Bar-Lev <alon.barlev@gmail.com> -# -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in -AM_CPPFLAGS = \ - -DVARLIB_DIR="\"$(varlibdir)\"" \ - -DCACHE_DIR="\"$(cachedir)\"" \ - -DCONFIG_DIR="\"$(configdir)\"" \ - -DLOG_DIR="\"$(logdir)\"" \ - -DPLUGINS_DIR="\"$(pluginsdir)\"" \ - -DRUN_DIR="\"$(localstatedir)/run/netdata\"" \ - -DWEB_DIR="\"$(webdir)\"" \ - $(NULL) - -AM_CFLAGS = \ - $(OPTIONAL_MATH_CFLAGS) \ - $(OPTIONAL_NFACCT_CLFAGS) \ - $(OPTIONAL_ZLIB_CFLAGS) \ - $(OPTIONAL_UUID_CFLAGS) \ - $(OPTIONAL_LIBCAP_CFLAGS) \ - $(OPTIONAL_IPMIMONITORING_CFLAGS)\ - $(NULL) - -dist_cache_DATA = .keep -dist_varlib_DATA = .keep -dist_registry_DATA = .keep -dist_log_DATA = .keep -netdata_SOURCES = adaptive_resortable_list.c \ - adaptive_resortable_list.h appconfig.c appconfig.h avl.c avl.h \ - backend_prometheus.c backend_prometheus.h backends.c \ - backends.h clocks.c clocks.h common.c common.h daemon.c \ - daemon.h dictionary.c dictionary.h eval.c eval.h \ - global_statistics.c global_statistics.h health.c health.h \ - health_config.c health_json.c health_log.c inlined.h locks.c \ - locks.h log.c log.h main.c main.h plugin_checks.c \ - plugin_checks.h plugin_idlejitter.c plugin_idlejitter.h \ - plugins_d.c plugins_d.h popen.c popen.h procfile.c procfile.h \ - registry.c registry.h registry_db.c registry_init.c \ - registry_internals.c registry_internals.h registry_log.c \ - registry_machine.c registry_machine.h registry_person.c \ - registry_person.h registry_url.c registry_url.h rrd.c rrd.h \ - rrd2json.c rrd2json.h rrd2json_api_old.c rrd2json_api_old.h \ - rrdcalc.c rrdcalctemplate.c rrddim.c rrddimvar.c rrdfamily.c \ - rrdhost.c rrdpush.c rrdpush.h rrdset.c rrdsetvar.c rrdvar.c \ - signals.c signals.h simple_pattern.c simple_pattern.h socket.c \ - socket.h statistical.c statistical.h statsd.c statsd.h \ - storage_number.c storage_number.h threads.c threads.h \ - unit_test.c unit_test.h url.c url.h web_api_old.c \ - web_api_old.h web_api_v1.c web_api_v1.h web_buffer.c \ - web_buffer.h web_buffer_svg.c web_buffer_svg.h web_client.c \ - web_client.h web_server.c web_server.h $(NULL) $(am__append_4) \ - $(am__append_5) $(am__append_6) -netdata_LDADD = \ - $(OPTIONAL_MATH_LIBS) \ - $(OPTIONAL_NFACCT_LIBS) \ - $(OPTIONAL_ZLIB_LIBS) \ - $(OPTIONAL_UUID_LIBS) \ - $(NULL) - -apps_plugin_SOURCES = apps_plugin.c avl.c avl.h clocks.c clocks.h \ - common.c common.h inlined.h locks.c locks.h log.c log.h \ - procfile.c procfile.h threads.c threads.h web_buffer.c \ - web_buffer.h $(NULL) $(am__append_7) $(am__append_8) -apps_plugin_LDADD = \ - $(OPTIONAL_MATH_LIBS) \ - $(OPTIONAL_LIBCAP_LIBS) \ - $(NULL) - -freeipmi_plugin_SOURCES = \ - freeipmi_plugin.c \ - clocks.c \ - clocks.h \ - common.c \ - common.h \ - inlined.h \ - locks.c \ - locks.h \ - log.c log.h \ - procfile.c \ - procfile.h \ - threads.c \ - threads.h \ - $(NULL) - -freeipmi_plugin_LDADD = \ - $(OPTIONAL_IPMIMONITORING_LIBS) \ - $(NULL) - -cgroup_network_SOURCES = \ - cgroup-network.c \ - clocks.c \ - clocks.h \ - common.c \ - common.h \ - inlined.h \ - locks.c \ - locks.h \ - log.c \ - log.h \ - procfile.c \ - procfile.h \ - popen.c \ - popen.h \ - signals.c \ - signals.h \ - threads.c \ - threads.h \ - $(NULL) - -cgroup_network_LDADD = \ - $(OPTIONAL_MATH_LIBS) \ - $(OPTIONAL_LIBCAP_LIBS) \ - $(NULL) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -install-pluginsPROGRAMS: $(plugins_PROGRAMS) - @$(NORMAL_INSTALL) - @list='$(plugins_PROGRAMS)'; test -n "$(pluginsdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pluginsdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" || exit 1; \ - fi; \ - for p in $$list; do echo "$$p $$p"; done | \ - sed 's/$(EXEEXT)$$//' | \ - while read p p1; do if test -f $$p \ - ; then echo "$$p"; echo "$$p"; else :; fi; \ - done | \ - sed -e 'p;s,.*/,,;n;h' \ - -e 's|.*|.|' \ - -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ - sed 'N;N;N;s,\n, ,g' | \ - $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ - { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ - if ($$2 == $$4) files[d] = files[d] " " $$1; \ - else { print "f", $$3 "/" $$4, $$1; } } \ - END { for (d in files) print "f", d, files[d] }' | \ - while read type dir files; do \ - if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ - test -z "$$files" || { \ - echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(pluginsdir)$$dir'"; \ - $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(pluginsdir)$$dir" || exit $$?; \ - } \ - ; done - -uninstall-pluginsPROGRAMS: - @$(NORMAL_UNINSTALL) - @list='$(plugins_PROGRAMS)'; test -n "$(pluginsdir)" || list=; \ - files=`for p in $$list; do echo "$$p"; done | \ - sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ - -e 's/$$/$(EXEEXT)/' \ - `; \ - test -n "$$list" || exit 0; \ - echo " ( cd '$(DESTDIR)$(pluginsdir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(pluginsdir)" && rm -f $$files - -clean-pluginsPROGRAMS: - -test -z "$(plugins_PROGRAMS)" || rm -f $(plugins_PROGRAMS) -install-sbinPROGRAMS: $(sbin_PROGRAMS) - @$(NORMAL_INSTALL) - @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ - fi; \ - for p in $$list; do echo "$$p $$p"; done | \ - sed 's/$(EXEEXT)$$//' | \ - while read p p1; do if test -f $$p \ - ; then echo "$$p"; echo "$$p"; else :; fi; \ - done | \ - sed -e 'p;s,.*/,,;n;h' \ - -e 's|.*|.|' \ - -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ - sed 'N;N;N;s,\n, ,g' | \ - $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ - { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ - if ($$2 == $$4) files[d] = files[d] " " $$1; \ - else { print "f", $$3 "/" $$4, $$1; } } \ - END { for (d in files) print "f", d, files[d] }' | \ - while read type dir files; do \ - if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ - test -z "$$files" || { \ - echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ - $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ - } \ - ; done - -uninstall-sbinPROGRAMS: - @$(NORMAL_UNINSTALL) - @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ - files=`for p in $$list; do echo "$$p"; done | \ - sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ - -e 's/$$/$(EXEEXT)/' \ - `; \ - test -n "$$list" || exit 0; \ - echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(sbindir)" && rm -f $$files - -clean-sbinPROGRAMS: - -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) - -apps.plugin$(EXEEXT): $(apps_plugin_OBJECTS) $(apps_plugin_DEPENDENCIES) $(EXTRA_apps_plugin_DEPENDENCIES) - @rm -f apps.plugin$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(apps_plugin_OBJECTS) $(apps_plugin_LDADD) $(LIBS) - -cgroup-network$(EXEEXT): $(cgroup_network_OBJECTS) $(cgroup_network_DEPENDENCIES) $(EXTRA_cgroup_network_DEPENDENCIES) - @rm -f cgroup-network$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(cgroup_network_OBJECTS) $(cgroup_network_LDADD) $(LIBS) - -freeipmi.plugin$(EXEEXT): $(freeipmi_plugin_OBJECTS) $(freeipmi_plugin_DEPENDENCIES) $(EXTRA_freeipmi_plugin_DEPENDENCIES) - @rm -f freeipmi.plugin$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(freeipmi_plugin_OBJECTS) $(freeipmi_plugin_LDADD) $(LIBS) - -netdata$(EXEEXT): $(netdata_OBJECTS) $(netdata_DEPENDENCIES) $(EXTRA_netdata_DEPENDENCIES) - @rm -f netdata$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(netdata_OBJECTS) $(netdata_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adaptive_resortable_list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/appconfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apps_plugin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_prometheus.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backends.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgroup-network.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clocks.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dictionary.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_devstat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_getifaddrs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_getmntinfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_ipfw.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_kstat_zfs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_sysctl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freeipmi_plugin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/global_statistics.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health_config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health_json.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health_log.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/locks.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macos_fw.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macos_mach_smi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macos_sysctl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_checks.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_freebsd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_idlejitter.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_macos.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_nfacct.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_proc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_proc_diskspace.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_tc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugins_d.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popen.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_diskstats.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_interrupts.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_loadavg.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_meminfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_dev.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_ip_vs_stats.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_netstat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_rpc_nfs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_rpc_nfsd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_snmp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_snmp6.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_sockstat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_sockstat6.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_softnet_stat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_stat_conntrack.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_stat_synproxy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_self_mountinfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_softirqs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_spl_kstat_zfs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_stat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_sys_kernel_random_entropy_avail.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_uptime.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_vmstat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procfile.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_db.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_internals.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_log.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_machine.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_person.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_url.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrd2json.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrd2json_api_old.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdcalc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdcalctemplate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrddim.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrddimvar.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdfamily.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdhost.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdpush.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdset.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdsetvar.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdvar.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signals.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple_pattern.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statistical.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statsd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage_number.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_devices_system_edac_mc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_devices_system_node.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_fs_btrfs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_fs_cgroup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_kernel_mm_ksm.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threads.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unit_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/url.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_api_old.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_api_v1.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_buffer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_buffer_svg.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_client.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_server.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_common.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` -install-dist_cacheDATA: $(dist_cache_DATA) - @$(NORMAL_INSTALL) - @list='$(dist_cache_DATA)'; test -n "$(cachedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(cachedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(cachedir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(cachedir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(cachedir)" || exit $$?; \ - done - -uninstall-dist_cacheDATA: - @$(NORMAL_UNINSTALL) - @list='$(dist_cache_DATA)'; test -n "$(cachedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(cachedir)'; $(am__uninstall_files_from_dir) -install-dist_logDATA: $(dist_log_DATA) - @$(NORMAL_INSTALL) - @list='$(dist_log_DATA)'; test -n "$(logdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(logdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(logdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(logdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(logdir)" || exit $$?; \ - done - -uninstall-dist_logDATA: - @$(NORMAL_UNINSTALL) - @list='$(dist_log_DATA)'; test -n "$(logdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(logdir)'; $(am__uninstall_files_from_dir) -install-dist_registryDATA: $(dist_registry_DATA) - @$(NORMAL_INSTALL) - @list='$(dist_registry_DATA)'; test -n "$(registrydir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(registrydir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(registrydir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(registrydir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(registrydir)" || exit $$?; \ - done - -uninstall-dist_registryDATA: - @$(NORMAL_UNINSTALL) - @list='$(dist_registry_DATA)'; test -n "$(registrydir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(registrydir)'; $(am__uninstall_files_from_dir) -install-dist_varlibDATA: $(dist_varlib_DATA) - @$(NORMAL_INSTALL) - @list='$(dist_varlib_DATA)'; test -n "$(varlibdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(varlibdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(varlibdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(varlibdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(varlibdir)" || exit $$?; \ - done - -uninstall-dist_varlibDATA: - @$(NORMAL_UNINSTALL) - @list='$(dist_varlib_DATA)'; test -n "$(varlibdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(varlibdir)'; $(am__uninstall_files_from_dir) - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) $(DATA) -installdirs: - for dir in "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(cachedir)" "$(DESTDIR)$(logdir)" "$(DESTDIR)$(registrydir)" "$(DESTDIR)$(varlibdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic clean-pluginsPROGRAMS clean-sbinPROGRAMS \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-dist_cacheDATA install-dist_logDATA \ - install-dist_registryDATA install-dist_varlibDATA \ - install-pluginsPROGRAMS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-sbinPROGRAMS - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-dist_cacheDATA uninstall-dist_logDATA \ - uninstall-dist_registryDATA uninstall-dist_varlibDATA \ - uninstall-pluginsPROGRAMS uninstall-sbinPROGRAMS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-pluginsPROGRAMS clean-sbinPROGRAMS cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am \ - install-dist_cacheDATA install-dist_logDATA \ - install-dist_registryDATA install-dist_varlibDATA install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-pluginsPROGRAMS install-ps \ - install-ps-am install-sbinPROGRAMS install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-dist_cacheDATA uninstall-dist_logDATA \ - uninstall-dist_registryDATA uninstall-dist_varlibDATA \ - uninstall-pluginsPROGRAMS uninstall-sbinPROGRAMS - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/appconfig.h b/src/appconfig.h deleted file mode 100644 index 7d056e6b..00000000 --- a/src/appconfig.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef NETDATA_CONFIG_H -#define NETDATA_CONFIG_H 1 - -#define CONFIG_FILENAME "netdata.conf" - -#define CONFIG_SECTION_GLOBAL "global" -#define CONFIG_SECTION_WEB "web" -#define CONFIG_SECTION_STATSD "statsd" -#define CONFIG_SECTION_PLUGINS "plugins" -#define CONFIG_SECTION_REGISTRY "registry" -#define CONFIG_SECTION_HEALTH "health" -#define CONFIG_SECTION_BACKEND "backend" -#define CONFIG_SECTION_STREAM "stream" - -// these are used to limit the configuration names and values lengths -// they are not enforced by config.c functions (they will strdup() all strings, no matter of their length) -#define CONFIG_MAX_NAME 1024 -#define CONFIG_MAX_VALUE 2048 - -struct config { - struct section *sections; - netdata_mutex_t mutex; - avl_tree_lock index; -}; - -extern struct config - netdata_config, - stream_config; - -#define CONFIG_BOOLEAN_NO 0 -#define CONFIG_BOOLEAN_YES 1 -#define CONFIG_BOOLEAN_AUTO 2 - -extern int appconfig_load(struct config *root, char *filename, int overwrite_used); - -extern char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value); -extern long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value); -extern LONG_DOUBLE appconfig_get_float(struct config *root, const char *section, const char *name, LONG_DOUBLE value); -extern int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value); -extern int appconfig_get_boolean_ondemand(struct config *root, const char *section, const char *name, int value); - -extern const char *appconfig_set(struct config *root, const char *section, const char *name, const char *value); -extern const char *appconfig_set_default(struct config *root, const char *section, const char *name, const char *value); -extern long long appconfig_set_number(struct config *root, const char *section, const char *name, long long value); -extern LONG_DOUBLE appconfig_set_float(struct config *root, const char *section, const char *name, LONG_DOUBLE value); -extern int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value); - -extern int appconfig_exists(struct config *root, const char *section, const char *name); -extern int appconfig_move(struct config *root, const char *section_old, const char *name_old, const char *section_new, const char *name_new); - -extern void appconfig_generate(struct config *root, BUFFER *wb, int only_changed); - -// ---------------------------------------------------------------------------- -// shortcuts for the default netdata configuration - -#define config_load(filename, overwrite_used) appconfig_load(&netdata_config, filename, overwrite_used) -#define config_get(section, name, default_value) appconfig_get(&netdata_config, section, name, default_value) -#define config_get_number(section, name, value) appconfig_get_number(&netdata_config, section, name, value) -#define config_get_float(section, name, value) appconfig_get_float(&netdata_config, section, name, value) -#define config_get_boolean(section, name, value) appconfig_get_boolean(&netdata_config, section, name, value) -#define config_get_boolean_ondemand(section, name, value) appconfig_get_boolean_ondemand(&netdata_config, section, name, value) - -#define config_set(section, name, default_value) appconfig_set(&netdata_config, section, name, default_value) -#define config_set_default(section, name, value) appconfig_set_default(&netdata_config, section, name, value) -#define config_set_number(section, name, value) appconfig_set_number(&netdata_config, section, name, value) -#define config_set_float(section, name, value) appconfig_set_float(&netdata_config, section, name, value) -#define config_set_boolean(section, name, value) appconfig_set_boolean(&netdata_config, section, name, value) - -#define config_exists(section, name) appconfig_exists(&netdata_config, section, name) -#define config_move(section_old, name_old, section_new, name_new) appconfig_move(&netdata_config, section_old, name_old, section_new, name_new) - -#define config_generate(buffer, only_changed) appconfig_generate(&netdata_config, buffer, only_changed) - -#endif /* NETDATA_CONFIG_H */ diff --git a/src/backend_prometheus.h b/src/backend_prometheus.h deleted file mode 100644 index b1a021ba..00000000 --- a/src/backend_prometheus.h +++ /dev/null @@ -1,11 +0,0 @@ -// -// Created by costa on 09/07/17. -// - -#ifndef NETDATA_BACKEND_PROMETHEUS_H -#define NETDATA_BACKEND_PROMETHEUS_H - -extern void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps); -extern void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps); - -#endif //NETDATA_BACKEND_PROMETHEUS_H diff --git a/src/backends.h b/src/backends.h deleted file mode 100644 index e882f3db..00000000 --- a/src/backends.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NETDATA_BACKENDS_H -#define NETDATA_BACKENDS_H 1 - -#define BACKEND_SOURCE_DATA_AS_COLLECTED 0x00000001 -#define BACKEND_SOURCE_DATA_AVERAGE 0x00000002 -#define BACKEND_SOURCE_DATA_SUM 0x00000004 - -#define BACKEND_SOURCE_BITS (BACKEND_SOURCE_DATA_AS_COLLECTED|BACKEND_SOURCE_DATA_AVERAGE|BACKEND_SOURCE_DATA_SUM) - -extern int backend_send_names; -extern int backend_update_every; -extern uint32_t backend_options; -extern const char *backend_prefix; - -extern void *backends_main(void *ptr); - -extern int backends_can_send_rrdset(uint32_t options, RRDSET *st); -extern uint32_t backend_parse_data_source(const char *source, uint32_t mode); - -extern calculated_number backend_calculate_value_from_stored_data( - RRDSET *st // the chart - , RRDDIM *rd // the dimension - , time_t after // the start timestamp - , time_t before // the end timestamp - , uint32_t options // BACKEND_SOURCE_* bitmap - , time_t *first_timestamp // the timestamp of the first point used in this response - , time_t *last_timestamp // the timestamp that should be reported to backend -); - -#endif /* NETDATA_BACKENDS_H */ diff --git a/src/clocks.c b/src/clocks.c deleted file mode 100644 index 2b1c36e3..00000000 --- a/src/clocks.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "common.h" - -#ifndef HAVE_CLOCK_GETTIME -inline int clock_gettime(clockid_t clk_id, struct timespec *ts) { - struct timeval tv; - if(unlikely(gettimeofday(&tv, NULL) == -1)) - return -1; - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC; - return 0; -} -#endif - -static inline time_t now_sec(clockid_t clk_id) { - struct timespec ts; - if(unlikely(clock_gettime(clk_id, &ts) == -1)) - return 0; - return ts.tv_sec; -} - -static inline usec_t now_usec(clockid_t clk_id) { - struct timespec ts; - if(unlikely(clock_gettime(clk_id, &ts) == -1)) - return 0; - return (usec_t)ts.tv_sec * USEC_PER_SEC + (ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC; -} - -static inline int now_timeval(clockid_t clk_id, struct timeval *tv) { - struct timespec ts; - - if(unlikely(clock_gettime(clk_id, &ts) == -1)) { - tv->tv_sec = 0; - tv->tv_usec = 0; - return -1; - } - - tv->tv_sec = ts.tv_sec; - tv->tv_usec = (suseconds_t)((ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC); - return 0; -} - -inline time_t now_realtime_sec(void) { - return now_sec(CLOCK_REALTIME); -} - -inline usec_t now_realtime_usec(void) { - return now_usec(CLOCK_REALTIME); -} - -inline int now_realtime_timeval(struct timeval *tv) { - return now_timeval(CLOCK_REALTIME, tv); -} - -inline time_t now_monotonic_sec(void) { - return now_sec(CLOCK_MONOTONIC); -} - -inline usec_t now_monotonic_usec(void) { - return now_usec(CLOCK_MONOTONIC); -} - -inline int now_monotonic_timeval(struct timeval *tv) { - return now_timeval(CLOCK_MONOTONIC, tv); -} - -inline time_t now_boottime_sec(void) { - return now_sec(CLOCK_BOOTTIME); -} - -inline usec_t now_boottime_usec(void) { - return now_usec(CLOCK_BOOTTIME); -} - -inline int now_boottime_timeval(struct timeval *tv) { - return now_timeval(CLOCK_BOOTTIME, tv); -} - -inline usec_t timeval_usec(struct timeval *tv) { - return (usec_t)tv->tv_sec * USEC_PER_SEC + (tv->tv_usec % USEC_PER_SEC); -} - -inline msec_t timeval_msec(struct timeval *tv) { - return (msec_t)tv->tv_sec * MSEC_PER_SEC + ((tv->tv_usec % USEC_PER_SEC) / MSEC_PER_SEC); -} - -inline susec_t dt_usec_signed(struct timeval *now, struct timeval *old) { - usec_t ts1 = timeval_usec(now); - usec_t ts2 = timeval_usec(old); - - if(likely(ts1 >= ts2)) return (susec_t)(ts1 - ts2); - return -((susec_t)(ts2 - ts1)); -} - -inline usec_t dt_usec(struct timeval *now, struct timeval *old) { - usec_t ts1 = timeval_usec(now); - usec_t ts2 = timeval_usec(old); - return (ts1 > ts2) ? (ts1 - ts2) : (ts2 - ts1); -} - -inline void heartbeat_init(heartbeat_t *hb) -{ - *hb = 0ULL; -} - -usec_t heartbeat_next(heartbeat_t *hb, usec_t tick) -{ - heartbeat_t now = now_monotonic_usec(); - usec_t next = now - (now % tick) + tick; - - while(now < next) { - sleep_usec(next - now); - now = now_monotonic_usec(); - } - - if(likely(*hb != 0ULL)) { - usec_t dt = now - *hb; - *hb = now; - - if(unlikely(dt >= tick + tick / 2)) { - errno = 0; - error("heartbeat missed %llu microseconds", dt - tick); - } - - return dt; - } - else { - *hb = now; - return 0ULL; - } -} - -inline usec_t heartbeat_dt_usec(heartbeat_t *hb) -{ - if(!*hb) - return 0ULL; - return now_monotonic_usec() - *hb; -} diff --git a/src/health.h b/src/health.h deleted file mode 100644 index f4157180..00000000 --- a/src/health.h +++ /dev/null @@ -1,438 +0,0 @@ -#ifndef NETDATA_HEALTH_H -#define NETDATA_HEALTH_H - -extern int default_health_enabled; - -extern int rrdvar_compare(void *a, void *b); - -typedef enum rrdvar_type { - RRDVAR_TYPE_CALCULATED = 1, - RRDVAR_TYPE_TIME_T = 2, - RRDVAR_TYPE_COLLECTED = 3, - RRDVAR_TYPE_TOTAL = 4, - RRDVAR_TYPE_INT = 5, - RRDVAR_TYPE_CALCULATED_ALLOCATED = 6 // a custom variable, allocated on purpose (ie. not inherited from charts) - // used only for custom host global variables -} RRDVAR_TYPE; - -// the variables as stored in the variables indexes -// there are 3 indexes: -// 1. at each chart (RRDSET.rrdvar_root_index) -// 2. at each context (RRDFAMILY.rrdvar_root_index) -// 3. at each host (RRDHOST.rrdvar_root_index) -typedef struct rrdvar { - avl avl; - - char *name; - uint32_t hash; - - RRDVAR_TYPE type; - void *value; - - time_t last_updated; -} RRDVAR; - -// variables linked to charts -// We link variables to point to the values that are already -// calculated / processed by the normal data collection process -// This means, there will be no speed penalty for using -// these variables - -typedef enum rrdvar_options { - RRDVAR_OPTION_DEFAULT = (0 << 0), - RRDVAR_OPTION_ALLOCATED = (1 << 0) // the value ptr is allocated (not a reference) - // future use -} RRDVAR_OPTIONS; - -typedef struct rrdsetvar { - char *variable; // variable name - uint32_t hash; // variable name hash - - char *key_fullid; // chart type.chart id.variable - char *key_fullname; // chart type.chart name.variable - - RRDVAR_TYPE type; - void *value; - - RRDVAR_OPTIONS options; - - RRDVAR *var_local; - RRDVAR *var_family; - RRDVAR *var_host; - RRDVAR *var_family_name; - RRDVAR *var_host_name; - - struct rrdset *rrdset; - - struct rrdsetvar *next; -} RRDSETVAR; - - -// variables linked to individual dimensions -// We link variables to point the values that are already -// calculated / processed by the normal data collection process -// This means, there will be no speed penalty for using -// these variables -typedef struct rrddimvar { - char *prefix; - char *suffix; - - char *key_id; // dimension id - char *key_name; // dimension name - char *key_contextid; // context + dimension id - char *key_contextname; // context + dimension name - char *key_fullidid; // chart type.chart id + dimension id - char *key_fullidname; // chart type.chart id + dimension name - char *key_fullnameid; // chart type.chart name + dimension id - char *key_fullnamename; // chart type.chart name + dimension name - - RRDVAR_TYPE type; - void *value; - - RRDVAR_OPTIONS options; - - RRDVAR *var_local_id; - RRDVAR *var_local_name; - - RRDVAR *var_family_id; - RRDVAR *var_family_name; - RRDVAR *var_family_contextid; - RRDVAR *var_family_contextname; - - RRDVAR *var_host_chartidid; - RRDVAR *var_host_chartidname; - RRDVAR *var_host_chartnameid; - RRDVAR *var_host_chartnamename; - - struct rrddim *rrddim; - - struct rrddimvar *next; -} RRDDIMVAR; - -// calculated variables (defined in health configuration) -// These aggregate time-series data at fixed intervals -// (defined in their update_every member below) -// They increase the overhead of netdata. -// -// These calculations are allocated and linked (->next) -// under RRDHOST. -// Then are also linked to RRDSET (of course only when the -// chart is found, via ->rrdset_next and ->rrdset_prev). -// This double-linked list is maintained sorted at all times -// having as RRDSET.calculations the RRDCALC to be processed -// next. - -#define RRDCALC_FLAG_DB_ERROR 0x00000001 -#define RRDCALC_FLAG_DB_NAN 0x00000002 -/* #define RRDCALC_FLAG_DB_STALE 0x00000004 */ -#define RRDCALC_FLAG_CALC_ERROR 0x00000008 -#define RRDCALC_FLAG_WARN_ERROR 0x00000010 -#define RRDCALC_FLAG_CRIT_ERROR 0x00000020 -#define RRDCALC_FLAG_RUNNABLE 0x00000040 -#define RRDCALC_FLAG_NO_CLEAR_NOTIFICATION 0x80000000 - -typedef struct rrdcalc { - uint32_t id; // the unique id of this alarm - uint32_t next_event_id; // the next event id that will be used for this alarm - - char *name; // the name of this alarm - uint32_t hash; - - char *exec; // the command to execute when this alarm switches state - char *recipient; // the recipient of the alarm (the first parameter to exec) - - char *chart; // the chart id this should be linked to - uint32_t hash_chart; - - char *source; // the source of this alarm - char *units; // the units of the alarm - char *info; // a short description of the alarm - - int update_every; // update frequency for the alarm - - // the red and green threshold of this alarm (to be set to the chart) - calculated_number green; - calculated_number red; - - // ------------------------------------------------------------------------ - // database lookup settings - - char *dimensions; // the chart dimensions - int group; // grouping method: average, max, etc. - int before; // ending point in time-series - int after; // starting point in time-series - uint32_t options; // calculation options - - // ------------------------------------------------------------------------ - // expressions related to the alarm - - EVAL_EXPRESSION *calculation; // expression to calculate the value of the alarm - EVAL_EXPRESSION *warning; // expression to check the warning condition - EVAL_EXPRESSION *critical; // expression to check the critical condition - - // ------------------------------------------------------------------------ - // notification delay settings - - int delay_up_duration; // duration to delay notifications when alarm raises - int delay_down_duration; // duration to delay notifications when alarm lowers - int delay_max_duration; // the absolute max delay to apply to this alarm - float delay_multiplier; // multiplier for all delays when alarms switch status - // while now < delay_up_to - - // ------------------------------------------------------------------------ - // runtime information - - RRDCALC_STATUS status; // the current status of the alarm - - calculated_number value; // the current value of the alarm - calculated_number old_value; // the previous value of the alarm - - uint32_t rrdcalc_flags; // check RRDCALC_FLAG_* - - time_t last_updated; // the last update timestamp of the alarm - time_t next_update; // the next update timestamp of the alarm - time_t last_status_change; // the timestamp of the last time this alarm changed status - - time_t db_after; // the first timestamp evaluated by the db lookup - time_t db_before; // the last timestamp evaluated by the db lookup - - time_t delay_up_to_timestamp; // the timestamp up to which we should delay notifications - int delay_up_current; // the current up notification delay duration - int delay_down_current; // the current down notification delay duration - int delay_last; // the last delay we used - - // ------------------------------------------------------------------------ - // variables this alarm exposes to the rest of the alarms - - RRDVAR *local; - RRDVAR *family; - RRDVAR *hostid; - RRDVAR *hostname; - - // ------------------------------------------------------------------------ - // the chart this alarm it is linked to - - struct rrdset *rrdset; - - // linking of this alarm on its chart - struct rrdcalc *rrdset_next; - struct rrdcalc *rrdset_prev; - - struct rrdcalc *next; -} RRDCALC; - -#define RRDCALC_HAS_DB_LOOKUP(rc) ((rc)->after) - -// RRDCALCTEMPLATE -// these are to be applied to charts found dynamically -// based on their context. -typedef struct rrdcalctemplate { - char *name; - uint32_t hash_name; - - char *exec; - char *recipient; - - char *context; - uint32_t hash_context; - - char *family_match; - SIMPLE_PATTERN *family_pattern; - - char *source; // the source of this alarm - char *units; // the units of the alarm - char *info; // a short description of the alarm - - int update_every; // update frequency for the alarm - - // the red and green threshold of this alarm (to be set to the chart) - calculated_number green; - calculated_number red; - - // ------------------------------------------------------------------------ - // database lookup settings - - char *dimensions; // the chart dimensions - int group; // grouping method: average, max, etc. - int before; // ending point in time-series - int after; // starting point in time-series - uint32_t options; // calculation options - - // ------------------------------------------------------------------------ - // notification delay settings - - int delay_up_duration; // duration to delay notifications when alarm raises - int delay_down_duration; // duration to delay notifications when alarm lowers - int delay_max_duration; // the absolute max delay to apply to this alarm - float delay_multiplier; // multiplier for all delays when alarms switch status - - // ------------------------------------------------------------------------ - // expressions related to the alarm - - EVAL_EXPRESSION *calculation; - EVAL_EXPRESSION *warning; - EVAL_EXPRESSION *critical; - - struct rrdcalctemplate *next; -} RRDCALCTEMPLATE; - -#define RRDCALCTEMPLATE_HAS_CALCULATION(rt) ((rt)->after) - -#define HEALTH_ENTRY_FLAG_PROCESSED 0x00000001 -#define HEALTH_ENTRY_FLAG_UPDATED 0x00000002 -#define HEALTH_ENTRY_FLAG_EXEC_RUN 0x00000004 -#define HEALTH_ENTRY_FLAG_EXEC_FAILED 0x00000008 -#define HEALTH_ENTRY_FLAG_SAVED 0x10000000 -#define HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION 0x80000000 - -typedef struct alarm_entry { - uint32_t unique_id; - uint32_t alarm_id; - uint32_t alarm_event_id; - - time_t when; - time_t duration; - time_t non_clear_duration; - - char *name; - uint32_t hash_name; - - char *chart; - uint32_t hash_chart; - - char *family; - - char *exec; - char *recipient; - time_t exec_run_timestamp; - int exec_code; - - char *source; - char *units; - char *info; - - calculated_number old_value; - calculated_number new_value; - - char *old_value_string; - char *new_value_string; - - RRDCALC_STATUS old_status; - RRDCALC_STATUS new_status; - - uint32_t flags; - - int delay; - time_t delay_up_to_timestamp; - - uint32_t updated_by_id; - uint32_t updates_id; - - struct alarm_entry *next; -} ALARM_ENTRY; - -typedef struct alarm_log { - uint32_t next_log_id; - uint32_t next_alarm_id; - unsigned int count; - unsigned int max; - ALARM_ENTRY *alarms; - netdata_rwlock_t alarm_log_rwlock; -} ALARM_LOG; - -#include "rrd.h" - -extern void rrdsetvar_rename_all(RRDSET *st); -extern RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options); -extern void rrdsetvar_free(RRDSETVAR *rs); - -extern void rrddimvar_rename_all(RRDDIM *rd); -extern RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, const char *suffix, void *value, RRDVAR_OPTIONS options); -extern void rrddimvar_free(RRDDIMVAR *rs); - -extern void rrdsetcalc_link_matching(RRDSET *st); -extern void rrdsetcalc_unlink(RRDCALC *rc); -extern void rrdcalctemplate_link_matching(RRDSET *st); -extern RRDCALC *rrdcalc_find(RRDSET *st, const char *name); - -extern void health_init(void); -extern void *health_main(void *ptr); - -extern void health_reload(void); - -extern int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result); -extern void health_alarms2json(RRDHOST *host, BUFFER *wb, int all); -extern void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after); - -void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf); - -extern RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name); -extern void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value); - -extern RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name); -extern void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rv, calculated_number value); - -extern void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock); - -extern const char *rrdcalc_status2string(RRDCALC_STATUS status); - - -extern int health_alarm_log_open(RRDHOST *host); -extern void health_alarm_log_close(RRDHOST *host); -extern void health_log_rotate(RRDHOST *host); -extern void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae); -extern ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename); -extern void health_alarm_log_load(RRDHOST *host); -extern void health_alarm_log( - RRDHOST *host, - uint32_t alarm_id, - uint32_t alarm_event_id, - time_t when, - const char *name, - const char *chart, - const char *family, - const char *exec, - const char *recipient, - time_t duration, - calculated_number old_value, - calculated_number new_value, - RRDCALC_STATUS old_status, - RRDCALC_STATUS new_status, - const char *source, - const char *units, - const char *info, - int delay, - uint32_t flags -); - -extern void health_readdir(RRDHOST *host, const char *path); -extern char *health_config_dir(void); -extern void health_reload_host(RRDHOST *host); -extern void health_alarm_log_free(RRDHOST *host); - -extern void rrdcalc_free(RRDCALC *rc); -extern void rrdcalc_unlink_and_free(RRDHOST *host, RRDCALC *rc); - -extern void rrdcalctemplate_free(RRDCALCTEMPLATE *rt); -extern void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt); - -extern int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data); - -#ifdef NETDATA_HEALTH_INTERNALS -#define RRDVAR_MAX_LENGTH 1024 - -extern int rrdcalc_exists(RRDHOST *host, const char *chart, const char *name, uint32_t hash_chart, uint32_t hash_name); -extern uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const char *name, uint32_t *next_event_id); -extern int rrdvar_fix_name(char *variable); - -extern RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart); -extern void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc); - -extern RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value); -extern void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv); - -extern void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae); - -#endif // NETDATA_HEALTH_INTERNALS - -#endif //NETDATA_HEALTH_H diff --git a/src/ipc.h b/src/ipc.h deleted file mode 100644 index 04f9df5c..00000000 --- a/src/ipc.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef NETDATA_PLUGIN_IPC_H -#define NETDATA_PLUGIN_IPC_H 1 - -extern int do_ipc(int update_every, usec_t dt); - -#endif /* NETDATA_PLUGIN_IPC_H */ - diff --git a/src/plugin_checks.h b/src/plugin_checks.h deleted file mode 100644 index 05a40bea..00000000 --- a/src/plugin_checks.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef NETDATA_PLUGIN_CHECKS_H -#define NETDATA_PLUGIN_CHECKS_H 1 - -#ifdef NETDATA_INTERNAL_CHECKS -void *checks_main(void *ptr); -#endif // NETDATA_INTERNAL_CHECKS - -#endif /* NETDATA_PLUGIN_PROC_H */ diff --git a/src/plugin_freebsd.h b/src/plugin_freebsd.h deleted file mode 100644 index 0a6f40c1..00000000 --- a/src/plugin_freebsd.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef NETDATA_PLUGIN_FREEBSD_H -#define NETDATA_PLUGIN_FREEBSD_H 1 - -#include <sys/sysctl.h> - -#define KILO_FACTOR 1024 -#define MEGA_FACTOR 1048576 // 1024 * 1024 -#define GIGA_FACTOR 1073741824 // 1024 * 1024 * 1024 - -#define MAX_INT_DIGITS 10 // maximum number of digits for int - -void *freebsd_main(void *ptr); - -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); - -#define GETSYSCTL_MIB(name, mib) getsysctl_mib(name, mib, sizeof(mib)/sizeof(int)) - -static inline int getsysctl_mib(const char *name, int *mib, size_t len) -{ - size_t nlen = len; - - if (unlikely(sysctlnametomib(name, mib, &nlen) == -1)) { - error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); - return 1; - } - if (unlikely(nlen != len)) { - error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); - return 1; - } - return 0; -} - -#define GETSYSCTL_SIMPLE(name, mib, var) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), &(var), sizeof(var)) -#define GETSYSCTL_WSIZE(name, mib, var, size) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), var, size) - -static inline int getsysctl_simple(const char *name, int *mib, size_t miblen, void *ptr, size_t len) -{ - size_t nlen = len; - - if (unlikely(!mib[0])) - if (unlikely(getsysctl_mib(name, mib, miblen))) - return 1; - - if (unlikely(sysctl(mib, miblen, ptr, &nlen, NULL, 0) == -1)) { - error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); - return 1; - } - if (unlikely(nlen != len)) { - error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); - return 1; - } - - return 0; -} - -#define GETSYSCTL_SIZE(name, mib, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), NULL, &(size)) -#define GETSYSCTL(name, mib, var, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), &(var), &(size)) - -static inline int getsysctl(const char *name, int *mib, size_t miblen, void *ptr, size_t *len) -{ - size_t nlen = *len; - - if (unlikely(!mib[0])) - if (unlikely(getsysctl_mib(name, mib, miblen))) - return 1; - - if (unlikely(sysctl(mib, miblen, ptr, len, NULL, 0) == -1)) { - error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); - return 1; - } - if (unlikely(ptr != NULL && nlen != *len)) { - error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)*len, (unsigned long)nlen); - return 1; - } - - return 0; -} - -#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var)) - -static inline int getsysctl_by_name(const char *name, void *ptr, size_t len) -{ - size_t nlen = len; - - if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) { - error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno)); - return 1; - } - if (unlikely(nlen != len)) { - error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen); - return 1; - } - return 0; -} - -#endif /* NETDATA_PLUGIN_FREEBSD_H */ diff --git a/src/plugin_idlejitter.h b/src/plugin_idlejitter.h deleted file mode 100644 index dc82f052..00000000 --- a/src/plugin_idlejitter.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef NETDATA_PLUGIN_IDLEJITTER_H -#define NETDATA_PLUGIN_IDLEJITTER_H 1 - -extern void *cpuidlejitter_main(void *ptr); - -#endif /* NETDATA_PLUGIN_IDLEJITTER_H */ diff --git a/src/plugin_macos.h b/src/plugin_macos.h deleted file mode 100644 index 6ccf3e86..00000000 --- a/src/plugin_macos.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NETDATA_PLUGIN_MACOS_H -#define NETDATA_PLUGIN_MACOS_H 1 - -void *macos_main(void *ptr); - -#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var)) - -extern int getsysctl_by_name(const char *name, void *ptr, size_t len); - -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); - -#endif /* NETDATA_PLUGIN_MACOS_H */ diff --git a/src/plugin_nfacct.h b/src/plugin_nfacct.h deleted file mode 100644 index 88a3a923..00000000 --- a/src/plugin_nfacct.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef NETDATA_NFACCT_H -#define NETDATA_NFACCT_H 1 - -extern void *nfacct_main(void *ptr); - -#endif /* NETDATA_NFACCT_H */ - diff --git a/src/plugin_proc_diskspace.h b/src/plugin_proc_diskspace.h deleted file mode 100644 index dcec28f7..00000000 --- a/src/plugin_proc_diskspace.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef NETDATA_PLUGIN_PROC_DISKSPACE_H -#define NETDATA_PLUGIN_PROC_DISKSPACE_H - -extern void *proc_diskspace_main(void *ptr); - -#endif //NETDATA_PLUGIN_PROC_DISKSPACE_H diff --git a/src/plugin_tc.h b/src/plugin_tc.h deleted file mode 100644 index 792c6496..00000000 --- a/src/plugin_tc.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef NETDATA_PLUGIN_TC_H -#define NETDATA_PLUGIN_TC_H 1 - -extern void *tc_main(void *ptr); - -#endif /* NETDATA_PLUGIN_TC_H */ - diff --git a/src/rrd2json.c b/src/rrd2json.c deleted file mode 100644 index 24b3da34..00000000 --- a/src/rrd2json.c +++ /dev/null @@ -1,2059 +0,0 @@ -#include "common.h" - -void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used) -{ - rrdset_rdlock(st); - - buffer_sprintf(wb, - "\t\t{\n" - "\t\t\t\"id\": \"%s\",\n" - "\t\t\t\"name\": \"%s\",\n" - "\t\t\t\"type\": \"%s\",\n" - "\t\t\t\"family\": \"%s\",\n" - "\t\t\t\"context\": \"%s\",\n" - "\t\t\t\"title\": \"%s (%s)\",\n" - "\t\t\t\"priority\": %ld,\n" - "\t\t\t\"plugin\": \"%s\",\n" - "\t\t\t\"module\": \"%s\",\n" - "\t\t\t\"enabled\": %s,\n" - "\t\t\t\"units\": \"%s\",\n" - "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n" - "\t\t\t\"chart_type\": \"%s\",\n" - "\t\t\t\"duration\": %ld,\n" - "\t\t\t\"first_entry\": %ld,\n" - "\t\t\t\"last_entry\": %ld,\n" - "\t\t\t\"update_every\": %d,\n" - "\t\t\t\"dimensions\": {\n" - , st->id - , st->name - , st->type - , st->family - , st->context - , st->title, st->name - , st->priority - , st->plugin_name?st->plugin_name:"" - , st->module_name?st->module_name:"" - , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?"true":"false" - , st->units - , st->name - , rrdset_type_name(st->chart_type) - , st->entries * st->update_every - , rrdset_first_entry_t(st) - , rrdset_last_entry_t(st) - , st->update_every - ); - - unsigned long memory = st->memsize; - - size_t dimensions = 0; - RRDDIM *rd; - rrddim_foreach_read(rd, st) { - if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) continue; - - memory += rd->memsize; - - buffer_sprintf( - wb - , "%s" - "\t\t\t\t\"%s\": { \"name\": \"%s\" }" - , dimensions ? ",\n" : "" - , rd->id - , rd->name - ); - - dimensions++; - } - - if(dimensions_count) *dimensions_count += dimensions; - if(memory_used) *memory_used += memory; - - buffer_strcat(wb, "\n\t\t\t},\n\t\t\t\"green\": "); - buffer_rrd_value(wb, st->green); - buffer_strcat(wb, ",\n\t\t\t\"red\": "); - buffer_rrd_value(wb, st->red); - - buffer_strcat(wb, ",\n\t\t\t\"alarms\": {\n"); - size_t alarms = 0; - RRDCALC *rc; - for(rc = st->alarms; rc ; rc = rc->rrdset_next) { - - buffer_sprintf( - wb - , "%s" - "\t\t\t\t\"%s\": {\n" - "\t\t\t\t\t\"id\": %u,\n" - "\t\t\t\t\t\"status\": \"%s\",\n" - "\t\t\t\t\t\"units\": \"%s\",\n" - "\t\t\t\t\t\"update_every\": %d\n" - "\t\t\t\t}" - , (alarms) ? ",\n" : "" - , rc->name - , rc->id - , rrdcalc_status2string(rc->status) - , rc->units - , rc->update_every - ); - - alarms++; - } - - buffer_sprintf(wb, - "\n\t\t\t}\n\t\t}" - ); - - rrdset_unlock(st); -} - -void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) { - rrd_stats_api_v1_chart_with_data(st, wb, NULL, NULL); -} - -void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) { - static char *custom_dashboard_info_js_filename = NULL; - size_t c, dimensions = 0, memory = 0, alarms = 0; - RRDSET *st; - - time_t now = now_realtime_sec(); - - if(unlikely(!custom_dashboard_info_js_filename)) - custom_dashboard_info_js_filename = config_get(CONFIG_SECTION_WEB, "custom dashboard_info.js", ""); - - buffer_sprintf(wb, "{\n" - "\t\"hostname\": \"%s\"" - ",\n\t\"version\": \"%s\"" - ",\n\t\"os\": \"%s\"" - ",\n\t\"timezone\": \"%s\"" - ",\n\t\"update_every\": %d" - ",\n\t\"history\": %ld" - ",\n\t\"custom_info\": \"%s\"" - ",\n\t\"charts\": {" - , host->hostname - , host->program_version - , host->os - , host->timezone - , host->rrd_update_every - , host->rrd_history_entries - , custom_dashboard_info_js_filename - ); - - c = 0; - rrdhost_rdlock(host); - rrdset_foreach_read(st, host) { - if(rrdset_is_available_for_viewers(st)) { - if(c) buffer_strcat(wb, ","); - buffer_strcat(wb, "\n\t\t\""); - buffer_strcat(wb, st->id); - buffer_strcat(wb, "\": "); - rrd_stats_api_v1_chart_with_data(st, wb, &dimensions, &memory); - - c++; - st->last_accessed_time = now; - } - } - - RRDCALC *rc; - for(rc = host->alarms; rc ; rc = rc->next) { - if(rc->rrdset) - alarms++; - } - rrdhost_unlock(host); - - buffer_sprintf(wb - , "\n\t}" - ",\n\t\"charts_count\": %zu" - ",\n\t\"dimensions_count\": %zu" - ",\n\t\"alarms_count\": %zu" - ",\n\t\"rrd_memory_bytes\": %zu" - ",\n\t\"hosts_count\": %zu" - ",\n\t\"hosts\": [" - , c - , dimensions - , alarms - , memory - , rrd_hosts_available - ); - - if(unlikely(rrd_hosts_available > 1)) { - rrd_rdlock(); - - size_t found = 0; - RRDHOST *h; - rrdhost_foreach_read(h) { - if(!rrdhost_should_be_removed(h, host, now)) { - buffer_sprintf(wb - , "%s\n\t\t{" - "\n\t\t\t\"hostname\": \"%s\"" - "\n\t\t}" - , (found > 0) ? "," : "" - , h->hostname - ); - - found++; - } - } - - rrd_unlock(); - } - else { - buffer_sprintf(wb - , "\n\t\t{" - "\n\t\t\t\"hostname\": \"%s\"" - "\n\t\t}" - , host->hostname - ); - } - - buffer_sprintf(wb, "\n\t]\n}\n"); -} - -// ---------------------------------------------------------------------------- -// BASH -// /api/v1/allmetrics?format=bash - -static inline size_t shell_name_copy(char *d, const char *s, size_t usable) { - size_t n; - - for(n = 0; *s && n < usable ; d++, s++, n++) { - register char c = *s; - - if(unlikely(!isalnum(c))) *d = '_'; - else *d = (char)toupper(c); - } - *d = '\0'; - - return n; -} - -#define SHELL_ELEMENT_MAX 100 - -void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) { - rrdhost_rdlock(host); - - // for each chart - RRDSET *st; - rrdset_foreach_read(st, host) { - calculated_number total = 0.0; - char chart[SHELL_ELEMENT_MAX + 1]; - shell_name_copy(chart, st->name?st->name:st->id, SHELL_ELEMENT_MAX); - - buffer_sprintf(wb, "\n# chart: %s (name: %s)\n", st->id, st->name); - if(rrdset_is_available_for_viewers(st)) { - rrdset_rdlock(st); - - // for each dimension - RRDDIM *rd; - rrddim_foreach_read(rd, st) { - if(rd->collections_counter) { - char dimension[SHELL_ELEMENT_MAX + 1]; - shell_name_copy(dimension, rd->name?rd->name:rd->id, SHELL_ELEMENT_MAX); - - calculated_number n = rd->last_stored_value; - - if(isnan(n) || isinf(n)) - buffer_sprintf(wb, "NETDATA_%s_%s=\"\" # %s\n", chart, dimension, st->units); - else { - if(rd->multiplier < 0 || rd->divisor < 0) n = -n; - n = calculated_number_round(n); - if(!rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) total += n; - buffer_sprintf(wb, "NETDATA_%s_%s=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, dimension, n, st->units); - } - } - } - - total = calculated_number_round(total); - buffer_sprintf(wb, "NETDATA_%s_VISIBLETOTAL=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, total, st->units); - rrdset_unlock(st); - } - } - - buffer_strcat(wb, "\n# NETDATA ALARMS RUNNING\n"); - - RRDCALC *rc; - for(rc = host->alarms; rc ;rc = rc->next) { - if(!rc->rrdset) continue; - - char chart[SHELL_ELEMENT_MAX + 1]; - shell_name_copy(chart, rc->rrdset->name?rc->rrdset->name:rc->rrdset->id, SHELL_ELEMENT_MAX); - - char alarm[SHELL_ELEMENT_MAX + 1]; - shell_name_copy(alarm, rc->name, SHELL_ELEMENT_MAX); - - calculated_number n = rc->value; - - if(isnan(n) || isinf(n)) - buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"\" # %s\n", chart, alarm, rc->units); - else { - n = calculated_number_round(n); - buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, alarm, n, rc->units); - } - - buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_STATUS=\"%s\"\n", chart, alarm, rrdcalc_status2string(rc->status)); - } - - rrdhost_unlock(host); -} - -// ---------------------------------------------------------------------------- - -void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb) { - rrdhost_rdlock(host); - - buffer_strcat(wb, "{"); - - size_t chart_counter = 0; - size_t dimension_counter = 0; - - // for each chart - RRDSET *st; - rrdset_foreach_read(st, host) { - if(rrdset_is_available_for_viewers(st)) { - rrdset_rdlock(st); - - buffer_sprintf(wb, "%s\n" - "\t\"%s\": {\n" - "\t\t\"name\":\"%s\",\n" - "\t\t\"context\":\"%s\",\n" - "\t\t\"units\":\"%s\",\n" - "\t\t\"last_updated\": %ld,\n" - "\t\t\"dimensions\": {" - , chart_counter?",":"" - , st->id - , st->name - , st->context - , st->units - , rrdset_last_entry_t(st) - ); - - chart_counter++; - dimension_counter = 0; - - // for each dimension - RRDDIM *rd; - rrddim_foreach_read(rd, st) { - if(rd->collections_counter) { - - buffer_sprintf(wb, "%s\n" - "\t\t\t\"%s\": {\n" - "\t\t\t\t\"name\": \"%s\",\n" - "\t\t\t\t\"value\": " - , dimension_counter?",":"" - , rd->id - , rd->name - ); - - if(isnan(rd->last_stored_value)) - buffer_strcat(wb, "null"); - else - buffer_sprintf(wb, CALCULATED_NUMBER_FORMAT, rd->last_stored_value); - - buffer_strcat(wb, "\n\t\t\t}"); - - dimension_counter++; - } - } - - buffer_strcat(wb, "\n\t\t}\n\t}"); - rrdset_unlock(st); - } - } - - buffer_strcat(wb, "\n}"); - rrdhost_unlock(host); -} - -// ---------------------------------------------------------------------------- - -// RRDR dimension options -#define RRDR_EMPTY 0x01 // the dimension contains / the value is empty (null) -#define RRDR_RESET 0x02 // the dimension contains / the value is reset -#define RRDR_HIDDEN 0x04 // the dimension contains / the value is hidden -#define RRDR_NONZERO 0x08 // the dimension contains / the value is non-zero -#define RRDR_SELECTED 0x10 // the dimension is selected - -// RRDR result options -#define RRDR_RESULT_OPTION_ABSOLUTE 0x00000001 -#define RRDR_RESULT_OPTION_RELATIVE 0x00000002 - -typedef struct rrdresult { - RRDSET *st; // the chart this result refers to - - uint32_t result_options; // RRDR_RESULT_OPTION_* - - int d; // the number of dimensions - long n; // the number of values in the arrays - long rows; // the number of rows used - - uint8_t *od; // the options for the dimensions - - time_t *t; // array of n timestamps - calculated_number *v; // array n x d values - uint8_t *o; // array n x d options - - long c; // current line ( -1 ~ n ), ( -1 = none, use rrdr_rows() to get number of rows ) - - long group; // how many collected values were grouped for each row - int update_every; // what is the suggested update frequency in seconds - - calculated_number min; - calculated_number max; - - time_t before; - time_t after; - - int has_st_lock; // if st is read locked by us -} RRDR; - -#define rrdr_rows(r) ((r)->rows) - -/* -static void rrdr_dump(RRDR *r) -{ - long c, i; - RRDDIM *d; - - fprintf(stderr, "\nCHART %s (%s)\n", r->st->id, r->st->name); - - for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) { - fprintf(stderr, "DIMENSION %s (%s), %s%s%s%s\n" - , d->id - , d->name - , (r->od[c] & RRDR_EMPTY)?"EMPTY ":"" - , (r->od[c] & RRDR_RESET)?"RESET ":"" - , (r->od[c] & RRDR_HIDDEN)?"HIDDEN ":"" - , (r->od[c] & RRDR_NONZERO)?"NONZERO ":"" - ); - } - - if(r->rows <= 0) { - fprintf(stderr, "RRDR does not have any values in it.\n"); - return; - } - - fprintf(stderr, "RRDR includes %d values in it:\n", r->rows); - - // for each line in the array - for(i = 0; i < r->rows ;i++) { - calculated_number *cn = &r->v[ i * r->d ]; - uint8_t *co = &r->o[ i * r->d ]; - - // print the id and the timestamp of the line - fprintf(stderr, "%ld %ld ", i + 1, r->t[i]); - - // for each dimension - for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue; - - if(co[c] & RRDR_EMPTY) - fprintf(stderr, "null "); - else - fprintf(stderr, CALCULATED_NUMBER_FORMAT " %s%s%s%s " - , cn[c] - , (co[c] & RRDR_EMPTY)?"E":" " - , (co[c] & RRDR_RESET)?"R":" " - , (co[c] & RRDR_HIDDEN)?"H":" " - , (co[c] & RRDR_NONZERO)?"N":" " - ); - } - - fprintf(stderr, "\n"); - } -} -*/ - -void rrdr_disable_not_selected_dimensions(RRDR *r, uint32_t options, const char *dims) { - rrdset_check_rdlock(r->st); - - if(unlikely(!dims || !*dims || (dims[0] == '*' && dims[1] == '\0'))) return; - - int match_ids = 0, match_names = 0; - - if(unlikely(options & RRDR_OPTION_MATCH_IDS)) - match_ids = 1; - if(unlikely(options & RRDR_OPTION_MATCH_NAMES)) - match_names = 1; - - if(likely(!match_ids && !match_names)) - match_ids = match_names = 1; - - SIMPLE_PATTERN *pattern = simple_pattern_create(dims, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT); - - RRDDIM *d; - long c, dims_selected = 0, dims_not_hidden_not_zero = 0; - for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) { - if( (match_ids && simple_pattern_matches(pattern, d->id)) - || (match_names && simple_pattern_matches(pattern, d->name)) - ) { - r->od[c] |= RRDR_SELECTED; - if(unlikely(r->od[c] & RRDR_HIDDEN)) r->od[c] &= ~RRDR_HIDDEN; - dims_selected++; - - // since the user needs this dimension - // make it appear as NONZERO, to return it - // even if the dimension has only zeros - // unless option non_zero is set - if(unlikely(!(options & RRDR_OPTION_NONZERO))) - r->od[c] |= RRDR_NONZERO; - - // count the visible dimensions - if(likely(r->od[c] & RRDR_NONZERO)) - dims_not_hidden_not_zero++; - } - else { - r->od[c] |= RRDR_HIDDEN; - if(unlikely(r->od[c] & RRDR_SELECTED)) r->od[c] &= ~RRDR_SELECTED; - } - } - simple_pattern_free(pattern); - - // check if all dimensions are hidden - if(unlikely(!dims_not_hidden_not_zero && dims_selected)) { - // there are a few selected dimensions - // but they are all zero - // enable the selected ones - // to avoid returning an empty chart - for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) - if(unlikely(r->od[c] & RRDR_SELECTED)) - r->od[c] |= RRDR_NONZERO; - } -} - -void rrdr_buffer_print_format(BUFFER *wb, uint32_t format) -{ - switch(format) { - case DATASOURCE_JSON: - buffer_strcat(wb, DATASOURCE_FORMAT_JSON); - break; - - case DATASOURCE_DATATABLE_JSON: - buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSON); - break; - - case DATASOURCE_DATATABLE_JSONP: - buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSONP); - break; - - case DATASOURCE_JSONP: - buffer_strcat(wb, DATASOURCE_FORMAT_JSONP); - break; - - case DATASOURCE_SSV: - buffer_strcat(wb, DATASOURCE_FORMAT_SSV); - break; - - case DATASOURCE_CSV: - buffer_strcat(wb, DATASOURCE_FORMAT_CSV); - break; - - case DATASOURCE_TSV: - buffer_strcat(wb, DATASOURCE_FORMAT_TSV); - break; - - case DATASOURCE_HTML: - buffer_strcat(wb, DATASOURCE_FORMAT_HTML); - break; - - case DATASOURCE_JS_ARRAY: - buffer_strcat(wb, DATASOURCE_FORMAT_JS_ARRAY); - break; - - case DATASOURCE_SSV_COMMA: - buffer_strcat(wb, DATASOURCE_FORMAT_SSV_COMMA); - break; - - default: - buffer_strcat(wb, "unknown"); - break; - } -} - -uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims) -{ - rrdset_check_rdlock(r->st); - - (void)dims; - - if(options & RRDR_OPTION_NONZERO) { - long i; - - // commented due to #1514 - - //if(dims && *dims) { - // the caller wants specific dimensions - // disable NONZERO option - // to make sure we don't accidentally prevent - // the specific dimensions from being returned - // i = 0; - //} - //else { - // find how many dimensions are not zero - long c; - RRDDIM *rd; - for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue; - i++; - } - //} - - // if with nonzero we get i = 0 (no dimensions will be returned) - // disable nonzero to show all dimensions - if(!i) options &= ~RRDR_OPTION_NONZERO; - } - - return options; -} - -void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value) -{ - rrdset_check_rdlock(r->st); - - long rows = rrdr_rows(r); - long c, i; - RRDDIM *rd; - - //info("JSONWRAPPER(): %s: BEGIN", r->st->id); - char kq[2] = "", // key quote - sq[2] = ""; // string quote - - if( options & RRDR_OPTION_GOOGLE_JSON ) { - kq[0] = '\0'; - sq[0] = '\''; - } - else { - kq[0] = '"'; - sq[0] = '"'; - } - - buffer_sprintf(wb, "{\n" - " %sapi%s: 1,\n" - " %sid%s: %s%s%s,\n" - " %sname%s: %s%s%s,\n" - " %sview_update_every%s: %d,\n" - " %supdate_every%s: %d,\n" - " %sfirst_entry%s: %u,\n" - " %slast_entry%s: %u,\n" - " %sbefore%s: %u,\n" - " %safter%s: %u,\n" - " %sdimension_names%s: [" - , kq, kq - , kq, kq, sq, r->st->id, sq - , kq, kq, sq, r->st->name, sq - , kq, kq, r->update_every - , kq, kq, r->st->update_every - , kq, kq, (uint32_t)rrdset_first_entry_t(r->st) - , kq, kq, (uint32_t)rrdset_last_entry_t(r->st) - , kq, kq, (uint32_t)r->before - , kq, kq, (uint32_t)r->after - , kq, kq); - - for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - if(i) buffer_strcat(wb, ", "); - buffer_strcat(wb, sq); - buffer_strcat(wb, rd->name); - buffer_strcat(wb, sq); - i++; - } - if(!i) { -#ifdef NETDATA_INTERNAL_CHECKS - error("RRDR is empty for %s (RRDR has %d dimensions, options is 0x%08x)", r->st->id, r->d, options); -#endif - rows = 0; - buffer_strcat(wb, sq); - buffer_strcat(wb, "no data"); - buffer_strcat(wb, sq); - } - - buffer_sprintf(wb, "],\n" - " %sdimension_ids%s: [" - , kq, kq); - - for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - if(i) buffer_strcat(wb, ", "); - buffer_strcat(wb, sq); - buffer_strcat(wb, rd->id); - buffer_strcat(wb, sq); - i++; - } - if(!i) { - rows = 0; - buffer_strcat(wb, sq); - buffer_strcat(wb, "no data"); - buffer_strcat(wb, sq); - } - - buffer_sprintf(wb, "],\n" - " %slatest_values%s: [" - , kq, kq); - - for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - if(i) buffer_strcat(wb, ", "); - i++; - - storage_number n = rd->values[rrdset_last_slot(r->st)]; - - if(!does_storage_number_exist(n)) - buffer_strcat(wb, "null"); - else - buffer_rrd_value(wb, unpack_storage_number(n)); - } - if(!i) { - rows = 0; - buffer_strcat(wb, "null"); - } - - buffer_sprintf(wb, "],\n" - " %sview_latest_values%s: [" - , kq, kq); - - i = 0; - if(rows) { - calculated_number total = 1; - - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { - total = 0; - for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - calculated_number *cn = &r->v[ (0) * r->d ]; - calculated_number n = cn[c]; - - if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - total += n; - } - // prevent a division by zero - if(total == 0) total = 1; - } - - for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - if(i) buffer_strcat(wb, ", "); - i++; - - calculated_number *cn = &r->v[ (0) * r->d ]; - uint8_t *co = &r->o[ (0) * r->d ]; - calculated_number n = cn[c]; - - if(co[c] & RRDR_EMPTY) { - if(options & RRDR_OPTION_NULL2ZERO) - buffer_strcat(wb, "0"); - else - buffer_strcat(wb, "null"); - } - else { - if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) - n = n * 100 / total; - - buffer_rrd_value(wb, n); - } - } - } - if(!i) { - rows = 0; - buffer_strcat(wb, "null"); - } - - buffer_sprintf(wb, "],\n" - " %sdimensions%s: %ld,\n" - " %spoints%s: %ld,\n" - " %sformat%s: %s" - , kq, kq, i - , kq, kq, rows - , kq, kq, sq - ); - - rrdr_buffer_print_format(wb, format); - - buffer_sprintf(wb, "%s,\n" - " %sresult%s: " - , sq - , kq, kq - ); - - if(string_value) buffer_strcat(wb, sq); - //info("JSONWRAPPER(): %s: END", r->st->id); -} - -void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value) -{ - (void)format; - - char kq[2] = "", // key quote - sq[2] = ""; // string quote - - if( options & RRDR_OPTION_GOOGLE_JSON ) { - kq[0] = '\0'; - sq[0] = '\''; - } - else { - kq[0] = '"'; - sq[0] = '"'; - } - - if(string_value) buffer_strcat(wb, sq); - - buffer_sprintf(wb, ",\n %smin%s: ", kq, kq); - buffer_rrd_value(wb, r->min); - buffer_sprintf(wb, ",\n %smax%s: ", kq, kq); - buffer_rrd_value(wb, r->max); - buffer_strcat(wb, "\n}\n"); -} - -#define JSON_DATES_JS 1 -#define JSON_DATES_TIMESTAMP 2 - -static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable) -{ - rrdset_check_rdlock(r->st); - - //info("RRD2JSON(): %s: BEGIN", r->st->id); - int row_annotations = 0, dates, dates_with_new = 0; - char kq[2] = "", // key quote - sq[2] = "", // string quote - pre_label[101] = "", // before each label - post_label[101] = "", // after each label - pre_date[101] = "", // the beginning of line, to the date - post_date[101] = "", // closing the date - pre_value[101] = "", // before each value - post_value[101] = "", // after each value - post_line[101] = "", // at the end of each row - normal_annotation[201] = "", // default row annotation - overflow_annotation[201] = "", // overflow row annotation - data_begin[101] = "", // between labels and values - finish[101] = ""; // at the end of everything - - if(datatable) { - dates = JSON_DATES_JS; - if( options & RRDR_OPTION_GOOGLE_JSON ) { - kq[0] = '\0'; - sq[0] = '\''; - } - else { - kq[0] = '"'; - sq[0] = '"'; - } - row_annotations = 1; - snprintfz(pre_date, 100, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq); - snprintfz(post_date, 100, "%s}", sq); - snprintfz(pre_label, 100, ",\n {%sid%s:%s%s,%slabel%s:%s", kq, kq, sq, sq, kq, kq, sq); - snprintfz(post_label, 100, "%s,%spattern%s:%s%s,%stype%s:%snumber%s}", sq, kq, kq, sq, sq, kq, kq, sq, sq); - snprintfz(pre_value, 100, ",{%sv%s:", kq, kq); - strcpy(post_value, "}"); - strcpy(post_line, "]}"); - snprintfz(data_begin, 100, "\n ],\n %srows%s:\n [\n", kq, kq); - strcpy(finish, "\n ]\n}"); - - snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq); - snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq); - - buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq); - buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq); - buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq); - buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq); - - // remove the valueobjects flag - // google wants its own keys - if(options & RRDR_OPTION_OBJECTSROWS) - options &= ~RRDR_OPTION_OBJECTSROWS; - } - else { - kq[0] = '"'; - sq[0] = '"'; - if(options & RRDR_OPTION_GOOGLE_JSON) { - dates = JSON_DATES_JS; - dates_with_new = 1; - } - else { - dates = JSON_DATES_TIMESTAMP; - dates_with_new = 0; - } - if( options & RRDR_OPTION_OBJECTSROWS ) - strcpy(pre_date, " { "); - else - strcpy(pre_date, " [ "); - strcpy(pre_label, ", \""); - strcpy(post_label, "\""); - strcpy(pre_value, ", "); - if( options & RRDR_OPTION_OBJECTSROWS ) - strcpy(post_line, "}"); - else - strcpy(post_line, "]"); - snprintfz(data_begin, 100, "],\n %sdata%s:\n [\n", kq, kq); - strcpy(finish, "\n ]\n}"); - - buffer_sprintf(wb, "{\n %slabels%s: [", kq, kq); - buffer_sprintf(wb, "%stime%s", sq, sq); - } - - // ------------------------------------------------------------------------- - // print the JSON header - - long c, i; - RRDDIM *rd; - - // print the header lines - for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - buffer_strcat(wb, pre_label); - buffer_strcat(wb, rd->name); - buffer_strcat(wb, post_label); - i++; - } - if(!i) { - buffer_strcat(wb, pre_label); - buffer_strcat(wb, "no data"); - buffer_strcat(wb, post_label); - } - - // print the begin of row data - buffer_strcat(wb, data_begin); - - // if all dimensions are hidden, print a null - if(!i) { - buffer_strcat(wb, finish); - return; - } - - long start = 0, end = rrdr_rows(r), step = 1; - if((options & RRDR_OPTION_REVERSED)) { - start = rrdr_rows(r) - 1; - end = -1; - step = -1; - } - - // for each line in the array - calculated_number total = 1; - for(i = start; i != end ;i += step) { - calculated_number *cn = &r->v[ i * r->d ]; - uint8_t *co = &r->o[ i * r->d ]; - - time_t now = r->t[i]; - - if(dates == JSON_DATES_JS) { - // generate the local date time - struct tm tmbuf, *tm = localtime_r(&now, &tmbuf); - if(!tm) { error("localtime_r() failed."); continue; } - - if(likely(i != start)) buffer_strcat(wb, ",\n"); - buffer_strcat(wb, pre_date); - - if( options & RRDR_OPTION_OBJECTSROWS ) - buffer_sprintf(wb, "%stime%s: ", kq, kq); - - if(dates_with_new) - buffer_strcat(wb, "new "); - - buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - buffer_strcat(wb, post_date); - - if(row_annotations) { - // google supports one annotation per row - int annotation_found = 0; - for(c = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) { - if(co[c] & RRDR_RESET) { - buffer_strcat(wb, overflow_annotation); - annotation_found = 1; - break; - } - } - if(!annotation_found) - buffer_strcat(wb, normal_annotation); - } - } - else { - // print the timestamp of the line - if(likely(i != start)) buffer_strcat(wb, ",\n"); - buffer_strcat(wb, pre_date); - - if( options & RRDR_OPTION_OBJECTSROWS ) - buffer_sprintf(wb, "%stime%s: ", kq, kq); - - buffer_rrd_value(wb, (calculated_number)r->t[i]); - // in ms - if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000"); - - buffer_strcat(wb, post_date); - } - - int set_min_max = 0; - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { - total = 0; - for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - calculated_number n = cn[c]; - - if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - total += n; - } - // prevent a division by zero - if(total == 0) total = 1; - set_min_max = 1; - } - - // for each dimension - for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - calculated_number n = cn[c]; - - buffer_strcat(wb, pre_value); - - if( options & RRDR_OPTION_OBJECTSROWS ) - buffer_sprintf(wb, "%s%s%s: ", kq, rd->name, kq); - - if(co[c] & RRDR_EMPTY) { - if(options & RRDR_OPTION_NULL2ZERO) - buffer_strcat(wb, "0"); - else - buffer_strcat(wb, "null"); - } - else { - if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { - n = n * 100 / total; - - if(unlikely(set_min_max)) { - r->min = r->max = n; - set_min_max = 0; - } - - if(n < r->min) r->min = n; - if(n > r->max) r->max = n; - } - - buffer_rrd_value(wb, n); - } - - buffer_strcat(wb, post_value); - } - - buffer_strcat(wb, post_line); - } - - buffer_strcat(wb, finish); - //info("RRD2JSON(): %s: END", r->st->id); -} - -static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startline, const char *separator, const char *endline, const char *betweenlines) -{ - rrdset_check_rdlock(r->st); - - //info("RRD2CSV(): %s: BEGIN", r->st->id); - long c, i; - RRDDIM *d; - - // print the csv header - for(c = 0, i = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - if(!i) { - buffer_strcat(wb, startline); - if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); - buffer_strcat(wb, "time"); - if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); - } - buffer_strcat(wb, separator); - if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); - buffer_strcat(wb, d->name); - if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); - i++; - } - buffer_strcat(wb, endline); - - if(!i) { - // no dimensions present - return; - } - - long start = 0, end = rrdr_rows(r), step = 1; - if((options & RRDR_OPTION_REVERSED)) { - start = rrdr_rows(r) - 1; - end = -1; - step = -1; - } - - // for each line in the array - calculated_number total = 1; - for(i = start; i != end ;i += step) { - calculated_number *cn = &r->v[ i * r->d ]; - uint8_t *co = &r->o[ i * r->d ]; - - buffer_strcat(wb, betweenlines); - buffer_strcat(wb, startline); - - time_t now = r->t[i]; - - if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) { - // print the timestamp of the line - buffer_rrd_value(wb, (calculated_number)now); - // in ms - if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000"); - } - else { - // generate the local date time - struct tm tmbuf, *tm = localtime_r(&now, &tmbuf); - if(!tm) { error("localtime() failed."); continue; } - buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - } - - int set_min_max = 0; - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { - total = 0; - for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { - calculated_number n = cn[c]; - - if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - total += n; - } - // prevent a division by zero - if(total == 0) total = 1; - set_min_max = 1; - } - - // for each dimension - for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - buffer_strcat(wb, separator); - - calculated_number n = cn[c]; - - if(co[c] & RRDR_EMPTY) { - if(options & RRDR_OPTION_NULL2ZERO) - buffer_strcat(wb, "0"); - else - buffer_strcat(wb, "null"); - } - else { - if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { - n = n * 100 / total; - - if(unlikely(set_min_max)) { - r->min = r->max = n; - set_min_max = 0; - } - - if(n < r->min) r->min = n; - if(n > r->max) r->max = n; - } - - buffer_rrd_value(wb, n); - } - } - - buffer_strcat(wb, endline); - } - //info("RRD2CSV(): %s: END", r->st->id); -} - -inline static calculated_number rrdr2value(RRDR *r, long i, uint32_t options, int *all_values_are_null) { - rrdset_check_rdlock(r->st); - - long c; - RRDDIM *d; - - calculated_number *cn = &r->v[ i * r->d ]; - uint8_t *co = &r->o[ i * r->d ]; - - calculated_number sum = 0, min = 0, max = 0, v; - int all_null = 1, init = 1; - - calculated_number total = 1; - int set_min_max = 0; - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { - total = 0; - for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { - calculated_number n = cn[c]; - - if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - total += n; - } - // prevent a division by zero - if(total == 0) total = 1; - set_min_max = 1; - } - - // for each dimension - for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { - if(unlikely(r->od[c] & RRDR_HIDDEN)) continue; - if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue; - - calculated_number n = cn[c]; - - if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) - n = -n; - - if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { - n = n * 100 / total; - - if(unlikely(set_min_max)) { - r->min = r->max = n; - set_min_max = 0; - } - - if(n < r->min) r->min = n; - if(n > r->max) r->max = n; - } - - if(unlikely(init)) { - if(n > 0) { - min = 0; - max = n; - } - else { - min = n; - max = 0; - } - init = 0; - } - - if(likely(!(co[c] & RRDR_EMPTY))) { - all_null = 0; - sum += n; - } - - if(n < min) min = n; - if(n > max) max = n; - } - - if(unlikely(all_null)) { - if(likely(all_values_are_null)) - *all_values_are_null = 1; - return 0; - } - else { - if(likely(all_values_are_null)) - *all_values_are_null = 0; - } - - if(options & RRDR_OPTION_MIN2MAX) - v = max - min; - else - v = sum; - - return v; -} - -static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix, const char *separator, const char *suffix) -{ - //info("RRD2SSV(): %s: BEGIN", r->st->id); - long i; - - buffer_strcat(wb, prefix); - long start = 0, end = rrdr_rows(r), step = 1; - if((options & RRDR_OPTION_REVERSED)) { - start = rrdr_rows(r) - 1; - end = -1; - step = -1; - } - - // for each line in the array - for(i = start; i != end ;i += step) { - int all_values_are_null = 0; - calculated_number v = rrdr2value(r, i, options, &all_values_are_null); - - if(likely(i != start)) { - if(r->min > v) r->min = v; - if(r->max < v) r->max = v; - } - else { - r->min = v; - r->max = v; - } - - if(likely(i != start)) - buffer_strcat(wb, separator); - - if(all_values_are_null) { - if(options & RRDR_OPTION_NULL2ZERO) - buffer_strcat(wb, "0"); - else - buffer_strcat(wb, "null"); - } - else - buffer_rrd_value(wb, v); - } - buffer_strcat(wb, suffix); - //info("RRD2SSV(): %s: END", r->st->id); -} - -inline static calculated_number *rrdr_line_values(RRDR *r) -{ - return &r->v[ r->c * r->d ]; -} - -inline static uint8_t *rrdr_line_options(RRDR *r) -{ - return &r->o[ r->c * r->d ]; -} - -inline static int rrdr_line_init(RRDR *r, time_t t) -{ - r->c++; - - if(unlikely(r->c >= r->n)) { - error("requested to step above RRDR size for chart %s", r->st->name); - r->c = r->n - 1; - } - - // save the time - r->t[r->c] = t; - - return 1; -} - -inline static void rrdr_lock_rrdset(RRDR *r) { - if(unlikely(!r)) { - error("NULL value given!"); - return; - } - - rrdset_rdlock(r->st); - r->has_st_lock = 1; -} - -inline static void rrdr_unlock_rrdset(RRDR *r) { - if(unlikely(!r)) { - error("NULL value given!"); - return; - } - - if(likely(r->has_st_lock)) { - rrdset_unlock(r->st); - r->has_st_lock = 0; - } -} - -inline static void rrdr_free(RRDR *r) -{ - if(unlikely(!r)) { - error("NULL value given!"); - return; - } - - rrdr_unlock_rrdset(r); - freez(r->t); - freez(r->v); - freez(r->o); - freez(r->od); - freez(r); -} - -static inline void rrdr_done(RRDR *r) -{ - r->rows = r->c + 1; - r->c = 0; -} - -static RRDR *rrdr_create(RRDSET *st, long n) -{ - if(unlikely(!st)) { - error("NULL value given!"); - return NULL; - } - - RRDR *r = callocz(1, sizeof(RRDR)); - r->st = st; - - rrdr_lock_rrdset(r); - - RRDDIM *rd; - rrddim_foreach_read(rd, st) r->d++; - - r->n = n; - - r->t = mallocz(n * sizeof(time_t)); - r->v = mallocz(n * r->d * sizeof(calculated_number)); - r->o = mallocz(n * r->d * sizeof(uint8_t)); - r->od = mallocz(r->d * sizeof(uint8_t)); - - // set the hidden flag on hidden dimensions - int c; - for(c = 0, rd = st->dimensions ; rd ; c++, rd = rd->next) { - if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN))) - r->od[c] = RRDR_HIDDEN; - else - r->od[c] = 0; - } - - r->c = -1; - r->group = 1; - r->update_every = 1; - - return r; -} - -RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int group_method, long group_time, int aligned) -{ -#ifdef NETDATA_INTERNAL_CHECKS - int debug = rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?1:0; -#endif - int absolute_period_requested = -1; - - time_t first_entry_t = rrdset_first_entry_t(st); - time_t last_entry_t = rrdset_last_entry_t(st); - - if(before == 0 && after == 0) { - // dump the all the data - before = last_entry_t; - after = first_entry_t; - absolute_period_requested = 0; - } - - // allow relative for before (smaller than API_RELATIVE_TIME_MAX) - if(((before < 0)?-before:before) <= API_RELATIVE_TIME_MAX) { - if(abs(before) % st->update_every) { - // make sure it is multiple of st->update_every - if(before < 0) before = before - st->update_every - before % st->update_every; - else before = before + st->update_every - before % st->update_every; - } - if(before > 0) before = first_entry_t + before; - else before = last_entry_t + before; - absolute_period_requested = 0; - } - - // allow relative for after (smaller than API_RELATIVE_TIME_MAX) - if(((after < 0)?-after:after) <= API_RELATIVE_TIME_MAX) { - if(after == 0) after = -st->update_every; - if(abs(after) % st->update_every) { - // make sure it is multiple of st->update_every - if(after < 0) after = after - st->update_every - after % st->update_every; - else after = after + st->update_every - after % st->update_every; - } - after = before + after; - absolute_period_requested = 0; - } - - if(absolute_period_requested == -1) - absolute_period_requested = 1; - - // make sure they are within our timeframe - if(before > last_entry_t) before = last_entry_t; - if(before < first_entry_t) before = first_entry_t; - - if(after > last_entry_t) after = last_entry_t; - if(after < first_entry_t) after = first_entry_t; - - // check if they are upside down - if(after > before) { - time_t tmp = before; - before = after; - after = tmp; - } - - // the duration of the chart - time_t duration = before - after; - long available_points = duration / st->update_every; - - if(duration <= 0 || available_points <= 0) - return rrdr_create(st, 1); - - // check the number of wanted points in the result - if(unlikely(points < 0)) points = -points; - if(unlikely(points > available_points)) points = available_points; - if(unlikely(points == 0)) points = available_points; - - // calculate the desired grouping of source data points - long group = available_points / points; - if(unlikely(group <= 0)) group = 1; - if(unlikely(available_points % points > points / 2)) group++; // rounding to the closest integer - - // group_time enforces a certain grouping multiple - calculated_number group_sum_divisor = 1.0; - long group_points = 1; - if(unlikely(group_time > st->update_every)) { - if (unlikely(group_time > duration)) { - // group_time is above the available duration - - #ifdef NETDATA_INTERNAL_CHECKS - info("INTERNAL CHECK: %s: requested gtime %ld secs, is greater than the desired duration %ld secs", st->id, group_time, duration); - #endif - - group = points; // use all the points - } - else { - // the points we should group to satisfy gtime - group_points = group_time / st->update_every; - if(unlikely(group_time % group_points)) { - #ifdef NETDATA_INTERNAL_CHECKS - info("INTERNAL CHECK: %s: requested gtime %ld secs, is not a multiple of the chart's data collection frequency %d secs", st->id, group_time, st->update_every); - #endif - - group_points++; - } - - // adapt group according to group_points - if(unlikely(group < group_points)) group = group_points; // do not allow grouping below the desired one - if(unlikely(group % group_points)) group += group_points - (group % group_points); // make sure group is multiple of group_points - - //group_sum_divisor = group / group_points; - group_sum_divisor = (calculated_number)(group * st->update_every) / (calculated_number)group_time; - } - } - - time_t after_new = after - (after % ( ((aligned)?group:1) * st->update_every )); - time_t before_new = before - (before % ( ((aligned)?group:1) * st->update_every )); - long points_new = (before_new - after_new) / st->update_every / group; - - // find the starting and ending slots in our round robin db - long start_at_slot = rrdset_time2slot(st, before_new), - stop_at_slot = rrdset_time2slot(st, after_new); - -#ifdef NETDATA_INTERNAL_CHECKS - if(after_new < first_entry_t) - error("INTERNAL CHECK: after_new %u is too small, minimum %u", (uint32_t)after_new, (uint32_t)first_entry_t); - - if(after_new > last_entry_t) - error("INTERNAL CHECK: after_new %u is too big, maximum %u", (uint32_t)after_new, (uint32_t)last_entry_t); - - if(before_new < first_entry_t) - error("INTERNAL CHECK: before_new %u is too small, minimum %u", (uint32_t)before_new, (uint32_t)first_entry_t); - - if(before_new > last_entry_t) - error("INTERNAL CHECK: before_new %u is too big, maximum %u", (uint32_t)before_new, (uint32_t)last_entry_t); - - if(start_at_slot < 0 || start_at_slot >= st->entries) - error("INTERNAL CHECK: start_at_slot is invalid %ld, expected 0 to %ld", start_at_slot, st->entries - 1); - - if(stop_at_slot < 0 || stop_at_slot >= st->entries) - error("INTERNAL CHECK: stop_at_slot is invalid %ld, expected 0 to %ld", stop_at_slot, st->entries - 1); - - if(points_new > (before_new - after_new) / group / st->update_every + 1) - error("INTERNAL CHECK: points_new %ld is more than points %ld", points_new, (before_new - after_new) / group / st->update_every + 1); - - if(group < group_points) - error("INTERNAL CHECK: group %ld is less than the desired group points %ld", group, group_points); - - if(group > group_points && group % group_points) - error("INTERNAL CHECK: group %ld is not a multiple of the desired group points %ld", group, group_points); -#endif - - //info("RRD2RRDR(): %s: wanted %ld points, got %ld - group=%ld, wanted duration=%u, got %u - wanted %ld - %ld, got %ld - %ld", st->id, points, points_new, group, before - after, before_new - after_new, after, before, after_new, before_new); - - after = after_new; - before = before_new; - duration = before - after; - points = points_new; - - // Now we have: - // before = the end time of the calculation - // after = the start time of the calculation - // duration = the duration of the calculation - // group = the number of source points to aggregate / group together - // method = the method of grouping source points - // points = the number of points to generate - - - // ------------------------------------------------------------------------- - // initialize our result set - - RRDR *r = rrdr_create(st, points); - if(unlikely(!r)) { -#ifdef NETDATA_INTERNAL_CHECKS - error("INTERNAL CHECK: Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points); -#endif - return NULL; - } - - if(unlikely(!r->d)) { -#ifdef NETDATA_INTERNAL_CHECKS - error("INTERNAL CHECK: Returning empty RRDR (no dimensions in RRDSET) for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points); -#endif - return r; - } - - if(unlikely(absolute_period_requested == 1)) - r->result_options |= RRDR_RESULT_OPTION_ABSOLUTE; - else - r->result_options |= RRDR_RESULT_OPTION_RELATIVE; - - // find how many dimensions we have - long dimensions = r->d; - - - // ------------------------------------------------------------------------- - // checks for debugging -#ifdef NETDATA_INTERNAL_CHECKS - if(debug) debug(D_RRD_STATS, "INFO %s first_t: %u, last_t: %u, all_duration: %u, after: %u, before: %u, duration: %u, points: %ld, group: %ld, group_points: %ld" - , st->id - , (uint32_t)first_entry_t - , (uint32_t)last_entry_t - , (uint32_t)(last_entry_t - first_entry_t) - , (uint32_t)after - , (uint32_t)before - , (uint32_t)duration - , points - , group - , group_points - ); -#endif - - // ------------------------------------------------------------------------- - // temp arrays for keeping values per dimension - - calculated_number last_values[dimensions]; // keep the last value of each dimension - calculated_number group_values[dimensions]; // keep sums when grouping - long group_counts[dimensions]; // keep the number of values added to group_values - uint8_t group_options[dimensions]; - uint8_t found_non_zero[dimensions]; - - - // initialize them - RRDDIM *rd; - long c; - rrdset_check_rdlock(st); - for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { - last_values[c] = 0; - group_values[c] = (group_method == GROUP_MAX || group_method == GROUP_MIN)?NAN:0; - group_counts[c] = 0; - group_options[c] = 0; - found_non_zero[c] = 0; - } - - - // ------------------------------------------------------------------------- - // the main loop - - time_t now = rrdset_slot2time(st, start_at_slot), - dt = st->update_every, - group_start_t = 0; - -#ifdef NETDATA_INTERNAL_CHECKS - if(unlikely(debug)) debug(D_RRD_STATS, "BEGIN %s after_t: %u (stop_at_t: %ld), before_t: %u (start_at_t: %ld), start_t(now): %u, current_entry: %ld, entries: %ld" - , st->id - , (uint32_t)after - , stop_at_slot - , (uint32_t)before - , start_at_slot - , (uint32_t)now - , st->current_entry - , st->entries - ); -#endif - - r->group = group; - r->update_every = (int)group * st->update_every; - r->before = now; - r->after = now; - - //info("RRD2RRDR(): %s: STARTING", st->id); - - long slot = start_at_slot, counter = 0, stop_now = 0, added = 0, group_count = 0, add_this = 0; - for(; !stop_now ; now -= dt, slot--, counter++) { - if(unlikely(slot < 0)) slot = st->entries - 1; - if(unlikely(slot == stop_at_slot)) stop_now = counter; - -#ifdef NETDATA_INTERNAL_CHECKS - if(unlikely(debug)) debug(D_RRD_STATS, "ROW %s slot: %ld, entries_counter: %ld, group_count: %ld, added: %ld, now: %ld, %s %s" - , st->id - , slot - , counter - , group_count + 1 - , added - , now - , (group_count + 1 == group)?"PRINT":" - " - , (now >= after && now <= before)?"RANGE":" - " - ); -#endif - - // make sure we return data in the proper time range - if(unlikely(now > before)) continue; - if(unlikely(now < after)) break; - - if(unlikely(group_count == 0)) group_start_t = now; - group_count++; - - if(unlikely(group_count == group)) { - if(unlikely(added >= points)) break; - add_this = 1; - } - - // do the calculations - for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { - storage_number n = rd->values[slot]; - if(unlikely(!does_storage_number_exist(n))) continue; - - group_counts[c]++; - - calculated_number value = unpack_storage_number(n); - if(likely(value != 0.0)) { - group_options[c] |= RRDR_NONZERO; - found_non_zero[c] = 1; - } - - if(unlikely(did_storage_number_reset(n))) - group_options[c] |= RRDR_RESET; - - switch(group_method) { - case GROUP_MIN: - if(unlikely(isnan(group_values[c])) || - calculated_number_fabs(value) < calculated_number_fabs(group_values[c])) - group_values[c] = value; - break; - - case GROUP_MAX: - if(unlikely(isnan(group_values[c])) || - calculated_number_fabs(value) > calculated_number_fabs(group_values[c])) - group_values[c] = value; - break; - - default: - case GROUP_SUM: - case GROUP_AVERAGE: - case GROUP_UNDEFINED: - group_values[c] += value; - break; - - case GROUP_INCREMENTAL_SUM: - if(unlikely(slot == start_at_slot)) - last_values[c] = value; - - group_values[c] += last_values[c] - value; - last_values[c] = value; - break; - } - } - - // added it - if(unlikely(add_this)) { - if(unlikely(!rrdr_line_init(r, group_start_t))) break; - - r->after = now; - - calculated_number *cn = rrdr_line_values(r); - uint8_t *co = rrdr_line_options(r); - - for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { - - // update the dimension options - if(likely(found_non_zero[c])) r->od[c] |= RRDR_NONZERO; - - // store the specific point options - co[c] = group_options[c]; - - // store the value - if(unlikely(group_counts[c] == 0)) { - cn[c] = 0.0; - co[c] |= RRDR_EMPTY; - group_values[c] = (group_method == GROUP_MAX || group_method == GROUP_MIN)?NAN:0; - } - else { - switch(group_method) { - case GROUP_MIN: - case GROUP_MAX: - if(unlikely(isnan(group_values[c]))) - cn[c] = 0; - else { - cn[c] = group_values[c]; - group_values[c] = NAN; - } - break; - - case GROUP_SUM: - case GROUP_INCREMENTAL_SUM: - cn[c] = group_values[c]; - group_values[c] = 0; - break; - - default: - case GROUP_AVERAGE: - case GROUP_UNDEFINED: - if(unlikely(group_points != 1)) - cn[c] = group_values[c] / group_sum_divisor; - else - cn[c] = group_values[c] / group_counts[c]; - - group_values[c] = 0; - break; - } - - if(cn[c] < r->min) r->min = cn[c]; - if(cn[c] > r->max) r->max = cn[c]; - } - - // reset for the next loop - group_counts[c] = 0; - group_options[c] = 0; - } - - added++; - group_count = 0; - add_this = 0; - } - } - - rrdr_done(r); - //info("RRD2RRDR(): %s: END %ld loops made, %ld points generated", st->id, counter, rrdr_rows(r)); - //error("SHIFT: %s: wanted %ld points, got %ld", st->id, points, rrdr_rows(r)); - return r; -} - -int rrdset2value_api_v1( - RRDSET *st - , BUFFER *wb - , calculated_number *n - , const char *dimensions - , long points - , long long after - , long long before - , int group_method - , long group_time - , uint32_t options - , time_t *db_after - , time_t *db_before - , int *value_is_null -) { - RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, !(options & RRDR_OPTION_NOT_ALIGNED)); - if(!r) { - if(value_is_null) *value_is_null = 1; - return 500; - } - - if(rrdr_rows(r) == 0) { - rrdr_free(r); - - if(db_after) *db_after = 0; - if(db_before) *db_before = 0; - if(value_is_null) *value_is_null = 1; - - return 400; - } - - if(wb) { - if (r->result_options & RRDR_RESULT_OPTION_RELATIVE) - buffer_no_cacheable(wb); - else if (r->result_options & RRDR_RESULT_OPTION_ABSOLUTE) - buffer_cacheable(wb); - } - - options = rrdr_check_options(r, options, dimensions); - - if(dimensions) - rrdr_disable_not_selected_dimensions(r, options, dimensions); - - if(db_after) *db_after = r->after; - if(db_before) *db_before = r->before; - - long i = (options & RRDR_OPTION_REVERSED)?rrdr_rows(r) - 1:0; - *n = rrdr2value(r, i, options, value_is_null); - - rrdr_free(r); - return 200; -} - -int rrdset2anything_api_v1( - RRDSET *st - , BUFFER *wb - , BUFFER *dimensions - , uint32_t format - , long points - , long long after - , long long before - , int group_method - , long group_time - , uint32_t options - , time_t *latest_timestamp -) { - st->last_accessed_time = now_realtime_sec(); - - RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, !(options & RRDR_OPTION_NOT_ALIGNED)); - if(!r) { - buffer_strcat(wb, "Cannot generate output with these parameters on this chart."); - return 500; - } - - if(r->result_options & RRDR_RESULT_OPTION_RELATIVE) - buffer_no_cacheable(wb); - else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE) - buffer_cacheable(wb); - - options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL); - - if(dimensions) - rrdr_disable_not_selected_dimensions(r, options, buffer_tostring(dimensions)); - - if(latest_timestamp && rrdr_rows(r) > 0) - *latest_timestamp = r->before; - - switch(format) { - case DATASOURCE_SSV: - if(options & RRDR_OPTION_JSON_WRAP) { - wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1); - rrdr2ssv(r, wb, options, "", " ", ""); - rrdr_json_wrapper_end(r, wb, format, options, 1); - } - else { - wb->contenttype = CT_TEXT_PLAIN; - rrdr2ssv(r, wb, options, "", " ", ""); - } - break; - - case DATASOURCE_SSV_COMMA: - if(options & RRDR_OPTION_JSON_WRAP) { - wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1); - rrdr2ssv(r, wb, options, "", ",", ""); - rrdr_json_wrapper_end(r, wb, format, options, 1); - } - else { - wb->contenttype = CT_TEXT_PLAIN; - rrdr2ssv(r, wb, options, "", ",", ""); - } - break; - - case DATASOURCE_JS_ARRAY: - if(options & RRDR_OPTION_JSON_WRAP) { - wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 0); - rrdr2ssv(r, wb, options, "[", ",", "]"); - rrdr_json_wrapper_end(r, wb, format, options, 0); - } - else { - wb->contenttype = CT_APPLICATION_JSON; - rrdr2ssv(r, wb, options, "[", ",", "]"); - } - break; - - case DATASOURCE_CSV: - if(options & RRDR_OPTION_JSON_WRAP) { - wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1); - rrdr2csv(r, wb, options, "", ",", "\\n", ""); - rrdr_json_wrapper_end(r, wb, format, options, 1); - } - else { - wb->contenttype = CT_TEXT_PLAIN; - rrdr2csv(r, wb, options, "", ",", "\r\n", ""); - } - break; - - case DATASOURCE_CSV_JSON_ARRAY: - wb->contenttype = CT_APPLICATION_JSON; - if(options & RRDR_OPTION_JSON_WRAP) { - rrdr_json_wrapper_begin(r, wb, format, options, 0); - buffer_strcat(wb, "[\n"); - rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n"); - buffer_strcat(wb, "\n]"); - rrdr_json_wrapper_end(r, wb, format, options, 0); - } - else { - wb->contenttype = CT_TEXT_PLAIN; - buffer_strcat(wb, "[\n"); - rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n"); - buffer_strcat(wb, "\n]"); - } - break; - - case DATASOURCE_TSV: - if(options & RRDR_OPTION_JSON_WRAP) { - wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1); - rrdr2csv(r, wb, options, "", "\t", "\\n", ""); - rrdr_json_wrapper_end(r, wb, format, options, 1); - } - else { - wb->contenttype = CT_TEXT_PLAIN; - rrdr2csv(r, wb, options, "", "\t", "\r\n", ""); - } - break; - - case DATASOURCE_HTML: - if(options & RRDR_OPTION_JSON_WRAP) { - wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1); - buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n"); - rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\\n", ""); - buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n"); - rrdr_json_wrapper_end(r, wb, format, options, 1); - } - else { - wb->contenttype = CT_TEXT_HTML; - buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n"); - rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\n", ""); - buffer_strcat(wb, "</table>\n</center>\n</html>\n"); - } - break; - - case DATASOURCE_DATATABLE_JSONP: - wb->contenttype = CT_APPLICATION_X_JAVASCRIPT; - - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0); - - rrdr2json(r, wb, options, 1); - - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_end(r, wb, format, options, 0); - break; - - case DATASOURCE_DATATABLE_JSON: - wb->contenttype = CT_APPLICATION_JSON; - - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0); - - rrdr2json(r, wb, options, 1); - - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_end(r, wb, format, options, 0); - break; - - case DATASOURCE_JSONP: - wb->contenttype = CT_APPLICATION_X_JAVASCRIPT; - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0); - - rrdr2json(r, wb, options, 0); - - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_end(r, wb, format, options, 0); - break; - - case DATASOURCE_JSON: - default: - wb->contenttype = CT_APPLICATION_JSON; - - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0); - - rrdr2json(r, wb, options, 0); - - if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_end(r, wb, format, options, 0); - break; - } - - rrdr_free(r); - return 200; -} diff --git a/src/rrd2json.h b/src/rrd2json.h deleted file mode 100644 index b41c814e..00000000 --- a/src/rrd2json.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef NETDATA_RRD2JSON_H -#define NETDATA_RRD2JSON_H 1 - -#define HOSTNAME_MAX 1024 - -#define API_RELATIVE_TIME_MAX (3 * 365 * 86400) - -// type of JSON generations -#define DATASOURCE_INVALID (-1) -#define DATASOURCE_JSON 0 -#define DATASOURCE_DATATABLE_JSON 1 -#define DATASOURCE_DATATABLE_JSONP 2 -#define DATASOURCE_SSV 3 -#define DATASOURCE_CSV 4 -#define DATASOURCE_JSONP 5 -#define DATASOURCE_TSV 6 -#define DATASOURCE_HTML 7 -#define DATASOURCE_JS_ARRAY 8 -#define DATASOURCE_SSV_COMMA 9 -#define DATASOURCE_CSV_JSON_ARRAY 10 - -#define DATASOURCE_FORMAT_JSON "json" -#define DATASOURCE_FORMAT_DATATABLE_JSON "datatable" -#define DATASOURCE_FORMAT_DATATABLE_JSONP "datasource" -#define DATASOURCE_FORMAT_JSONP "jsonp" -#define DATASOURCE_FORMAT_SSV "ssv" -#define DATASOURCE_FORMAT_CSV "csv" -#define DATASOURCE_FORMAT_TSV "tsv" -#define DATASOURCE_FORMAT_HTML "html" -#define DATASOURCE_FORMAT_JS_ARRAY "array" -#define DATASOURCE_FORMAT_SSV_COMMA "ssvcomma" -#define DATASOURCE_FORMAT_CSV_JSON_ARRAY "csvjsonarray" - -#define ALLMETRICS_FORMAT_SHELL "shell" -#define ALLMETRICS_FORMAT_PROMETHEUS "prometheus" -#define ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS "prometheus_all_hosts" -#define ALLMETRICS_FORMAT_JSON "json" - -#define ALLMETRICS_SHELL 1 -#define ALLMETRICS_PROMETHEUS 2 -#define ALLMETRICS_JSON 3 -#define ALLMETRICS_PROMETHEUS_ALL_HOSTS 4 - -#define GROUP_UNDEFINED 0 -#define GROUP_AVERAGE 1 -#define GROUP_MIN 2 -#define GROUP_MAX 3 -#define GROUP_SUM 4 -#define GROUP_INCREMENTAL_SUM 5 - -#define RRDR_OPTION_NONZERO 0x00000001 // don't output dimensions will just zero values -#define RRDR_OPTION_REVERSED 0x00000002 // output the rows in reverse order (oldest to newest) -#define RRDR_OPTION_ABSOLUTE 0x00000004 // values positive, for DATASOURCE_SSV before summing -#define RRDR_OPTION_MIN2MAX 0x00000008 // when adding dimensions, use max - min, instead of sum -#define RRDR_OPTION_SECONDS 0x00000010 // output seconds, instead of dates -#define RRDR_OPTION_MILLISECONDS 0x00000020 // output milliseconds, instead of dates -#define RRDR_OPTION_NULL2ZERO 0x00000040 // do not show nulls, convert them to zeros -#define RRDR_OPTION_OBJECTSROWS 0x00000080 // each row of values should be an object, not an array -#define RRDR_OPTION_GOOGLE_JSON 0x00000100 // comply with google JSON/JSONP specs -#define RRDR_OPTION_JSON_WRAP 0x00000200 // wrap the response in a JSON header with info about the result -#define RRDR_OPTION_LABEL_QUOTES 0x00000400 // in CSV output, wrap header labels in double quotes -#define RRDR_OPTION_PERCENTAGE 0x00000800 // give values as percentage of total -#define RRDR_OPTION_NOT_ALIGNED 0x00001000 // do not align charts for persistant timeframes -#define RRDR_OPTION_DISPLAY_ABS 0x00002000 // for badges, display the absolute value, but calculate colors with sign -#define RRDR_OPTION_MATCH_IDS 0x00004000 // when filtering dimensions, match only IDs -#define RRDR_OPTION_MATCH_NAMES 0x00008000 // when filtering dimensions, match only names - -extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb); -extern void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb); - -extern void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb); -extern void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb); - -extern int rrdset2anything_api_v1(RRDSET *st, BUFFER *out, BUFFER *dimensions, uint32_t format, long points - , long long after, long long before, int group_method, long group_time, uint32_t options - , time_t *latest_timestamp); - -extern int rrdset2value_api_v1(RRDSET *st, BUFFER *wb, calculated_number *n, const char *dimensions, long points - , long long after, long long before, int group_method, long group_time, uint32_t options - , time_t *db_after, time_t *db_before, int *value_is_null); - -#endif /* NETDATA_RRD2JSON_H */ diff --git a/src/rrd2json_api_old.c b/src/rrd2json_api_old.c deleted file mode 100644 index 003b8626..00000000 --- a/src/rrd2json_api_old.c +++ /dev/null @@ -1,487 +0,0 @@ -#include "common.h" - -unsigned long rrdset_info2json_api_old(RRDSET *st, char *options, BUFFER *wb) { - time_t now = now_realtime_sec(); - - rrdset_rdlock(st); - - st->last_accessed_time = now; - - buffer_sprintf(wb, - "\t\t{\n" - "\t\t\t\"id\": \"%s\",\n" - "\t\t\t\"name\": \"%s\",\n" - "\t\t\t\"type\": \"%s\",\n" - "\t\t\t\"family\": \"%s\",\n" - "\t\t\t\"context\": \"%s\",\n" - "\t\t\t\"title\": \"%s (%s)\",\n" - "\t\t\t\"priority\": %ld,\n" - "\t\t\t\"enabled\": %d,\n" - "\t\t\t\"units\": \"%s\",\n" - "\t\t\t\"url\": \"/data/%s/%s\",\n" - "\t\t\t\"chart_type\": \"%s\",\n" - "\t\t\t\"counter\": %lu,\n" - "\t\t\t\"entries\": %ld,\n" - "\t\t\t\"first_entry_t\": %ld,\n" - "\t\t\t\"last_entry\": %lu,\n" - "\t\t\t\"last_entry_t\": %ld,\n" - "\t\t\t\"last_entry_secs_ago\": %ld,\n" - "\t\t\t\"update_every\": %d,\n" - "\t\t\t\"isdetail\": %d,\n" - "\t\t\t\"usec_since_last_update\": %llu,\n" - "\t\t\t\"collected_total\": " TOTAL_NUMBER_FORMAT ",\n" - "\t\t\t\"last_collected_total\": " TOTAL_NUMBER_FORMAT ",\n" - "\t\t\t\"dimensions\": [\n" - , st->id - , st->name - , st->type - , st->family - , st->context - , st->title, st->name - , st->priority - , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?1:0 - , st->units - , st->name, options?options:"" - , rrdset_type_name(st->chart_type) - , st->counter - , st->entries - , rrdset_first_entry_t(st) - , rrdset_last_slot(st) - , rrdset_last_entry_t(st) - , (now < rrdset_last_entry_t(st)) ? (time_t)0 : now - rrdset_last_entry_t(st) - , st->update_every - , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?1:0 - , st->usec_since_last_update - , st->collected_total - , st->last_collected_total - ); - - unsigned long memory = st->memsize; - - RRDDIM *rd; - rrddim_foreach_read(rd, st) { - - memory += rd->memsize; - - buffer_sprintf(wb, - "\t\t\t\t{\n" - "\t\t\t\t\t\"id\": \"%s\",\n" - "\t\t\t\t\t\"name\": \"%s\",\n" - "\t\t\t\t\t\"entries\": %ld,\n" - "\t\t\t\t\t\"isHidden\": %d,\n" - "\t\t\t\t\t\"algorithm\": \"%s\",\n" - "\t\t\t\t\t\"multiplier\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"divisor\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"last_entry_t\": %ld,\n" - "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"memory\": %lu\n" - "\t\t\t\t}%s\n" - , rd->id - , rd->name - , rd->entries - , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0 - , rrd_algorithm_name(rd->algorithm) - , rd->multiplier - , rd->divisor - , rd->last_collected_time.tv_sec - , rd->collected_value - , rd->calculated_value - , rd->last_collected_value - , rd->last_calculated_value - , rd->memsize - , rd->next?",":"" - ); - } - - buffer_sprintf(wb, - "\t\t\t],\n" - "\t\t\t\"memory\" : %lu\n" - "\t\t}" - , memory - ); - - rrdset_unlock(st); - return memory; -} - -#define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n" -#define RRD_GRAPH_JSON_FOOTER "\n\t]\n}\n" - -void rrd_graph2json_api_old(RRDSET *st, char *options, BUFFER *wb) -{ - buffer_strcat(wb, RRD_GRAPH_JSON_HEADER); - rrdset_info2json_api_old(st, options, wb); - buffer_strcat(wb, RRD_GRAPH_JSON_FOOTER); -} - -void rrd_all2json_api_old(RRDHOST *host, BUFFER *wb) -{ - unsigned long memory = 0; - long c = 0; - RRDSET *st; - - time_t now = now_realtime_sec(); - - buffer_strcat(wb, RRD_GRAPH_JSON_HEADER); - - rrdhost_rdlock(host); - rrdset_foreach_read(st, host) { - if(rrdset_is_available_for_viewers(st)) { - if(c) buffer_strcat(wb, ",\n"); - memory += rrdset_info2json_api_old(st, NULL, wb); - - c++; - st->last_accessed_time = now; - } - } - rrdhost_unlock(host); - - buffer_sprintf(wb, "\n\t],\n" - "\t\"hostname\": \"%s\",\n" - "\t\"update_every\": %d,\n" - "\t\"history\": %ld,\n" - "\t\"memory\": %lu\n" - "}\n" - , host->hostname - , host->rrd_update_every - , host->rrd_history_entries - , memory - ); -} - -time_t rrdset2json_api_old( - int type - , RRDSET *st - , BUFFER *wb - , long points - , long group - , int group_method - , time_t after - , time_t before - , int only_non_zero -) { - int c; - rrdset_rdlock(st); - - st->last_accessed_time = now_realtime_sec(); - - // ------------------------------------------------------------------------- - // switch from JSON to google JSON - - char kq[2] = "\""; - char sq[2] = "\""; - switch(type) { - case DATASOURCE_DATATABLE_JSON: - case DATASOURCE_DATATABLE_JSONP: - kq[0] = '\0'; - sq[0] = '\''; - break; - - case DATASOURCE_JSON: - default: - break; - } - - - // ------------------------------------------------------------------------- - // validate the parameters - - if(points < 1) points = 1; - if(group < 1) group = 1; - - if(before == 0 || before > rrdset_last_entry_t(st)) before = rrdset_last_entry_t(st); - if(after == 0 || after < rrdset_first_entry_t(st)) after = rrdset_first_entry_t(st); - - // --- - - // our return value (the last timestamp printed) - // this is required to detect re-transmit in google JSONP - time_t last_timestamp = 0; - - - // ------------------------------------------------------------------------- - // find how many dimensions we have - - int dimensions = 0; - RRDDIM *rd; - rrddim_foreach_read(rd, st) dimensions++; - if(!dimensions) { - rrdset_unlock(st); - buffer_strcat(wb, "No dimensions yet."); - return 0; - } - - - // ------------------------------------------------------------------------- - // prepare various strings, to speed up the loop - - char overflow_annotation[201]; snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq); - char normal_annotation[201]; snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq); - char pre_date[51]; snprintfz(pre_date, 50, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq); - char post_date[21]; snprintfz(post_date, 20, "%s}", sq); - char pre_value[21]; snprintfz(pre_value, 20, ",{%sv%s:", kq, kq); - char post_value[21]; strcpy(post_value, "}"); - - - // ------------------------------------------------------------------------- - // checks for debugging - - if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)) { - debug(D_RRD_STATS, "%s first_entry_t = %ld, last_entry_t = %ld, duration = %ld, after = %ld, before = %ld, duration = %ld, entries_to_show = %ld, group = %ld" - , st->id - , rrdset_first_entry_t(st) - , rrdset_last_entry_t(st) - , rrdset_last_entry_t(st) - rrdset_first_entry_t(st) - , after - , before - , before - after - , points - , group - ); - - if(before < after) - debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%ld) is earlier than the oldest (%ld)", st->name, before, after); - - if((before - after) > st->entries * st->update_every) - debug(D_RRD_STATS, "WARNING: %s The time difference between the oldest and the newest entries (%ld) is higher than the capacity of the database (%ld)", st->name, before - after, st->entries * st->update_every); - } - - - // ------------------------------------------------------------------------- - // temp arrays for keeping values per dimension - - calculated_number group_values[dimensions]; // keep sums when grouping - int print_hidden[dimensions]; // keep hidden flags - int found_non_zero[dimensions]; - int found_non_existing[dimensions]; - - // initialize them - for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { - group_values[c] = 0; - print_hidden[c] = rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0; - found_non_zero[c] = 0; - found_non_existing[c] = 0; - } - - - // error("OLD: points=%d after=%d before=%d group=%d, duration=%d", entries_to_show, before - (st->update_every * group * entries_to_show), before, group, before - after + 1); - // rrd2array(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method, only_non_zero); - // rrd2rrdr(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method); - - // ------------------------------------------------------------------------- - // remove dimensions that contain only zeros - - int max_loop = 1; - if(only_non_zero) max_loop = 2; - - for(; max_loop ; max_loop--) { - - // ------------------------------------------------------------------------- - // print the JSON header - - buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq); - buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq); - buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq); - buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq); - - // print the header for each dimension - // and update the print_hidden array for the dimensions that should be hidden - int pc = 0; - for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { - if(!print_hidden[c]) { - pc++; - buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq); - } - } - if(!pc) { - buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq); - } - - // print the begin of row data - buffer_sprintf(wb, "\n ],\n %srows%s:\n [\n", kq, kq); - - - // ------------------------------------------------------------------------- - // the main loop - - int annotate_reset = 0; - int annotation_count = 0; - - long t = rrdset_time2slot(st, before), - stop_at_t = rrdset_time2slot(st, after), - stop_now = 0; - - t -= t % group; - - time_t now = rrdset_slot2time(st, t), - dt = st->update_every; - - long count = 0, printed = 0, group_count = 0; - last_timestamp = 0; - - if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) - debug(D_RRD_STATS, "%s: REQUEST after:%u before:%u, points:%ld, group:%ld, CHART cur:%ld first: %u last:%u, CALC start_t:%ld, stop_t:%ld" - , st->id - , (uint32_t)after - , (uint32_t)before - , points - , group - , st->current_entry - , (uint32_t)rrdset_first_entry_t(st) - , (uint32_t)rrdset_last_entry_t(st) - , t - , stop_at_t - ); - - long counter = 0; - for(; !stop_now ; now -= dt, t--, counter++) { - if(t < 0) t = st->entries - 1; - if(t == stop_at_t) stop_now = counter; - - int print_this = 0; - - if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) - debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %ld, %s %s" - , st->id - , t - , count + 1 - , group_count + 1 - , printed - , now - , (group_count + 1 == group)?"PRINT":" - " - , (now >= after && now <= before)?"RANGE":" - " - ); - - - // make sure we return data in the proper time range - if(now > before) continue; - if(now < after) break; - - //if(rrdset_slot2time(st, t) != now) - // error("%s: slot=%ld, now=%ld, slot2time=%ld, diff=%ld, last_entry_t=%ld, rrdset_last_slot=%ld", st->id, t, now, rrdset_slot2time(st,t), now - rrdset_slot2time(st,t), rrdset_last_entry_t(st), rrdset_last_slot(st)); - - count++; - group_count++; - - // check if we have to print this now - if(group_count == group) { - if(printed >= points) { - // debug(D_RRD_STATS, "Already printed all rows. Stopping."); - break; - } - - // generate the local date time - struct tm tmbuf, *tm = localtime_r(&now, &tmbuf); - if(!tm) { error("localtime() failed."); continue; } - if(now > last_timestamp) last_timestamp = now; - - if(printed) buffer_strcat(wb, "]},\n"); - buffer_strcat(wb, pre_date); - buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - buffer_strcat(wb, post_date); - - print_this = 1; - } - - // do the calculations - for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { - storage_number n = rd->values[t]; - calculated_number value = unpack_storage_number(n); - - if(!does_storage_number_exist(n)) { - value = 0.0; - found_non_existing[c]++; - } - if(did_storage_number_reset(n)) annotate_reset = 1; - - switch(group_method) { - case GROUP_MAX: - if(abs(value) > abs(group_values[c])) group_values[c] = value; - break; - - case GROUP_SUM: - group_values[c] += value; - break; - - default: - case GROUP_AVERAGE: - group_values[c] += value; - if(print_this) group_values[c] /= ( group_count - found_non_existing[c] ); - break; - } - } - - if(print_this) { - if(annotate_reset) { - annotation_count++; - buffer_strcat(wb, overflow_annotation); - annotate_reset = 0; - } - else - buffer_strcat(wb, normal_annotation); - - pc = 0; - for(c = 0 ; c < dimensions ; c++) { - if(found_non_existing[c] == group_count) { - // all entries are non-existing - pc++; - buffer_strcat(wb, pre_value); - buffer_strcat(wb, "null"); - buffer_strcat(wb, post_value); - } - else if(!print_hidden[c]) { - pc++; - buffer_strcat(wb, pre_value); - buffer_rrd_value(wb, group_values[c]); - buffer_strcat(wb, post_value); - - if(group_values[c]) found_non_zero[c]++; - } - - // reset them for the next loop - group_values[c] = 0; - found_non_existing[c] = 0; - } - - // if all dimensions are hidden, print a null - if(!pc) { - buffer_strcat(wb, pre_value); - buffer_strcat(wb, "null"); - buffer_strcat(wb, post_value); - } - - printed++; - group_count = 0; - } - } - - if(printed) buffer_strcat(wb, "]}"); - buffer_strcat(wb, "\n ]\n}\n"); - - if(only_non_zero && max_loop > 1) { - int changed = 0; - for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { - group_values[c] = 0; - found_non_existing[c] = 0; - - if(!print_hidden[c] && !found_non_zero[c]) { - changed = 1; - print_hidden[c] = 1; - } - } - - if(changed) buffer_flush(wb); - else break; - } - else break; - - } // max_loop - - debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %zu bytes", st->name, wb->len); - - rrdset_unlock(st); - return last_timestamp; -} diff --git a/src/rrd2json_api_old.h b/src/rrd2json_api_old.h deleted file mode 100644 index f8c63814..00000000 --- a/src/rrd2json_api_old.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NETDATA_RRD2JSON_API_OLD_H -#define NETDATA_RRD2JSON_API_OLD_H - -extern unsigned long rrdset_info2json_api_old(RRDSET *st, char *options, BUFFER *wb); - -extern void rrd_graph2json_api_old(RRDSET *st, char *options, BUFFER *wb); - -extern void rrd_all2json_api_old(RRDHOST *host, BUFFER *wb); - -extern time_t rrdset2json_api_old(int type, RRDSET *st, BUFFER *wb, long entries_to_show, long group, int group_method - , time_t after, time_t before, int only_non_zero); - - -#endif //NETDATA_RRD2JSON_API_OLD_H diff --git a/src/statsd.h b/src/statsd.h deleted file mode 100644 index 17af098e..00000000 --- a/src/statsd.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef NETDATA_STATSD_H -#define NETDATA_STATSD_H - -#define STATSD_LISTEN_PORT 8125 -#define STATSD_LISTEN_BACKLOG 4096 - -extern void *statsd_main(void *ptr); - -#endif //NETDATA_STATSD_H diff --git a/src/web_api_old.c b/src/web_api_old.c deleted file mode 100644 index 373e7e9f..00000000 --- a/src/web_api_old.c +++ /dev/null @@ -1,237 +0,0 @@ -#include "common.h" - -int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type) { - if(!url || !*url) { - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Incomplete request."); - return 400; - } - - RRDSET *st = NULL; - - char *args = strchr(url, '?'); - if(args) { - *args='\0'; - args = &args[1]; - } - - // get the name of the data to show - char *tok = mystrsep(&url, "/"); - if(!tok) tok = ""; - - // do we have such a data set? - if(*tok) { - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); - st = rrdset_find_byname(host, tok); - if(!st) st = rrdset_find(host, tok); - } - - if(!st) { - // we don't have it - // try to send a file with that name - buffer_flush(w->response.data); - return(mysendfile(w, tok)); - } - - // we have it - debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok); - - // how many entries does the client want? - int lines = (int)st->entries; - int group_count = 1; - time_t after = 0, before = 0; - int group_method = GROUP_AVERAGE; - int nonzero = 0; - - if(url) { - // parse the lines required - tok = mystrsep(&url, "/"); - if(tok) lines = str2i(tok); - if(lines < 1) lines = 1; - } - if(url) { - // parse the group count required - tok = mystrsep(&url, "/"); - if(tok && *tok) group_count = str2i(tok); - if(group_count < 1) group_count = 1; - //if(group_count > save_history / 20) group_count = save_history / 20; - } - if(url) { - // parse the grouping method required - tok = mystrsep(&url, "/"); - if(tok && *tok) { - if(strcmp(tok, "max") == 0) group_method = GROUP_MAX; - else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE; - else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM; - else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok); - } - } - if(url) { - // parse after time - tok = mystrsep(&url, "/"); - if(tok && *tok) after = str2ul(tok); - if(after < 0) after = 0; - } - if(url) { - // parse before time - tok = mystrsep(&url, "/"); - if(tok && *tok) before = str2ul(tok); - if(before < 0) before = 0; - } - if(url) { - // parse nonzero - tok = mystrsep(&url, "/"); - if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1; - } - - w->response.data->contenttype = CT_APPLICATION_JSON; - buffer_flush(w->response.data); - - char *google_version = "0.6"; - char *google_reqId = "0"; - char *google_sig = "0"; - char *google_out = "json"; - char *google_responseHandler = "google.visualization.Query.setResponse"; - char *google_outFileName = NULL; - time_t last_timestamp_in_data = 0; - if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) { - - w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT; - - while(args) { - tok = mystrsep(&args, "&"); - if(tok && *tok) { - char *name = mystrsep(&tok, "="); - if(name && *name && strcmp(name, "tqx") == 0) { - char *key = mystrsep(&tok, ":"); - char *value = mystrsep(&tok, ";"); - if(key && value && *key && *value) { - if(strcmp(key, "version") == 0) - google_version = value; - - else if(strcmp(key, "reqId") == 0) - google_reqId = value; - - else if(strcmp(key, "sig") == 0) - google_sig = value; - - else if(strcmp(key, "out") == 0) - google_out = value; - - else if(strcmp(key, "responseHandler") == 0) - google_responseHandler = value; - - else if(strcmp(key, "outFileName") == 0) - google_outFileName = value; - } - } - } - } - - debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'", - w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName - ); - - if(datasource_type == DATASOURCE_DATATABLE_JSONP) { - last_timestamp_in_data = strtoul(google_sig, NULL, 0); - - // check the client wants json - if(strcmp(google_out, "json") != 0) { - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});", - google_responseHandler, google_version, google_reqId, google_out); - return 200; - } - } - } - - if(datasource_type == DATASOURCE_DATATABLE_JSONP) { - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:", - google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec); - } - - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).", - w->id, st->name, st->id, lines, group_count, group_method, after, before); - - time_t timestamp_in_data = rrdset2json_api_old(datasource_type, st, w->response.data, lines, group_count - , group_method, (unsigned long) after, (unsigned long) before - , nonzero); - - if(datasource_type == DATASOURCE_DATATABLE_JSONP) { - if(timestamp_in_data > last_timestamp_in_data) - buffer_strcat(w->response.data, "});"); - - else { - // the client already has the latest data - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});", - google_responseHandler, google_version, google_reqId); - } - } - - return 200; -} - -inline int web_client_api_old_data_request_json(RRDHOST *host, struct web_client *w, char *url) { - return web_client_api_old_data_request(host, w, url, DATASOURCE_JSON); -} - -inline int web_client_api_old_data_request_jsonp(RRDHOST *host, struct web_client *w, char *url) { - return web_client_api_old_data_request(host, w, url, DATASOURCE_DATATABLE_JSONP); -} - -inline int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url) { - // get the name of the data to show - char *tok = mystrsep(&url, "/?&"); - if(tok && *tok) { - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); - - // do we have such a data set? - RRDSET *st = rrdset_find_byname(host, tok); - if(!st) st = rrdset_find(host, tok); - if(!st) { - // we don't have it - // try to send a file with that name - buffer_flush(w->response.data); - return mysendfile(w, tok); - } - st->last_accessed_time = now_realtime_sec(); - - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name); - w->response.data->contenttype = CT_APPLICATION_JSON; - buffer_flush(w->response.data); - rrd_graph2json_api_old(st, url, w->response.data); - return 200; - } - - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Graph name?\r\n"); - return 400; -} - -inline int web_client_api_old_list_request(RRDHOST *host, struct web_client *w, char *url) { - (void)url; - - buffer_flush(w->response.data); - RRDSET *st; - - rrdhost_rdlock(host); - rrdset_foreach_read(st, host) { - if(rrdset_is_available_for_viewers(st)) - buffer_sprintf(w->response.data, "%s\n", st->name); - } - rrdhost_unlock(host); - - return 200; -} - -inline int web_client_api_old_all_json(RRDHOST *host, struct web_client *w, char *url) { - (void)url; - - w->response.data->contenttype = CT_APPLICATION_JSON; - buffer_flush(w->response.data); - rrd_all2json_api_old(host, w->response.data); - return 200; -} diff --git a/src/web_api_old.h b/src/web_api_old.h deleted file mode 100644 index dff48c2f..00000000 --- a/src/web_api_old.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NETDATA_WEB_API_OLD_H -#define NETDATA_WEB_API_OLD_H - -#include "common.h" - -extern int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type); -extern int web_client_api_old_data_request_json(RRDHOST *host, struct web_client *w, char *url); -extern int web_client_api_old_data_request_jsonp(RRDHOST *host, struct web_client *w, char *url); -extern int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url); -extern int web_client_api_old_list_request(RRDHOST *host, struct web_client *w, char *url); -extern int web_client_api_old_all_json(RRDHOST *host, struct web_client *w, char *url); - -#endif //NETDATA_WEB_API_OLD_H diff --git a/src/web_server.c b/src/web_server.c deleted file mode 100644 index 31c54641..00000000 --- a/src/web_server.c +++ /dev/null @@ -1,1292 +0,0 @@ -#include "common.h" - -// this file includes 3 web servers: -// -// 1. single-threaded, based on select() -// 2. multi-threaded, based on poll() that spawns threads to handle the requests, based on select() -// 3. static-threaded, based on poll() using a fixed number of threads (configured at netdata.conf) - -WEB_SERVER_MODE web_server_mode = WEB_SERVER_MODE_STATIC_THREADED; - -// -------------------------------------------------------------------------------------- - -WEB_SERVER_MODE web_server_mode_id(const char *mode) { - if(!strcmp(mode, "none")) - return WEB_SERVER_MODE_NONE; - else if(!strcmp(mode, "single") || !strcmp(mode, "single-threaded")) - return WEB_SERVER_MODE_SINGLE_THREADED; - else if(!strcmp(mode, "static") || !strcmp(mode, "static-threaded")) - return WEB_SERVER_MODE_STATIC_THREADED; - else // if(!strcmp(mode, "multi") || !strcmp(mode, "multi-threaded")) - return WEB_SERVER_MODE_MULTI_THREADED; -} - -const char *web_server_mode_name(WEB_SERVER_MODE id) { - switch(id) { - case WEB_SERVER_MODE_NONE: - return "none"; - - case WEB_SERVER_MODE_SINGLE_THREADED: - return "single-threaded"; - - case WEB_SERVER_MODE_STATIC_THREADED: - return "static-threaded"; - - default: - case WEB_SERVER_MODE_MULTI_THREADED: - return "multi-threaded"; - } -} - -// -------------------------------------------------------------------------------------- -// API sockets - -static LISTEN_SOCKETS api_sockets = { - .config_section = CONFIG_SECTION_WEB, - .default_bind_to = "*", - .default_port = API_LISTEN_PORT, - .backlog = API_LISTEN_BACKLOG -}; - -int api_listen_sockets_setup(void) { - int socks = listen_sockets_setup(&api_sockets); - - if(!socks) - fatal("LISTENER: Cannot listen on any API socket. Exiting..."); - - return socks; -} - - -// -------------------------------------------------------------------------------------- -// access lists - -SIMPLE_PATTERN *web_allow_connections_from = NULL; -SIMPLE_PATTERN *web_allow_streaming_from = NULL; -SIMPLE_PATTERN *web_allow_netdataconf_from = NULL; - -// WEB_CLIENT_ACL -SIMPLE_PATTERN *web_allow_dashboard_from = NULL; -SIMPLE_PATTERN *web_allow_registry_from = NULL; -SIMPLE_PATTERN *web_allow_badges_from = NULL; - -static void web_client_update_acl_matches(struct web_client *w) { - w->acl = WEB_CLIENT_ACL_NONE; - - if(!web_allow_dashboard_from || simple_pattern_matches(web_allow_dashboard_from, w->client_ip)) - w->acl |= WEB_CLIENT_ACL_DASHBOARD; - - if(!web_allow_registry_from || simple_pattern_matches(web_allow_registry_from, w->client_ip)) - w->acl |= WEB_CLIENT_ACL_REGISTRY; - - if(!web_allow_badges_from || simple_pattern_matches(web_allow_badges_from, w->client_ip)) - w->acl |= WEB_CLIENT_ACL_BADGE; -} - - -// -------------------------------------------------------------------------------------- - -static void log_connection(struct web_client *w, const char *msg) { - log_access("%llu: %d '[%s]:%s' '%s'", w->id, gettid(), w->client_ip, w->client_port, msg); -} - -// ---------------------------------------------------------------------------- -// allocate and free web_clients - -static void web_client_zero(struct web_client *w) { - // zero everything about it - but keep the buffers - - // remember the pointers to the buffers - BUFFER *b1 = w->response.data; - BUFFER *b2 = w->response.header; - BUFFER *b3 = w->response.header_output; - - // empty the buffers - buffer_flush(b1); - buffer_flush(b2); - buffer_flush(b3); - - freez(w->user_agent); - - // zero everything - memset(w, 0, sizeof(struct web_client)); - - // restore the pointers of the buffers - w->response.data = b1; - w->response.header = b2; - w->response.header_output = b3; -} - -static void web_client_free(struct web_client *w) { - buffer_free(w->response.header_output); - buffer_free(w->response.header); - buffer_free(w->response.data); - freez(w->user_agent); - freez(w); -} - -static struct web_client *web_client_alloc(void) { - struct web_client *w = callocz(1, sizeof(struct web_client)); - w->response.data = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE); - w->response.header = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE); - w->response.header_output = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE); - return w; -} - -// ---------------------------------------------------------------------------- -// web clients caching - -// When clients connect and disconnect, avoid allocating and releasing memory. -// Instead, when new clients get connected, reuse any memory previously allocated -// for serving web clients that are now disconnected. - -// The size of the cache is adaptive. It caches the structures of 2x -// the number of currently connected clients. - -// Comments per server: -// SINGLE-THREADED : 1 cache is maintained -// MULTI-THREADED : 1 cache is maintained -// STATIC-THREADED : 1 cache for each thred of the web server - -struct clients_cache { - pid_t pid; - - struct web_client *used; // the structures of the currently connected clients - size_t used_count; // the count the currently connected clients - - struct web_client *avail; // the cached structures, available for future clients - size_t avail_count; // the number of cached structures - - size_t reused; // the number of re-uses - size_t allocated; // the number of allocations -}; - -static __thread struct clients_cache web_clients_cache = { - .pid = 0, - .used = NULL, - .used_count = 0, - .avail = NULL, - .avail_count = 0, - .allocated = 0, - .reused = 0 -}; - -static inline void web_client_cache_verify(int force) { -#ifdef NETDATA_INTERNAL_CHECKS - static __thread size_t count = 0; - count++; - - if(unlikely(force || count > 1000)) { - count = 0; - - struct web_client *w; - size_t used = 0, avail = 0; - for(w = web_clients_cache.used; w ; w = w->next) used++; - for(w = web_clients_cache.avail; w ; w = w->next) avail++; - - info("web_client_cache has %zu (%zu) used and %zu (%zu) available clients, allocated %zu, reused %zu (hit %zu%%)." - , used, web_clients_cache.used_count - , avail, web_clients_cache.avail_count - , web_clients_cache.allocated - , web_clients_cache.reused - , (web_clients_cache.allocated + web_clients_cache.reused)?(web_clients_cache.reused * 100 / (web_clients_cache.allocated + web_clients_cache.reused)):0 - ); - } -#else - if(unlikely(force)) { - info("web_client_cache has %zu used and %zu available clients, allocated %zu, reused %zu (hit %zu%%)." - , web_clients_cache.used_count - , web_clients_cache.avail_count - , web_clients_cache.allocated - , web_clients_cache.reused - , (web_clients_cache.allocated + web_clients_cache.reused)?(web_clients_cache.reused * 100 / (web_clients_cache.allocated + web_clients_cache.reused)):0 - ); - } -#endif -} - -// destroy the cache and free all the memory it uses -static void web_client_cache_destroy(void) { -#ifdef NETDATA_INTERNAL_CHECKS - if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid())) - error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid()); - - web_client_cache_verify(1); -#endif - - netdata_thread_disable_cancelability(); - - struct web_client *w, *t; - - w = web_clients_cache.used; - while(w) { - t = w; - w = w->next; - web_client_free(t); - } - web_clients_cache.used = NULL; - web_clients_cache.used_count = 0; - - w = web_clients_cache.avail; - while(w) { - t = w; - w = w->next; - web_client_free(t); - } - web_clients_cache.avail = NULL; - web_clients_cache.avail_count = 0; - - netdata_thread_enable_cancelability(); -} - -static struct web_client *web_client_get_from_cache_or_allocate() { - -#ifdef NETDATA_INTERNAL_CHECKS - if(unlikely(web_clients_cache.pid == 0)) - web_clients_cache.pid = gettid(); - - if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid())) - error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid()); -#endif - - netdata_thread_disable_cancelability(); - - struct web_client *w = web_clients_cache.avail; - - if(w) { - // get it from avail - if (w == web_clients_cache.avail) web_clients_cache.avail = w->next; - if(w->prev) w->prev->next = w->next; - if(w->next) w->next->prev = w->prev; - web_clients_cache.avail_count--; - web_client_zero(w); - web_clients_cache.reused++; - } - else { - // allocate it - w = web_client_alloc(); - web_clients_cache.allocated++; - } - - // link it to used web clients - if (web_clients_cache.used) web_clients_cache.used->prev = w; - w->next = web_clients_cache.used; - w->prev = NULL; - web_clients_cache.used = w; - web_clients_cache.used_count++; - - // initialize it - w->id = web_client_connected(); - w->mode = WEB_CLIENT_MODE_NORMAL; - - netdata_thread_enable_cancelability(); - - return w; -} - -static void web_client_release(struct web_client *w) { -#ifdef NETDATA_INTERNAL_CHECKS - if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid())) - error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid()); - - if(unlikely(w->running)) - error("%llu: releasing web client from %s port %s, but it still running.", w->id, w->client_ip, w->client_port); -#endif - - debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port); - - log_connection(w, "DISCONNECTED"); - web_client_request_done(w); - web_client_disconnected(); - - netdata_thread_disable_cancelability(); - - if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) { - if (w->ifd != -1) close(w->ifd); - if (w->ofd != -1 && w->ofd != w->ifd) close(w->ofd); - w->ifd = w->ofd = -1; - } - - // unlink it from the used - if (w == web_clients_cache.used) web_clients_cache.used = w->next; - if(w->prev) w->prev->next = w->next; - if(w->next) w->next->prev = w->prev; - web_clients_cache.used_count--; - - if(web_clients_cache.avail_count >= 2 * web_clients_cache.used_count) { - // we have too many of them - free it - web_client_free(w); - } - else { - // link it to the avail - if (web_clients_cache.avail) web_clients_cache.avail->prev = w; - w->next = web_clients_cache.avail; - w->prev = NULL; - web_clients_cache.avail = w; - web_clients_cache.avail_count++; - } - - netdata_thread_enable_cancelability(); -} - - -// ---------------------------------------------------------------------------- -// high level web clients connection management - -static void web_client_initialize_connection(struct web_client *w) { - int flag = 1; - if(setsockopt(w->ifd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0) - error("%llu: failed to enable TCP_NODELAY on socket fd %d.", w->id, w->ifd); - - flag = 1; - if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0) - error("%llu: failed to enable SO_KEEPALIVE on socket fd %d.", w->id, w->ifd); - - web_client_update_acl_matches(w); - - w->origin[0] = '*'; w->origin[1] = '\0'; - w->cookie1[0] = '\0'; w->cookie2[0] = '\0'; - freez(w->user_agent); w->user_agent = NULL; - - web_client_enable_wait_receive(w); - - log_connection(w, "CONNECTED"); - - web_client_cache_verify(0); -} - -static struct web_client *web_client_create_on_fd(int fd, const char *client_ip, const char *client_port) { - struct web_client *w; - - w = web_client_get_from_cache_or_allocate(); - w->ifd = w->ofd = fd; - - strncpyz(w->client_ip, client_ip, sizeof(w->client_ip) - 1); - strncpyz(w->client_port, client_port, sizeof(w->client_port) - 1); - - if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-"); - if(unlikely(!*w->client_port)) strcpy(w->client_port, "-"); - - web_client_initialize_connection(w); - return(w); -} - -static struct web_client *web_client_create_on_listenfd(int listener) { - struct web_client *w; - - w = web_client_get_from_cache_or_allocate(); - w->ifd = w->ofd = accept_socket(listener, SOCK_NONBLOCK, w->client_ip, sizeof(w->client_ip), w->client_port, sizeof(w->client_port), web_allow_connections_from); - - if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-"); - if(unlikely(!*w->client_port)) strcpy(w->client_port, "-"); - - if (w->ifd == -1) { - if(errno == EPERM) - log_connection(w, "ACCESS DENIED"); - else { - log_connection(w, "CONNECTION FAILED"); - error("%llu: Failed to accept new incoming connection.", w->id); - } - - web_client_release(w); - return NULL; - } - - web_client_initialize_connection(w); - return(w); -} - - -// -------------------------------------------------------------------------------------- -// the thread of a single client - for the MULTI-THREADED web server - -// 1. waits for input and output, using async I/O -// 2. it processes HTTP requests -// 3. it generates HTTP responses -// 4. it copies data from input to output if mode is FILECOPY - -int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS; -int web_client_first_request_timeout = DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST; - -static void multi_threaded_web_client_worker_main_cleanup(void *ptr) { - struct web_client *w = ptr; - WEB_CLIENT_IS_DEAD(w); - w->running = 0; -} - -static void *multi_threaded_web_client_worker_main(void *ptr) { - netdata_thread_cleanup_push(multi_threaded_web_client_worker_main_cleanup, ptr); - - struct web_client *w = ptr; - w->running = 1; - - struct pollfd fds[2], *ifd, *ofd; - int retval, timeout_ms; - nfds_t fdmax = 0; - - while(!netdata_exit) { - if(unlikely(web_client_check_dead(w))) { - debug(D_WEB_CLIENT, "%llu: client is dead.", w->id); - break; - } - else if(unlikely(!web_client_has_wait_receive(w) && !web_client_has_wait_send(w))) { - debug(D_WEB_CLIENT, "%llu: client is not set for neither receiving nor sending data.", w->id); - break; - } - - if(unlikely(w->ifd < 0 || w->ofd < 0)) { - error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd", w->id, w->ifd, w->ofd); - break; - } - - if(w->ifd == w->ofd) { - fds[0].fd = w->ifd; - fds[0].events = 0; - fds[0].revents = 0; - - if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN; - if(web_client_has_wait_send(w)) fds[0].events |= POLLOUT; - - fds[1].fd = -1; - fds[1].events = 0; - fds[1].revents = 0; - - ifd = ofd = &fds[0]; - - fdmax = 1; - } - else { - fds[0].fd = w->ifd; - fds[0].events = 0; - fds[0].revents = 0; - if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN; - ifd = &fds[0]; - - fds[1].fd = w->ofd; - fds[1].events = 0; - fds[1].revents = 0; - if(web_client_has_wait_send(w)) fds[1].events |= POLLOUT; - ofd = &fds[1]; - - fdmax = 2; - } - - debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, web_client_has_wait_receive(w)?"INPUT":"", web_client_has_wait_send(w)?"OUTPUT":""); - errno = 0; - timeout_ms = web_client_timeout * 1000; - retval = poll(fds, fdmax, timeout_ms); - - if(unlikely(netdata_exit)) break; - - if(unlikely(retval == -1)) { - if(errno == EAGAIN || errno == EINTR) { - debug(D_WEB_CLIENT, "%llu: EAGAIN received.", w->id); - continue; - } - - debug(D_WEB_CLIENT, "%llu: LISTENER: poll() failed (input fd = %d, output fd = %d). Closing client.", w->id, w->ifd, w->ofd); - break; - } - else if(unlikely(!retval)) { - debug(D_WEB_CLIENT, "%llu: Timeout while waiting socket async I/O for %s %s", w->id, web_client_has_wait_receive(w)?"INPUT":"", web_client_has_wait_send(w)?"OUTPUT":""); - break; - } - - if(unlikely(netdata_exit)) break; - - int used = 0; - if(web_client_has_wait_send(w) && ofd->revents & POLLOUT) { - used++; - if(web_client_send(w) < 0) { - debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id); - break; - } - } - - if(unlikely(netdata_exit)) break; - - if(web_client_has_wait_receive(w) && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) { - used++; - if(web_client_receive(w) < 0) { - debug(D_WEB_CLIENT, "%llu: Cannot receive data from client. Closing client.", w->id); - break; - } - - if(w->mode == WEB_CLIENT_MODE_NORMAL) { - debug(D_WEB_CLIENT, "%llu: Attempting to process received data.", w->id); - web_client_process_request(w); - - // if the sockets are closed, may have transferred this client - // to plugins.d - if(unlikely(w->mode == WEB_CLIENT_MODE_STREAM)) - break; - } - } - - if(unlikely(!used)) { - debug(D_WEB_CLIENT_ACCESS, "%llu: Received error on socket.", w->id); - break; - } - } - - if(w->mode != WEB_CLIENT_MODE_STREAM) - log_connection(w, "DISCONNECTED"); - - web_client_request_done(w); - - debug(D_WEB_CLIENT, "%llu: done...", w->id); - - // close the sockets/files now - // to free file descriptors - if(w->ifd == w->ofd) { - if(w->ifd != -1) close(w->ifd); - } - else { - if(w->ifd != -1) close(w->ifd); - if(w->ofd != -1) close(w->ofd); - } - w->ifd = -1; - w->ofd = -1; - - netdata_thread_cleanup_pop(1); - return NULL; -} - -// -------------------------------------------------------------------------------------- -// the main socket listener - MULTI-THREADED - -// 1. it accepts new incoming requests on our port -// 2. creates a new web_client for each connection received -// 3. spawns a new netdata_thread to serve the client (this is optimal for keep-alive clients) -// 4. cleans up old web_clients that their netdata_threads have been exited - -static void web_client_multi_threaded_web_server_release_clients(void) { - struct web_client *w; - for(w = web_clients_cache.used; w ; ) { - if(unlikely(!w->running && web_client_check_dead(w))) { - struct web_client *t = w->next; - web_client_release(w); - w = t; - } - else - w = w->next; - } -} - -static void web_client_multi_threaded_web_server_stop_all_threads(void) { - struct web_client *w; - - int found = 1, max = 2 * USEC_PER_SEC, step = 50000; - for(w = web_clients_cache.used; w ; w = w->next) { - if(w->running) { - found++; - info("stopping web client %s, id %llu", w->client_ip, w->id); - netdata_thread_cancel(w->thread); - } - } - - while(found && max > 0) { - max -= step; - info("Waiting %d web threads to finish...", found); - sleep_usec(step); - found = 0; - for(w = web_clients_cache.used; w ; w = w->next) - if(w->running) found++; - } - - if(found) - error("%d web threads are taking too long to finish. Giving up.", found); -} - -static struct pollfd *socket_listen_main_multi_threaded_fds = NULL; - -static void socket_listen_main_multi_threaded_cleanup(void *data) { - struct netdata_static_thread *static_thread = (struct netdata_static_thread *)data; - static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; - - info("cleaning up..."); - - info("releasing allocated memory..."); - freez(socket_listen_main_multi_threaded_fds); - - info("closing all sockets..."); - listen_sockets_close(&api_sockets); - - info("stopping all running web server threads..."); - web_client_multi_threaded_web_server_stop_all_threads(); - - info("freeing web clients cache..."); - web_client_cache_destroy(); - - info("cleanup completed."); - static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; -} - -#define CLEANUP_EVERY_EVENTS 60 -void *socket_listen_main_multi_threaded(void *ptr) { - netdata_thread_cleanup_push(socket_listen_main_multi_threaded_cleanup, ptr); - - web_server_mode = WEB_SERVER_MODE_MULTI_THREADED; - web_server_is_multithreaded = 1; - - struct web_client *w; - int retval, counter = 0; - - if(!api_sockets.opened) - fatal("LISTENER: No sockets to listen to."); - - socket_listen_main_multi_threaded_fds = callocz(sizeof(struct pollfd), api_sockets.opened); - - size_t i; - for(i = 0; i < api_sockets.opened ;i++) { - socket_listen_main_multi_threaded_fds[i].fd = api_sockets.fds[i]; - socket_listen_main_multi_threaded_fds[i].events = POLLIN; - socket_listen_main_multi_threaded_fds[i].revents = 0; - - info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN"); - } - - int timeout_ms = 1 * 1000; - - while(!netdata_exit) { - - // debug(D_WEB_CLIENT, "LISTENER: Waiting..."); - retval = poll(socket_listen_main_multi_threaded_fds, api_sockets.opened, timeout_ms); - - if(unlikely(retval == -1)) { - error("LISTENER: poll() failed."); - continue; - } - else if(unlikely(!retval)) { - debug(D_WEB_CLIENT, "LISTENER: poll() timeout."); - counter++; - continue; - } - - for(i = 0 ; i < api_sockets.opened ; i++) { - short int revents = socket_listen_main_multi_threaded_fds[i].revents; - - // check for new incoming connections - if(revents & POLLIN || revents & POLLPRI) { - socket_listen_main_multi_threaded_fds[i].revents = 0; - - w = web_client_create_on_listenfd(socket_listen_main_multi_threaded_fds[i].fd); - if(unlikely(!w)) { - // no need for error log - web_client_create_on_listenfd already logged the error - continue; - } - - if(api_sockets.fds_families[i] == AF_UNIX) - web_client_set_unix(w); - else - web_client_set_tcp(w); - - char tag[NETDATA_THREAD_TAG_MAX + 1]; - snprintfz(tag, NETDATA_THREAD_TAG_MAX, "WEB_CLIENT[%llu,[%s]:%s]", w->id, w->client_ip, w->client_port); - - w->running = 1; - if(netdata_thread_create(&w->thread, tag, NETDATA_THREAD_OPTION_DONT_LOG, multi_threaded_web_client_worker_main, w) != 0) { - w->running = 0; - web_client_release(w); - } - } - } - - counter++; - if(counter > CLEANUP_EVERY_EVENTS) { - counter = 0; - web_client_multi_threaded_web_server_release_clients(); - } - } - - netdata_thread_cleanup_pop(1); - return NULL; -} - - -// -------------------------------------------------------------------------------------- -// the main socket listener - SINGLE-THREADED - -struct web_client *single_threaded_clients[FD_SETSIZE]; - -static inline int single_threaded_link_client(struct web_client *w, fd_set *ifds, fd_set *ofds, fd_set *efds, int *max) { - if(unlikely(web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w)))) { - return 1; - } - - if(unlikely(w->ifd < 0 || w->ifd >= (int)FD_SETSIZE || w->ofd < 0 || w->ofd >= (int)FD_SETSIZE)) { - error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd < FD_SETSIZE (%d)", w->id, w->ifd, w->ofd, (int)FD_SETSIZE); - return 1; - } - - FD_SET(w->ifd, efds); - if(unlikely(*max < w->ifd)) *max = w->ifd; - - if(unlikely(w->ifd != w->ofd)) { - if(*max < w->ofd) *max = w->ofd; - FD_SET(w->ofd, efds); - } - - if(web_client_has_wait_receive(w)) FD_SET(w->ifd, ifds); - if(web_client_has_wait_send(w)) FD_SET(w->ofd, ofds); - - single_threaded_clients[w->ifd] = w; - single_threaded_clients[w->ofd] = w; - - return 0; -} - -static inline int single_threaded_unlink_client(struct web_client *w, fd_set *ifds, fd_set *ofds, fd_set *efds) { - FD_CLR(w->ifd, efds); - if(unlikely(w->ifd != w->ofd)) FD_CLR(w->ofd, efds); - - if(web_client_has_wait_receive(w)) FD_CLR(w->ifd, ifds); - if(web_client_has_wait_send(w)) FD_CLR(w->ofd, ofds); - - single_threaded_clients[w->ifd] = NULL; - single_threaded_clients[w->ofd] = NULL; - - if(unlikely(web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w)))) { - return 1; - } - - return 0; -} - -static void socket_listen_main_single_threaded_cleanup(void *data) { - struct netdata_static_thread *static_thread = (struct netdata_static_thread *)data; - static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; - - info("closing all sockets..."); - listen_sockets_close(&api_sockets); - - info("freeing web clients cache..."); - web_client_cache_destroy(); - - info("cleanup completed."); - static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; -} - -void *socket_listen_main_single_threaded(void *ptr) { - netdata_thread_cleanup_push(socket_listen_main_single_threaded_cleanup, ptr); - web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED; - web_server_is_multithreaded = 0; - - struct web_client *w; - - if(!api_sockets.opened) - fatal("LISTENER: no listen sockets available."); - - size_t i; - for(i = 0; i < (size_t)FD_SETSIZE ; i++) - single_threaded_clients[i] = NULL; - - fd_set ifds, ofds, efds, rifds, rofds, refds; - FD_ZERO (&ifds); - FD_ZERO (&ofds); - FD_ZERO (&efds); - int fdmax = 0; - - for(i = 0; i < api_sockets.opened ; i++) { - if (api_sockets.fds[i] < 0 || api_sockets.fds[i] >= (int)FD_SETSIZE) - fatal("LISTENER: Listen socket %d is not ready, or invalid.", api_sockets.fds[i]); - - info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN"); - - FD_SET(api_sockets.fds[i], &ifds); - FD_SET(api_sockets.fds[i], &efds); - if(fdmax < api_sockets.fds[i]) - fdmax = api_sockets.fds[i]; - } - - while(!netdata_exit) { - debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server waiting (fdmax = %d)...", fdmax); - - struct timeval tv = { .tv_sec = 1, .tv_usec = 0 }; - rifds = ifds; - rofds = ofds; - refds = efds; - int retval = select(fdmax+1, &rifds, &rofds, &refds, &tv); - - if(unlikely(retval == -1)) { - error("LISTENER: select() failed."); - continue; - } - else if(likely(retval)) { - debug(D_WEB_CLIENT_ACCESS, "LISTENER: got something."); - - for(i = 0; i < api_sockets.opened ; i++) { - if (FD_ISSET(api_sockets.fds[i], &rifds)) { - debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection."); - w = web_client_create_on_listenfd(api_sockets.fds[i]); - if(unlikely(!w)) - continue; - - if(api_sockets.fds_families[i] == AF_UNIX) - web_client_set_unix(w); - else - web_client_set_tcp(w); - - if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) { - web_client_release(w); - } - } - } - - for(i = 0 ; i <= (size_t)fdmax ; i++) { - if(likely(!FD_ISSET(i, &rifds) && !FD_ISSET(i, &rofds) && !FD_ISSET(i, &refds))) - continue; - - w = single_threaded_clients[i]; - if(unlikely(!w)) { - // error("no client on slot %zu", i); - continue; - } - - if(unlikely(single_threaded_unlink_client(w, &ifds, &ofds, &efds) != 0)) { - // error("failed to unlink client %zu", i); - web_client_release(w); - continue; - } - - if (unlikely(FD_ISSET(w->ifd, &refds) || FD_ISSET(w->ofd, &refds))) { - // error("no input on client %zu", i); - web_client_release(w); - continue; - } - - if (unlikely(web_client_has_wait_receive(w) && FD_ISSET(w->ifd, &rifds))) { - if (unlikely(web_client_receive(w) < 0)) { - // error("cannot read from client %zu", i); - web_client_release(w); - continue; - } - - if (w->mode != WEB_CLIENT_MODE_FILECOPY) { - debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id); - web_client_process_request(w); - } - } - - if (unlikely(web_client_has_wait_send(w) && FD_ISSET(w->ofd, &rofds))) { - if (unlikely(web_client_send(w) < 0)) { - // error("cannot send data to client %zu", i); - debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id); - web_client_release(w); - continue; - } - } - - if(unlikely(single_threaded_link_client(w, &ifds, &ofds, &efds, &fdmax) != 0)) { - // error("failed to link client %zu", i); - web_client_release(w); - } - } - } - else { - debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server timeout."); - } - } - - netdata_thread_cleanup_pop(1); - return NULL; -} - - -// -------------------------------------------------------------------------------------- -// the main socket listener - STATIC-THREADED - -struct web_server_static_threaded_worker { - netdata_thread_t thread; - - int id; - int running; - - size_t max_sockets; - - volatile size_t connected; - volatile size_t disconnected; - volatile size_t receptions; - volatile size_t sends; - volatile size_t max_concurrent; - - volatile size_t files_read; - volatile size_t file_reads; -}; - -static long long static_threaded_workers_count = 1; -static struct web_server_static_threaded_worker *static_workers_private_data = NULL; -static __thread struct web_server_static_threaded_worker *worker_private = NULL; - -// ---------------------------------------------------------------------------- - -static inline int web_server_check_client_status(struct web_client *w) { - if(unlikely(web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w)))) - return -1; - - return 0; -} - -// ---------------------------------------------------------------------------- -// web server files - -static void *web_server_file_add_callback(POLLINFO *pi, short int *events, void *data) { - struct web_client *w = (struct web_client *)data; - - worker_private->files_read++; - - debug(D_WEB_CLIENT, "%llu: ADDED FILE READ ON FD %d", w->id, pi->fd); - *events = POLLIN; - pi->data = w; - return w; -} - -static void web_werver_file_del_callback(POLLINFO *pi) { - struct web_client *w = (struct web_client *)pi->data; - debug(D_WEB_CLIENT, "%llu: RELEASE FILE READ ON FD %d", w->id, pi->fd); - - w->pollinfo_filecopy_slot = 0; - - if(unlikely(!w->pollinfo_slot)) { - debug(D_WEB_CLIENT, "%llu: CROSS WEB CLIENT CLEANUP (iFD %d, oFD %d)", w->id, pi->fd, w->ofd); - web_client_release(w); - } -} - -static int web_server_file_read_callback(POLLINFO *pi, short int *events) { - struct web_client *w = (struct web_client *)pi->data; - - // if there is no POLLINFO linked to this, it means the client disconnected - // stop the file reading too - if(unlikely(!w->pollinfo_slot)) { - debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON CLOSED WEB CLIENT", w->id, pi->fd); - return -1; - } - - if(unlikely(w->mode != WEB_CLIENT_MODE_FILECOPY || w->ifd == w->ofd)) { - debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON NON-FILECOPY WEB CLIENT", w->id, pi->fd); - return -1; - } - - debug(D_WEB_CLIENT, "%llu: READING FILE ON FD %d", w->id, pi->fd); - - worker_private->file_reads++; - ssize_t ret = unlikely(web_client_read_file(w)); - - if(likely(web_client_has_wait_send(w))) { - POLLJOB *p = pi->p; // our POLLJOB - POLLINFO *wpi = pollinfo_from_slot(p, w->pollinfo_slot); // POLLINFO of the client socket - - debug(D_WEB_CLIENT, "%llu: SIGNALING W TO SEND (iFD %d, oFD %d)", w->id, pi->fd, wpi->fd); - p->fds[wpi->slot].events |= POLLOUT; - } - - if(unlikely(ret <= 0 || w->ifd == w->ofd)) { - debug(D_WEB_CLIENT, "%llu: DONE READING FILE ON FD %d", w->id, pi->fd); - return -1; - } - - *events = POLLIN; - return 0; -} - -static int web_server_file_write_callback(POLLINFO *pi, short int *events) { - (void)pi; - (void)events; - - error("Writing to web files is not supported!"); - - return -1; -} - -// ---------------------------------------------------------------------------- -// web server clients - -static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data) { - (void)data; - - worker_private->connected++; - - size_t concurrent = worker_private->connected - worker_private->disconnected; - if(unlikely(concurrent > worker_private->max_concurrent)) - worker_private->max_concurrent = concurrent; - - *events = POLLIN; - - debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", pi->fd); - struct web_client *w = web_client_create_on_fd(pi->fd, pi->client_ip, pi->client_port); - w->pollinfo_slot = pi->slot; - - if(unlikely(pi->socktype == AF_UNIX)) - web_client_set_unix(w); - else - web_client_set_tcp(w); - - debug(D_WEB_CLIENT, "%llu: ADDED CLIENT FD %d", w->id, pi->fd); - return w; -} - -// TCP client disconnected -static void web_server_del_callback(POLLINFO *pi) { - worker_private->disconnected++; - - struct web_client *w = (struct web_client *)pi->data; - - w->pollinfo_slot = 0; - if(unlikely(w->pollinfo_filecopy_slot)) { - POLLINFO *fpi = pollinfo_from_slot(pi->p, w->pollinfo_filecopy_slot); // POLLINFO of the client socket - debug(D_WEB_CLIENT, "%llu: THE CLIENT WILL BE FRED BY READING FILE JOB ON FD %d", w->id, fpi->fd); - } - else { - if(web_client_flag_check(w, WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET)) - pi->flags |= POLLINFO_FLAG_DONT_CLOSE; - - debug(D_WEB_CLIENT, "%llu: CLOSING CLIENT FD %d", w->id, pi->fd); - web_client_release(w); - } -} - -static int web_server_rcv_callback(POLLINFO *pi, short int *events) { - worker_private->receptions++; - - struct web_client *w = (struct web_client *)pi->data; - int fd = pi->fd; - - if(unlikely(web_client_receive(w) < 0)) - return -1; - - debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd); - web_client_process_request(w); - - if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) { - if(w->pollinfo_filecopy_slot == 0) { - debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd); - - if (unlikely(w->ifd != -1 && w->ifd != w->ofd && w->ifd != fd)) { - // add a new socket to poll_events, with the same - debug(D_WEB_CLIENT, "%llu: CREATING FILECOPY SLOT ON FD %d", w->id, pi->fd); - - POLLINFO *fpi = poll_add_fd( - pi->p - , w->ifd - , 0 - , POLLINFO_FLAG_CLIENT_SOCKET - , "FILENAME" - , "" - , web_server_file_add_callback - , web_werver_file_del_callback - , web_server_file_read_callback - , web_server_file_write_callback - , (void *) w - ); - - if(fpi) - w->pollinfo_filecopy_slot = fpi->slot; - else { - error("Failed to add filecopy fd. Closing client."); - return -1; - } - } - } - } - else { - if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) - *events |= POLLIN; - } - - if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) - *events |= POLLOUT; - - return web_server_check_client_status(w); -} - -static int web_server_snd_callback(POLLINFO *pi, short int *events) { - worker_private->sends++; - - struct web_client *w = (struct web_client *)pi->data; - int fd = pi->fd; - - debug(D_WEB_CLIENT, "%llu: sending data on fd %d.", w->id, fd); - - if(unlikely(web_client_send(w) < 0)) - return -1; - - if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) - *events |= POLLIN; - - if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) - *events |= POLLOUT; - - return web_server_check_client_status(w); -} - -static void web_server_tmr_callback(void *timer_data) { - worker_private = (struct web_server_static_threaded_worker *)timer_data; - - static __thread RRDSET *st = NULL; - static __thread RRDDIM *rd_user = NULL, *rd_system = NULL; - - if(unlikely(!st)) { - char id[100 + 1]; - char title[100 + 1]; - - snprintfz(id, 100, "web_thread%d_cpu", worker_private->id + 1); - snprintfz(title, 100, "NetData web server thread No %d CPU usage", worker_private->id + 1); - - st = rrdset_create_localhost( - "netdata" - , id - , NULL - , "web" - , "netdata.web_cpu" - , title - , "milliseconds/s" - , "web" - , "stats" - , 132000 + worker_private->id - , default_rrd_update_every - , RRDSET_TYPE_STACKED - ); - - rd_user = rrddim_add(st, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - rd_system = rrddim_add(st, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st); - - struct rusage rusage; - getrusage(RUSAGE_THREAD, &rusage); - rrddim_set_by_pointer(st, rd_user, rusage.ru_utime.tv_sec * 1000000ULL + rusage.ru_utime.tv_usec); - rrddim_set_by_pointer(st, rd_system, rusage.ru_stime.tv_sec * 1000000ULL + rusage.ru_stime.tv_usec); - rrdset_done(st); -} - -// ---------------------------------------------------------------------------- -// web server worker thread - -static void socket_listen_main_static_threaded_worker_cleanup(void *ptr) { - worker_private = (struct web_server_static_threaded_worker *)ptr; - - info("freeing local web clients cache..."); - web_client_cache_destroy(); - - info("stopped after %zu connects, %zu disconnects (max concurrent %zu), %zu receptions and %zu sends", - worker_private->connected, - worker_private->disconnected, - worker_private->max_concurrent, - worker_private->receptions, - worker_private->sends - ); - - worker_private->running = 0; -} - -void *socket_listen_main_static_threaded_worker(void *ptr) { - worker_private = (struct web_server_static_threaded_worker *)ptr; - worker_private->running = 1; - - netdata_thread_cleanup_push(socket_listen_main_static_threaded_worker_cleanup, ptr); - - poll_events(&api_sockets - , web_server_add_callback - , web_server_del_callback - , web_server_rcv_callback - , web_server_snd_callback - , web_server_tmr_callback - , web_allow_connections_from - , NULL - , web_client_first_request_timeout - , web_client_timeout - , default_rrd_update_every * 1000 // timer_milliseconds - , ptr // timer_data - , worker_private->max_sockets - ); - - netdata_thread_cleanup_pop(1); - return NULL; -} - - -// ---------------------------------------------------------------------------- -// web server main thread - also becomes a worker - -static void socket_listen_main_static_threaded_cleanup(void *ptr) { - struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; - static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; - - int i, found = 0, max = 2 * USEC_PER_SEC, step = 50000; - - // we start from 1, - 0 is self - for(i = 1; i < static_threaded_workers_count; i++) { - if(static_workers_private_data[i].running) { - found++; - info("stopping worker %d", i + 1); - netdata_thread_cancel(static_workers_private_data[i].thread); - } - else - info("found stopped worker %d", i + 1); - } - - while(found && max > 0) { - max -= step; - info("Waiting %d static web threads to finish...", found); - sleep_usec(step); - found = 0; - - // we start from 1, - 0 is self - for(i = 1; i < static_threaded_workers_count; i++) { - if (static_workers_private_data[i].running) - found++; - } - } - - if(found) - error("%d static web threads are taking too long to finish. Giving up.", found); - - info("closing all web server sockets..."); - listen_sockets_close(&api_sockets); - - info("all static web threads stopped."); - static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; -} - -void *socket_listen_main_static_threaded(void *ptr) { - netdata_thread_cleanup_push(socket_listen_main_static_threaded_cleanup, ptr); - web_server_mode = WEB_SERVER_MODE_STATIC_THREADED; - - if(!api_sockets.opened) - fatal("LISTENER: no listen sockets available."); - - // 6 threads is the optimal value - // since 6 are the parallel connections browsers will do - // so, if the machine has more CPUs, avoid using resources unnecessarily - int def_thread_count = (processors > 6)?6:processors; - - static_threaded_workers_count = config_get_number(CONFIG_SECTION_WEB, "web server threads", def_thread_count); - if(static_threaded_workers_count < 1) static_threaded_workers_count = 1; - - size_t max_sockets = (size_t)config_get_number(CONFIG_SECTION_WEB, "web server max sockets", (long long int)(rlimit_nofile.rlim_cur / 2)); - - static_workers_private_data = callocz((size_t)static_threaded_workers_count, sizeof(struct web_server_static_threaded_worker)); - - web_server_is_multithreaded = (static_threaded_workers_count > 1); - - int i; - for(i = 1; i < static_threaded_workers_count; i++) { - static_workers_private_data[i].id = i; - static_workers_private_data[i].max_sockets = max_sockets / static_threaded_workers_count; - - char tag[50 + 1]; - snprintfz(tag, 50, "WEB_SERVER[static%d]", i+1); - - info("starting worker %d", i+1); - netdata_thread_create(&static_workers_private_data[i].thread, tag, NETDATA_THREAD_OPTION_DEFAULT, socket_listen_main_static_threaded_worker, (void *)&static_workers_private_data[i]); - } - - // and the main one - static_workers_private_data[0].max_sockets = max_sockets / static_threaded_workers_count; - socket_listen_main_static_threaded_worker((void *)&static_workers_private_data[0]); - - netdata_thread_cleanup_pop(1); - return NULL; -} diff --git a/src/rrdpush.c b/streaming/rrdpush.c index 8f71c6d4..df1a2177 100644 --- a/src/rrdpush.c +++ b/streaming/rrdpush.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrdpush.h" /* * rrdpush @@ -30,14 +32,46 @@ typedef enum { RRDPUSH_MULTIPLE_CONNECTIONS_DENY_NEW } RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY; -int default_rrdpush_enabled = 0; +static struct config stream_config = { + .sections = NULL, + .mutex = NETDATA_MUTEX_INITIALIZER, + .index = { + .avl_tree = { + .root = NULL, + .compar = appconfig_section_compare + }, + .rwlock = AVL_LOCK_INITIALIZER + } +}; + +unsigned int default_rrdpush_enabled = 0; char *default_rrdpush_destination = NULL; char *default_rrdpush_api_key = NULL; +char *default_rrdpush_send_charts_matching = NULL; + +static void load_stream_conf() { + errno = 0; + char *filename = strdupz_path_subpath(netdata_configured_user_config_dir, "stream.conf"); + if(!appconfig_load(&stream_config, filename, 0)) { + info("CONFIG: cannot load user config '%s'. Will try stock config.", filename); + freez(filename); + + filename = strdupz_path_subpath(netdata_configured_stock_config_dir, "stream.conf"); + if(!appconfig_load(&stream_config, filename, 0)) + info("CONFIG: cannot load stock config '%s'. Running with internal defaults.", filename); + } + freez(filename); +} int rrdpush_init() { - default_rrdpush_enabled = appconfig_get_boolean(&stream_config, CONFIG_SECTION_STREAM, "enabled", default_rrdpush_enabled); + // -------------------------------------------------------------------- + // load stream.conf + load_stream_conf(); + + default_rrdpush_enabled = (unsigned int)appconfig_get_boolean(&stream_config, CONFIG_SECTION_STREAM, "enabled", default_rrdpush_enabled); default_rrdpush_destination = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "destination", ""); default_rrdpush_api_key = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "api key", ""); + default_rrdpush_send_charts_matching = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "send charts matching", "*"); rrdhost_free_orphan_time = config_get_number(CONFIG_SECTION_GLOBAL, "cleanup orphan hosts after seconds", rrdhost_free_orphan_time); if(default_rrdpush_enabled && (!default_rrdpush_destination || !*default_rrdpush_destination || !default_rrdpush_api_key || !*default_rrdpush_api_key)) { @@ -67,17 +101,44 @@ unsigned int remote_clock_resync_iterations = 60; #define rrdpush_buffer_lock(host) netdata_mutex_lock(&((host)->rrdpush_sender_buffer_mutex)) #define rrdpush_buffer_unlock(host) netdata_mutex_unlock(&((host)->rrdpush_sender_buffer_mutex)) +static inline int should_send_chart_matching(RRDSET *st) { + if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_ENABLED))) { + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_SEND); + rrdset_flag_set(st, RRDSET_FLAG_UPSTREAM_IGNORE); + } + else if(!rrdset_flag_check(st, RRDSET_FLAG_UPSTREAM_SEND|RRDSET_FLAG_UPSTREAM_IGNORE)) { + RRDHOST *host = st->rrdhost; + + if(simple_pattern_matches(host->rrdpush_send_charts_matching, st->id) || + simple_pattern_matches(host->rrdpush_send_charts_matching, st->name)) { + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_IGNORE); + rrdset_flag_set(st, RRDSET_FLAG_UPSTREAM_SEND); + } + else { + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_SEND); + rrdset_flag_set(st, RRDSET_FLAG_UPSTREAM_IGNORE); + } + } + + return(rrdset_flag_check(st, RRDSET_FLAG_UPSTREAM_SEND)); +} + // checks if the current chart definition has been sent static inline int need_to_send_chart_definition(RRDSET *st) { rrdset_check_rdlock(st); - if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_EXPOSED_UPSTREAM)))) + if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_UPSTREAM_EXPOSED)))) return 1; RRDDIM *rd; - rrddim_foreach_read(rd, st) - if(unlikely(!rd->exposed)) + rrddim_foreach_read(rd, st) { + if(unlikely(!rd->exposed)) { + #ifdef NETDATA_INTERNAL_CHECKS + info("host '%s', chart '%s', dimension '%s' flag 'exposed' triggered chart refresh to upstream", st->rrdhost->hostname, st->id, rd->id); + #endif return 1; + } + } return 0; } @@ -86,14 +147,27 @@ static inline int need_to_send_chart_definition(RRDSET *st) { static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) { RRDHOST *host = st->rrdhost; - rrdset_flag_set(st, RRDSET_FLAG_EXPOSED_UPSTREAM); + rrdset_flag_set(st, RRDSET_FLAG_UPSTREAM_EXPOSED); + + // properly set the name for the remote end to parse it + char *name = ""; + if(unlikely(strcmp(st->id, st->name))) { + // they differ + name = strchr(st->name, '.'); + if(name) + name++; + else + name = ""; + } + + // info("CHART '%s' '%s'", st->id, name); // send the chart buffer_sprintf( host->rrdpush_sender_buffer , "CHART \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %ld %d \"%s %s %s %s\" \"%s\" \"%s\"\n" , st->id - , st->name + , name , st->title , st->units , st->family @@ -129,7 +203,7 @@ static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) { // send the chart local custom variables RRDSETVAR *rs; for(rs = st->variables; rs ;rs = rs->next) { - if(unlikely(rs->options && RRDVAR_OPTION_ALLOCATED)) { + if(unlikely(rs->type == RRDVAR_TYPE_CALCULATED && rs->options & RRDVAR_OPTION_CUSTOM_CHART_VAR)) { calculated_number *value = (calculated_number *) rs->value; buffer_sprintf( @@ -147,7 +221,7 @@ static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) { // sends the current chart dimensions static inline void rrdpush_send_chart_metrics_nolock(RRDSET *st) { RRDHOST *host = st->rrdhost; - buffer_sprintf(host->rrdpush_sender_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->upstream_resync_time > st->last_collected_time.tv_sec)?st->usec_since_last_update:0); + buffer_sprintf(host->rrdpush_sender_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->last_collected_time.tv_sec > st->upstream_resync_time)?st->usec_since_last_update:0); RRDDIM *rd; rrddim_foreach_read(rd, st) { @@ -164,9 +238,12 @@ static inline void rrdpush_send_chart_metrics_nolock(RRDSET *st) { static void rrdpush_sender_thread_spawn(RRDHOST *host); -void rrdset_push_chart_definition(RRDSET *st) { +void rrdset_push_chart_definition_now(RRDSET *st) { RRDHOST *host = st->rrdhost; + if(unlikely(!host->rrdpush_send_enabled || !should_send_chart_matching(st))) + return; + rrdset_rdlock(st); rrdpush_buffer_lock(host); rrdpush_send_chart_definition_nolock(st); @@ -175,11 +252,11 @@ void rrdset_push_chart_definition(RRDSET *st) { } void rrdset_done_push(RRDSET *st) { - RRDHOST *host = st->rrdhost; - - if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_ENABLED))) + if(unlikely(!should_send_chart_matching(st))) return; + RRDHOST *host = st->rrdhost; + rrdpush_buffer_lock(host); if(unlikely(host->rrdpush_send_enabled && !host->rrdpush_sender_spawn)) @@ -239,7 +316,7 @@ static int rrdpush_sender_thread_custom_host_variables_callback(void *rrdvar_ptr RRDVAR *rv = (RRDVAR *)rrdvar_ptr; RRDHOST *host = (RRDHOST *)host_ptr; - if(unlikely(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED)) { + if(unlikely(rv->options & RRDVAR_OPTION_CUSTOM_HOST_VAR && rv->type == RRDVAR_TYPE_CALCULATED)) { rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv); // return 1, so that the traversal will return the number of variables sent @@ -252,6 +329,8 @@ static int rrdpush_sender_thread_custom_host_variables_callback(void *rrdvar_ptr static void rrdpush_sender_thread_send_custom_host_variables(RRDHOST *host) { int ret = rrdvar_callback_for_all_host_variables(host, rrdpush_sender_thread_custom_host_variables_callback, host); + (void)ret; + debug(D_STREAM, "RRDVAR sent %d VARIABLES", ret); } @@ -262,7 +341,7 @@ static void rrdpush_sender_thread_reset_all_charts(RRDHOST *host) { RRDSET *st; rrdset_foreach_read(st, host) { - rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM); + rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); st->upstream_resync_time = 0; @@ -475,6 +554,7 @@ void *rrdpush_sender_thread(void *ptr) { size_t reconnects_counter = 0; size_t sent_bytes = 0; size_t sent_bytes_on_this_connection = 0; + size_t send_attempts = 0; time_t last_sent_t = 0; @@ -494,6 +574,8 @@ void *rrdpush_sender_thread(void *ptr) { // if we don't have socket open, lets wait a bit if(unlikely(host->rrdpush_sender_socket == -1)) { + send_attempts = 0; + if(not_connected_loops == 0 && sent_bytes_on_this_connection > 0) { // fast re-connection on first disconnect sleep_usec(USEC_PER_MS * 500); // milliseconds @@ -509,6 +591,9 @@ void *rrdpush_sender_thread(void *ptr) { // reset the buffer, to properly send charts and metrics rrdpush_sender_thread_data_flush(host); + // send from the beginning + begin = 0; + // make sure the next reconnection will be immediate not_connected_loops = 0; @@ -530,7 +615,7 @@ void *rrdpush_sender_thread(void *ptr) { continue; } else if(unlikely(now_monotonic_sec() - last_sent_t > timeout)) { - error("STREAM %s [send to %s]: could not send metrics for %d seconds - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, timeout, sent_bytes_on_this_connection); + error("STREAM %s [send to %s]: could not send metrics for %d seconds - closing connection - we have sent %zu bytes on this connection via %zu send attempts.", host->hostname, connected_to, timeout, sent_bytes_on_this_connection, send_attempts); rrdpush_sender_thread_close_socket(host); } @@ -544,6 +629,7 @@ void *rrdpush_sender_thread(void *ptr) { debug(D_STREAM, "STREAM: Requesting data output on streaming socket %d...", ofd->fd); ofd->events = POLLOUT; fdmax = 2; + send_attempts++; } else { debug(D_STREAM, "STREAM: Not requesting data output on streaming socket %d (nothing to send now)...", ofd->fd); @@ -743,6 +829,7 @@ static int rrdpush_receive(int fd int rrdpush_enabled = default_rrdpush_enabled; char *rrdpush_destination = default_rrdpush_destination; char *rrdpush_api_key = default_rrdpush_api_key; + char *rrdpush_send_charts_matching = default_rrdpush_send_charts_matching; time_t alarms_delay = 60; RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY rrdpush_multiple_connections_strategy = RRDPUSH_MULTIPLE_CONNECTIONS_ALLOW; @@ -774,6 +861,9 @@ static int rrdpush_receive(int fd rrdpush_multiple_connections_strategy = get_multiple_connections_strategy(&stream_config, key, "multiple connections", rrdpush_multiple_connections_strategy); rrdpush_multiple_connections_strategy = get_multiple_connections_strategy(&stream_config, machine_guid, "multiple connections", rrdpush_multiple_connections_strategy); + rrdpush_send_charts_matching = appconfig_get(&stream_config, key, "default proxy send charts matching", rrdpush_send_charts_matching); + rrdpush_send_charts_matching = appconfig_get(&stream_config, machine_guid, "proxy send charts matching", rrdpush_send_charts_matching); + tags = appconfig_set_default(&stream_config, machine_guid, "host tags", (tags)?tags:""); if(tags && !*tags) tags = NULL; @@ -792,10 +882,11 @@ static int rrdpush_receive(int fd , update_every , history , mode - , (health_enabled != CONFIG_BOOLEAN_NO) - , (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key) + , (unsigned int)(health_enabled != CONFIG_BOOLEAN_NO) + , (unsigned int)(rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key) , rrdpush_destination , rrdpush_api_key + , rrdpush_send_charts_matching ); if(!host) { @@ -1005,6 +1096,14 @@ int rrdpush_receiver_permission_denied(struct web_client *w) { return 401; } +int rrdpush_receiver_too_busy_now(struct web_client *w) { + // we always respond with the same message and error code + // to prevent an attacker from gaining info about the error + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "The server is too busy now to accept this request. Try later."); + return 503; +} + int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url) { (void)host; @@ -1110,6 +1209,26 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url } } + if(unlikely(web_client_streaming_rate_t > 0)) { + static netdata_mutex_t stream_rate_mutex = NETDATA_MUTEX_INITIALIZER; + static volatile time_t last_stream_accepted_t = 0; + + netdata_mutex_lock(&stream_rate_mutex); + time_t now = now_realtime_sec(); + + if(unlikely(last_stream_accepted_t == 0)) + last_stream_accepted_t = now; + + if(now - last_stream_accepted_t < web_client_streaming_rate_t) { + netdata_mutex_unlock(&stream_rate_mutex); + error("STREAM [receive from [%s]:%s]: too busy to accept new streaming request. Will be allowed in %ld secs.", w->client_ip, w->client_port, (long)(web_client_streaming_rate_t - (now - last_stream_accepted_t))); + return rrdpush_receiver_too_busy_now(w); + } + + last_stream_accepted_t = now; + netdata_mutex_unlock(&stream_rate_mutex); + } + struct rrdpush_thread *rpt = callocz(1, sizeof(struct rrdpush_thread)); rpt->fd = w->ifd; rpt->key = strdupz(key); diff --git a/src/rrdpush.h b/streaming/rrdpush.h index bf3d9435..7bf3db93 100644 --- a/src/rrdpush.h +++ b/streaming/rrdpush.h @@ -1,14 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_RRDPUSH_H -#define NETDATA_RRDPUSH_H +#define NETDATA_RRDPUSH_H 1 + +#include "web/server/web_client.h" +#include "daemon/common.h" -extern int default_rrdpush_enabled; +extern unsigned int default_rrdpush_enabled; extern char *default_rrdpush_destination; extern char *default_rrdpush_api_key; +extern char *default_rrdpush_send_charts_matching; extern unsigned int remote_clock_resync_iterations; extern int rrdpush_init(); extern void rrdset_done_push(RRDSET *st); -extern void rrdset_push_chart_definition(RRDSET *st); +extern void rrdset_push_chart_definition_now(RRDSET *st); extern void *rrdpush_sender_thread(void *ptr); extern int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url); diff --git a/src/web_buffer_svg.c b/web/api/badges/web_buffer_svg.c index c05e526e..d0600359 100644 --- a/src/web_buffer_svg.c +++ b/web/api/badges/web_buffer_svg.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "web_buffer_svg.h" #define BADGE_HORIZONTAL_PADDING 4 #define VERDANA_KERNING 0.2 @@ -9,7 +11,7 @@ * https://github.com/badges/shields/blob/master/measure-text.js */ -double verdana11_widths[256] = { +static double verdana11_widths[256] = { [0] = 0.0, [1] = 0.0, [2] = 0.0, @@ -428,57 +430,91 @@ static inline char *format_value_with_precision_and_unit(char *value_string, siz return value_string; } +typedef enum badge_units_format { + UNITS_FORMAT_NONE, + UNITS_FORMAT_SECONDS, + UNITS_FORMAT_SECONDS_AGO, + UNITS_FORMAT_MINUTES, + UNITS_FORMAT_MINUTES_AGO, + UNITS_FORMAT_HOURS, + UNITS_FORMAT_HOURS_AGO, + UNITS_FORMAT_ONOFF, + UNITS_FORMAT_UPDOWN, + UNITS_FORMAT_OKERROR, + UNITS_FORMAT_OKFAILED, + UNITS_FORMAT_EMPTY, + UNITS_FORMAT_PERCENT +} UNITS_FORMAT; + + +static struct units_formatter { + const char *units; + uint32_t hash; + UNITS_FORMAT format; +} badge_units_formatters[] = { + { "seconds", 0, UNITS_FORMAT_SECONDS }, + { "seconds ago", 0, UNITS_FORMAT_SECONDS_AGO }, + { "minutes", 0, UNITS_FORMAT_MINUTES }, + { "minutes ago", 0, UNITS_FORMAT_MINUTES_AGO }, + { "hours", 0, UNITS_FORMAT_HOURS }, + { "hours ago", 0, UNITS_FORMAT_HOURS_AGO }, + { "on/off", 0, UNITS_FORMAT_ONOFF }, + { "on-off", 0, UNITS_FORMAT_ONOFF }, + { "onoff", 0, UNITS_FORMAT_ONOFF }, + { "up/down", 0, UNITS_FORMAT_UPDOWN }, + { "up-down", 0, UNITS_FORMAT_UPDOWN }, + { "updown", 0, UNITS_FORMAT_UPDOWN }, + { "ok/error", 0, UNITS_FORMAT_OKERROR }, + { "ok-error", 0, UNITS_FORMAT_OKERROR }, + { "okerror", 0, UNITS_FORMAT_OKERROR }, + { "ok/failed", 0, UNITS_FORMAT_OKFAILED }, + { "ok-failed", 0, UNITS_FORMAT_OKFAILED }, + { "okfailed", 0, UNITS_FORMAT_OKFAILED }, + { "empty", 0, UNITS_FORMAT_EMPTY }, + { "null", 0, UNITS_FORMAT_EMPTY }, + { "percentage", 0, UNITS_FORMAT_PERCENT }, + { "percent", 0, UNITS_FORMAT_PERCENT }, + { "pcent", 0, UNITS_FORMAT_PERCENT }, + + // terminator + { NULL, 0, UNITS_FORMAT_NONE } +}; + inline char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision) { - static uint32_t - hash_seconds = 0, - hash_seconds_ago = 0, - hash_minutes = 0, - hash_minutes_ago = 0, - hash_hours = 0, - hash_hours_ago = 0, - hash_onoff = 0, - hash_updown = 0, - hash_okerror = 0, - hash_okfailed = 0, - hash_empty = 0, - hash_null = 0, - hash_percentage = 0, - hash_percent = 0, - hash_pcent = 0; - - if(unlikely(!hash_seconds)) { - hash_seconds = simple_hash("seconds"); - hash_seconds_ago = simple_hash("seconds ago"); - hash_minutes = simple_hash("minutes"); - hash_minutes_ago = simple_hash("minutes ago"); - hash_hours = simple_hash("hours"); - hash_hours_ago = simple_hash("hours ago"); - hash_onoff = simple_hash("on/off"); - hash_updown = simple_hash("up/down"); - hash_okerror = simple_hash("ok/error"); - hash_okfailed = simple_hash("ok/failed"); - hash_empty = simple_hash("empty"); - hash_null = simple_hash("null"); - hash_percentage = simple_hash("percentage"); - hash_percent = simple_hash("percent"); - hash_pcent = simple_hash("pcent"); + static int max = -1; + int i; + + if(unlikely(max == -1)) { + for(i = 0; badge_units_formatters[i].units; i++) + badge_units_formatters[i].hash = simple_hash(badge_units_formatters[i].units); + + max = i; } if(unlikely(!units)) units = ""; - uint32_t hash_units = simple_hash(units); - if(unlikely((hash_units == hash_seconds && !strcmp(units, "seconds")) || (hash_units == hash_seconds_ago && !strcmp(units, "seconds ago")))) { + UNITS_FORMAT format = UNITS_FORMAT_NONE; + for(i = 0; i < max; i++) { + struct units_formatter *ptr = &badge_units_formatters[i]; + + if(hash_units == ptr->hash && !strcmp(units, ptr->units)) { + format = ptr->format; + break; + } + } + + if(unlikely(format == UNITS_FORMAT_SECONDS || format == UNITS_FORMAT_SECONDS_AGO)) { if(value == 0.0) { snprintfz(value_string, value_string_len, "%s", "now"); return value_string; } else if(isnan(value) || isinf(value)) { - snprintfz(value_string, value_string_len, "%s", "never"); + snprintfz(value_string, value_string_len, "%s", "undefined"); return value_string; } - const char *suffix = (hash_units == hash_seconds_ago)?" ago":""; + const char *suffix = (format == UNITS_FORMAT_SECONDS_AGO)?" ago":""; size_t s = (size_t)value; size_t d = s / 86400; @@ -498,17 +534,17 @@ inline char *format_value_and_unit(char *value_string, size_t value_string_len, return value_string; } - else if(unlikely((hash_units == hash_minutes && !strcmp(units, "minutes")) || (hash_units == hash_minutes_ago && !strcmp(units, "minutes ago")))) { + else if(unlikely(format == UNITS_FORMAT_MINUTES || format == UNITS_FORMAT_MINUTES_AGO)) { if(value == 0.0) { snprintfz(value_string, value_string_len, "%s", "now"); return value_string; } else if(isnan(value) || isinf(value)) { - snprintfz(value_string, value_string_len, "%s", "never"); + snprintfz(value_string, value_string_len, "%s", "undefined"); return value_string; } - const char *suffix = (hash_units == hash_minutes_ago)?" ago":""; + const char *suffix = (format == UNITS_FORMAT_MINUTES_AGO)?" ago":""; size_t m = (size_t)value; size_t d = m / (60 * 24); @@ -525,17 +561,17 @@ inline char *format_value_and_unit(char *value_string, size_t value_string_len, return value_string; } - else if(unlikely((hash_units == hash_hours && !strcmp(units, "hours")) || (hash_units == hash_hours_ago && !strcmp(units, "hours ago")))) { + else if(unlikely(format == UNITS_FORMAT_HOURS || format == UNITS_FORMAT_HOURS_AGO)) { if(value == 0.0) { snprintfz(value_string, value_string_len, "%s", "now"); return value_string; } else if(isnan(value) || isinf(value)) { - snprintfz(value_string, value_string_len, "%s", "never"); + snprintfz(value_string, value_string_len, "%s", "undefined"); return value_string; } - const char *suffix = (hash_units == hash_hours_ago)?" ago":""; + const char *suffix = (format == UNITS_FORMAT_HOURS_AGO)?" ago":""; size_t h = (size_t)value; size_t d = h / 24; @@ -549,42 +585,32 @@ inline char *format_value_and_unit(char *value_string, size_t value_string_len, return value_string; } - else if(unlikely(hash_units == hash_onoff && !strcmp(units, "on/off"))) { + else if(unlikely(format == UNITS_FORMAT_ONOFF)) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"on":"off"); return value_string; } - else if(unlikely(hash_units == hash_updown && !strcmp(units, "up/down"))) { + else if(unlikely(format == UNITS_FORMAT_UPDOWN)) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"up":"down"); return value_string; } - else if(unlikely(hash_units == hash_okerror && !strcmp(units, "ok/error"))) { + else if(unlikely(format == UNITS_FORMAT_OKERROR)) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"error"); return value_string; } - else if(unlikely(hash_units == hash_okfailed && !strcmp(units, "ok/failed"))) { + else if(unlikely(format == UNITS_FORMAT_OKFAILED)) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"failed"); return value_string; } - else if(unlikely(hash_units == hash_empty && !strcmp(units, "empty"))) + else if(unlikely(format == UNITS_FORMAT_EMPTY)) units = ""; - else if(unlikely(hash_units == hash_null && !strcmp(units, "null"))) - units = ""; - - else if(unlikely(hash_units == hash_percentage && !strcmp(units, "percentage"))) - units = "%"; - - else if(unlikely(hash_units == hash_percent && !strcmp(units, "percent"))) - units = "%"; - - else if(unlikely(hash_units == hash_pcent && !strcmp(units, "pcent"))) + else if(unlikely(format == UNITS_FORMAT_PERCENT)) units = "%"; - if(unlikely(isnan(value) || isinf(value))) { strcpy(value_string, "-"); return value_string; @@ -593,20 +619,51 @@ inline char *format_value_and_unit(char *value_string, size_t value_string_len, return format_value_with_precision_and_unit(value_string, value_string_len, value, units, precision); } +static struct badge_color { + const char *name; + uint32_t hash; + const char *color; +} badge_colors[] = { + + // colors from: + // https://github.com/badges/shields/blob/master/colorscheme.json + + { "brightgreen", 0, "#4c1" }, + { "green", 0, "#97CA00" }, + { "yellow", 0, "#dfb317" }, + { "yellowgreen", 0, "#a4a61d" }, + { "orange", 0, "#fe7d37" }, + { "red", 0, "#e05d44" }, + { "blue", 0, "#007ec6" }, + { "grey", 0, "#555" }, + { "gray", 0, "#555" }, + { "lightgrey", 0, "#9f9f9f" }, + { "lightgray", 0, "#9f9f9f" }, + + // terminator + { NULL, 0, NULL } +}; + static inline const char *color_map(const char *color) { - // colors from: - // https://github.com/badges/shields/blob/master/colorscheme.json - if(!strcmp(color, "brightgreen")) return "#4c1"; - else if(!strcmp(color, "green")) return "#97CA00"; - else if(!strcmp(color, "yellow")) return "#dfb317"; - else if(!strcmp(color, "yellowgreen")) return "#a4a61d"; - else if(!strcmp(color, "orange")) return "#fe7d37"; - else if(!strcmp(color, "red")) return "#e05d44"; - else if(!strcmp(color, "blue")) return "#007ec6"; - else if(!strcmp(color, "grey")) return "#555"; - else if(!strcmp(color, "gray")) return "#555"; - else if(!strcmp(color, "lightgrey")) return "#9f9f9f"; - else if(!strcmp(color, "lightgray")) return "#9f9f9f"; + static int max = -1; + int i; + + if(unlikely(max == -1)) { + for(i = 0; badge_colors[i].name ;i++) + badge_colors[i].hash = simple_hash(badge_colors[i].name); + + max = i; + } + + uint32_t hash = simple_hash(color); + + for(i = 0; i < max; i++) { + struct badge_color *ptr = &badge_colors[i]; + + if(hash == ptr->hash && !strcmp(color, ptr->name)) + return ptr->color; + } + return color; } @@ -830,3 +887,256 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch label_width + value_width / 2 -1, ceil(height - text_offset), value_escaped, label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped); } + +int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) { + int ret = 400; + buffer_flush(w->response.data); + + BUFFER *dimensions = NULL; + + const char *chart = NULL + , *before_str = NULL + , *after_str = NULL + , *points_str = NULL + , *multiply_str = NULL + , *divide_str = NULL + , *label = NULL + , *units = NULL + , *label_color = NULL + , *value_color = NULL + , *refresh_str = NULL + , *precision_str = NULL + , *scale_str = NULL + , *alarm = NULL; + + int group = RRDR_GROUPING_AVERAGE; + uint32_t options = 0x00000000; + + while(url) { + char *value = mystrsep(&url, "/?&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value); + + // name and value are now the parameters + // they are not null and not empty + + if(!strcmp(name, "chart")) chart = value; + else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { + if(!dimensions) + dimensions = buffer_create(100); + + buffer_strcat(dimensions, "|"); + buffer_strcat(dimensions, value); + } + else if(!strcmp(name, "after")) after_str = value; + else if(!strcmp(name, "before")) before_str = value; + else if(!strcmp(name, "points")) points_str = value; + else if(!strcmp(name, "group")) { + group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE); + } + else if(!strcmp(name, "options")) { + options |= web_client_api_request_v1_data_options(value); + } + else if(!strcmp(name, "label")) label = value; + else if(!strcmp(name, "units")) units = value; + else if(!strcmp(name, "label_color")) label_color = value; + else if(!strcmp(name, "value_color")) value_color = value; + else if(!strcmp(name, "multiply")) multiply_str = value; + else if(!strcmp(name, "divide")) divide_str = value; + else if(!strcmp(name, "refresh")) refresh_str = value; + else if(!strcmp(name, "precision")) precision_str = value; + else if(!strcmp(name, "scale")) scale_str = value; + else if(!strcmp(name, "alarm")) alarm = value; + } + + if(!chart || !*chart) { + buffer_no_cacheable(w->response.data); + buffer_sprintf(w->response.data, "No chart id is given at the request."); + goto cleanup; + } + + int scale = (scale_str && *scale_str)?str2i(scale_str):100; + + RRDSET *st = rrdset_find(host, chart); + if(!st) st = rrdset_find_byname(host, chart); + if(!st) { + buffer_no_cacheable(w->response.data); + buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0); + ret = 200; + goto cleanup; + } + st->last_accessed_time = now_realtime_sec(); + + RRDCALC *rc = NULL; + if(alarm) { + rc = rrdcalc_find(st, alarm); + if (!rc) { + buffer_no_cacheable(w->response.data); + buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0); + ret = 200; + goto cleanup; + } + } + + long long multiply = (multiply_str && *multiply_str )?str2l(multiply_str):1; + long long divide = (divide_str && *divide_str )?str2l(divide_str):1; + long long before = (before_str && *before_str )?str2l(before_str):0; + long long after = (after_str && *after_str )?str2l(after_str):-st->update_every; + int points = (points_str && *points_str )?str2i(points_str):1; + int precision = (precision_str && *precision_str)?str2i(precision_str):-1; + + if(!multiply) multiply = 1; + if(!divide) divide = 1; + + int refresh = 0; + if(refresh_str && *refresh_str) { + if(!strcmp(refresh_str, "auto")) { + if(rc) refresh = rc->update_every; + else if(options & RRDR_OPTION_NOT_ALIGNED) + refresh = st->update_every; + else { + refresh = (int)(before - after); + if(refresh < 0) refresh = -refresh; + } + } + else { + refresh = str2i(refresh_str); + if(refresh < 0) refresh = -refresh; + } + } + + if(!label) { + if(alarm) { + char *s = (char *)alarm; + while(*s) { + if(*s == '_') *s = ' '; + s++; + } + label = alarm; + } + else if(dimensions) { + const char *dim = buffer_tostring(dimensions); + if(*dim == '|') dim++; + label = dim; + } + else + label = st->name; + } + if(!units) { + if(alarm) { + if(rc->units) + units = rc->units; + else + units = ""; + } + else if(options & RRDR_OPTION_PERCENTAGE) + units = "%"; + else + units = st->units; + } + + debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'" + , w->id + , chart + , alarm?alarm:"" + , (dimensions)?buffer_tostring(dimensions):"" + , after + , before + , points + , group + , options + ); + + if(rc) { + if (refresh > 0) { + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + w->response.data->expires = now_realtime_sec() + refresh; + } + else buffer_no_cacheable(w->response.data); + + if(!value_color) { + switch(rc->status) { + case RRDCALC_STATUS_CRITICAL: + value_color = "red"; + break; + + case RRDCALC_STATUS_WARNING: + value_color = "orange"; + break; + + case RRDCALC_STATUS_CLEAR: + value_color = "brightgreen"; + break; + + case RRDCALC_STATUS_UNDEFINED: + value_color = "lightgrey"; + break; + + case RRDCALC_STATUS_UNINITIALIZED: + value_color = "#000"; + break; + + default: + value_color = "grey"; + break; + } + } + + buffer_svg(w->response.data, + label, + (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide, + units, + label_color, + value_color, + precision, + scale, + options + ); + ret = 200; + } + else { + time_t latest_timestamp = 0; + int value_is_null = 1; + calculated_number n = NAN; + ret = 500; + + // if the collected value is too old, don't calculate its value + if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above))) + ret = rrdset2value_api_v1(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL + , points, after, before, group, 0, options, NULL, &latest_timestamp, &value_is_null); + + // if the value cannot be calculated, show empty badge + if (ret != 200) { + buffer_no_cacheable(w->response.data); + value_is_null = 1; + n = 0; + ret = 200; + } + else if (refresh > 0) { + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + w->response.data->expires = now_realtime_sec() + refresh; + } + else buffer_no_cacheable(w->response.data); + + // render the badge + buffer_svg(w->response.data, + label, + (value_is_null)?NAN:(n * multiply / divide), + units, + label_color, + value_color, + precision, + scale, + options + ); + } + + cleanup: + buffer_free(dimensions); + return ret; +} diff --git a/src/web_buffer_svg.h b/web/api/badges/web_buffer_svg.h index c23abf0d..f75677bf 100644 --- a/src/web_buffer_svg.h +++ b/web/api/badges/web_buffer_svg.h @@ -1,7 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_WEB_BUFFER_SVG_H #define NETDATA_WEB_BUFFER_SVG_H 1 +#include "libnetdata/libnetdata.h" +#include "web/server/web_client.h" + extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options); extern char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision); +extern int web_client_api_request_v1_badge(struct rrdhost *host, struct web_client *w, char *url); + +#include "web/api/web_api_v1.h" + #endif /* NETDATA_WEB_BUFFER_SVG_H */ diff --git a/src/web_api_v1.c b/web/api/web_api_v1.c index c32660c8..1e03828e 100644 --- a/src/web_api_v1.c +++ b/web/api/web_api_v1.c @@ -1,23 +1,11 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later -static struct { - const char *name; - uint32_t hash; - int value; -} api_v1_data_groups[] = { - { "average" , 0 , GROUP_AVERAGE} - , {"min" , 0 , GROUP_MIN} - , {"max" , 0 , GROUP_MAX} - , {"sum" , 0 , GROUP_SUM} - , {"incremental_sum", 0 , GROUP_INCREMENTAL_SUM} - , {"incremental-sum", 0 , GROUP_INCREMENTAL_SUM} - , { NULL, 0, 0} -}; +#include "web_api_v1.h" static struct { const char *name; uint32_t hash; - uint32_t value; + RRDR_OPTIONS value; } api_v1_data_options[] = { { "nonzero" , 0 , RRDR_OPTION_NONZERO} , {"flip" , 0 , RRDR_OPTION_REVERSED} @@ -64,6 +52,7 @@ static struct { , {DATASOURCE_FORMAT_JS_ARRAY , 0 , DATASOURCE_JS_ARRAY} , {DATASOURCE_FORMAT_SSV_COMMA , 0 , DATASOURCE_SSV_COMMA} , {DATASOURCE_FORMAT_CSV_JSON_ARRAY , 0 , DATASOURCE_CSV_JSON_ARRAY} + , {DATASOURCE_FORMAT_CSV_MARKDOWN , 0 , DATASOURCE_CSV_MARKDOWN} , { NULL, 0, 0} }; @@ -84,9 +73,6 @@ static struct { void web_client_api_v1_init(void) { int i; - for(i = 0; api_v1_data_groups[i].name ; i++) - api_v1_data_groups[i].hash = simple_hash(api_v1_data_groups[i].name); - for(i = 0; api_v1_data_options[i].name ; i++) api_v1_data_options[i].hash = simple_hash(api_v1_data_options[i].name); @@ -95,17 +81,8 @@ void web_client_api_v1_init(void) { for(i = 0; api_v1_data_google_formats[i].name ; i++) api_v1_data_google_formats[i].hash = simple_hash(api_v1_data_google_formats[i].name); -} - -inline int web_client_api_request_v1_data_group(char *name, int def) { - int i; - uint32_t hash = simple_hash(name); - for(i = 0; api_v1_data_groups[i].name ; i++) - if(unlikely(hash == api_v1_data_groups[i].hash && !strcmp(name, api_v1_data_groups[i].name))) - return api_v1_data_groups[i].value; - - return def; + web_client_api_v1_init_grouping(); } inline uint32_t web_client_api_request_v1_data_options(char *o) { @@ -248,358 +225,21 @@ inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, buffer_flush(w->response.data); w->response.data->contenttype = CT_APPLICATION_JSON; - rrd_stats_api_v1_charts(host, w->response.data); + charts2json(host, w->response.data); return 200; } -inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url) { - int format = ALLMETRICS_SHELL; - int help = 0, types = 0, timestamps = 1, names = backend_send_names; // prometheus options - const char *prometheus_server = w->client_ip; - uint32_t prometheus_options = backend_options; - const char *prometheus_prefix = backend_prefix; - - while(url) { - char *value = mystrsep(&url, "?&"); - if (!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if(!name || !*name) continue; - if(!value || !*value) continue; - - if(!strcmp(name, "format")) { - if(!strcmp(value, ALLMETRICS_FORMAT_SHELL)) - format = ALLMETRICS_SHELL; - else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS)) - format = ALLMETRICS_PROMETHEUS; - else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS)) - format = ALLMETRICS_PROMETHEUS_ALL_HOSTS; - else if(!strcmp(value, ALLMETRICS_FORMAT_JSON)) - format = ALLMETRICS_JSON; - else - format = 0; - } - else if(!strcmp(name, "help")) { - if(!strcmp(value, "yes")) - help = 1; - else - help = 0; - } - else if(!strcmp(name, "types")) { - if(!strcmp(value, "yes")) - types = 1; - else - types = 0; - } - else if(!strcmp(name, "names")) { - if(!strcmp(value, "yes")) - names = 1; - else - names = 0; - } - else if(!strcmp(name, "timestamps")) { - if(!strcmp(value, "yes")) - timestamps = 1; - else - timestamps = 0; - } - else if(!strcmp(name, "server")) { - prometheus_server = value; - } - else if(!strcmp(name, "prefix")) { - prometheus_prefix = value; - } - else if(!strcmp(name, "data") || !strcmp(name, "source") || !strcmp(name, "data source") || !strcmp(name, "data-source") || !strcmp(name, "data_source") || !strcmp(name, "datasource")) { - prometheus_options = backend_parse_data_source(value, prometheus_options); - } - } - - buffer_flush(w->response.data); - buffer_no_cacheable(w->response.data); - - switch(format) { - case ALLMETRICS_JSON: - w->response.data->contenttype = CT_APPLICATION_JSON; - rrd_stats_api_v1_charts_allmetrics_json(host, w->response.data); - return 200; - - case ALLMETRICS_SHELL: - w->response.data->contenttype = CT_TEXT_PLAIN; - rrd_stats_api_v1_charts_allmetrics_shell(host, w->response.data); - return 200; - - case ALLMETRICS_PROMETHEUS: - w->response.data->contenttype = CT_PROMETHEUS; - rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_options, help, types, names, timestamps); - return 200; - - case ALLMETRICS_PROMETHEUS_ALL_HOSTS: - w->response.data->contenttype = CT_PROMETHEUS; - rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_options, help, types, names, timestamps); - return 200; - - default: - w->response.data->contenttype = CT_TEXT_PLAIN; - buffer_strcat(w->response.data, "Which format? '" ALLMETRICS_FORMAT_SHELL "', '" ALLMETRICS_FORMAT_PROMETHEUS "', '" ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS "' and '" ALLMETRICS_FORMAT_JSON "' are currently supported."); - return 400; - } -} - inline int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url) { return web_client_api_request_single_chart(host, w, url, rrd_stats_api_v1_chart); } -int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) { - int ret = 400; - buffer_flush(w->response.data); - - BUFFER *dimensions = NULL; - - const char *chart = NULL - , *before_str = NULL - , *after_str = NULL - , *points_str = NULL - , *multiply_str = NULL - , *divide_str = NULL - , *label = NULL - , *units = NULL - , *label_color = NULL - , *value_color = NULL - , *refresh_str = NULL - , *precision_str = NULL - , *scale_str = NULL - , *alarm = NULL; - - int group = GROUP_AVERAGE; - uint32_t options = 0x00000000; - - while(url) { - char *value = mystrsep(&url, "/?&"); - if(!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if(!name || !*name) continue; - if(!value || !*value) continue; - - debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value); - - // name and value are now the parameters - // they are not null and not empty - - if(!strcmp(name, "chart")) chart = value; - else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { - if(!dimensions) - dimensions = buffer_create(100); - - buffer_strcat(dimensions, "|"); - buffer_strcat(dimensions, value); - } - else if(!strcmp(name, "after")) after_str = value; - else if(!strcmp(name, "before")) before_str = value; - else if(!strcmp(name, "points")) points_str = value; - else if(!strcmp(name, "group")) { - group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE); - } - else if(!strcmp(name, "options")) { - options |= web_client_api_request_v1_data_options(value); - } - else if(!strcmp(name, "label")) label = value; - else if(!strcmp(name, "units")) units = value; - else if(!strcmp(name, "label_color")) label_color = value; - else if(!strcmp(name, "value_color")) value_color = value; - else if(!strcmp(name, "multiply")) multiply_str = value; - else if(!strcmp(name, "divide")) divide_str = value; - else if(!strcmp(name, "refresh")) refresh_str = value; - else if(!strcmp(name, "precision")) precision_str = value; - else if(!strcmp(name, "scale")) scale_str = value; - else if(!strcmp(name, "alarm")) alarm = value; - } - - if(!chart || !*chart) { - buffer_no_cacheable(w->response.data); - buffer_sprintf(w->response.data, "No chart id is given at the request."); - goto cleanup; - } - - int scale = (scale_str && *scale_str)?str2i(scale_str):100; - - RRDSET *st = rrdset_find(host, chart); - if(!st) st = rrdset_find_byname(host, chart); - if(!st) { - buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0); - ret = 200; - goto cleanup; - } - st->last_accessed_time = now_realtime_sec(); - - RRDCALC *rc = NULL; - if(alarm) { - rc = rrdcalc_find(st, alarm); - if (!rc) { - buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0); - ret = 200; - goto cleanup; - } - } - - long long multiply = (multiply_str && *multiply_str )?str2l(multiply_str):1; - long long divide = (divide_str && *divide_str )?str2l(divide_str):1; - long long before = (before_str && *before_str )?str2l(before_str):0; - long long after = (after_str && *after_str )?str2l(after_str):-st->update_every; - int points = (points_str && *points_str )?str2i(points_str):1; - int precision = (precision_str && *precision_str)?str2i(precision_str):-1; - - if(!multiply) multiply = 1; - if(!divide) divide = 1; - - int refresh = 0; - if(refresh_str && *refresh_str) { - if(!strcmp(refresh_str, "auto")) { - if(rc) refresh = rc->update_every; - else if(options & RRDR_OPTION_NOT_ALIGNED) - refresh = st->update_every; - else { - refresh = (int)(before - after); - if(refresh < 0) refresh = -refresh; - } - } - else { - refresh = str2i(refresh_str); - if(refresh < 0) refresh = -refresh; - } - } - - if(!label) { - if(alarm) { - char *s = (char *)alarm; - while(*s) { - if(*s == '_') *s = ' '; - s++; - } - label = alarm; - } - else if(dimensions) { - const char *dim = buffer_tostring(dimensions); - if(*dim == '|') dim++; - label = dim; - } - else - label = st->name; - } - if(!units) { - if(alarm) { - if(rc->units) - units = rc->units; - else - units = ""; - } - else if(options & RRDR_OPTION_PERCENTAGE) - units = "%"; - else - units = st->units; - } - - debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'" - , w->id - , chart - , alarm?alarm:"" - , (dimensions)?buffer_tostring(dimensions):"" - , after - , before - , points - , group - , options - ); - - if(rc) { - if (refresh > 0) { - buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); - w->response.data->expires = now_realtime_sec() + refresh; - } - else buffer_no_cacheable(w->response.data); - - if(!value_color) { - switch(rc->status) { - case RRDCALC_STATUS_CRITICAL: - value_color = "red"; - break; - - case RRDCALC_STATUS_WARNING: - value_color = "orange"; - break; +void fix_google_param(char *s) { + if(unlikely(!s)) return; - case RRDCALC_STATUS_CLEAR: - value_color = "brightgreen"; - break; - - case RRDCALC_STATUS_UNDEFINED: - value_color = "lightgrey"; - break; - - case RRDCALC_STATUS_UNINITIALIZED: - value_color = "#000"; - break; - - default: - value_color = "grey"; - break; - } - } - - buffer_svg(w->response.data, - label, - (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide, - units, - label_color, - value_color, - precision, - scale, - options - ); - ret = 200; + for( ; *s ;s++) { + if(!isalnum(*s) && *s != '.' && *s != '_' && *s != '-') + *s = '_'; } - else { - time_t latest_timestamp = 0; - int value_is_null = 1; - calculated_number n = NAN; - ret = 500; - - // if the collected value is too old, don't calculate its value - if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above))) - ret = rrdset2value_api_v1(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL - , points, after, before, group, 0, options, NULL, &latest_timestamp, &value_is_null); - - // if the value cannot be calculated, show empty badge - if (ret != 200) { - buffer_no_cacheable(w->response.data); - value_is_null = 1; - n = 0; - ret = 200; - } - else if (refresh > 0) { - buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); - w->response.data->expires = now_realtime_sec() + refresh; - } - else buffer_no_cacheable(w->response.data); - - // render the badge - buffer_svg(w->response.data, - label, - (value_is_null)?NAN:(n * multiply / divide), - units, - label_color, - value_color, - precision, - scale, - options - ); - } - - cleanup: - buffer_free(dimensions); - return ret; } // returns the HTTP code @@ -626,7 +266,7 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c , *group_time_str = NULL , *points_str = NULL; - int group = GROUP_AVERAGE; + int group = RRDR_GROUPING_AVERAGE; uint32_t format = DATASOURCE_JSON; uint32_t options = 0x00000000; @@ -654,7 +294,7 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c else if(!strcmp(name, "points")) points_str = value; else if(!strcmp(name, "gtime")) group_time_str = value; else if(!strcmp(name, "group")) { - group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE); + group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE); } else if(!strcmp(name, "format")) { format = web_client_api_request_v1_data_format(value); @@ -701,6 +341,14 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c } } + // validate the google parameters given + fix_google_param(google_out); + fix_google_param(google_sig); + fix_google_param(google_reqId); + fix_google_param(google_version); + fix_google_param(responseHandler); + fix_google_param(outFileName); + if(!chart || !*chart) { buffer_sprintf(w->response.data, "No chart id is given at the request."); goto cleanup; @@ -808,7 +456,7 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client * debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url); - // FIXME + // TODO // The browser may send multiple cookies with our id char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "="); diff --git a/src/web_api_v1.h b/web/api/web_api_v1.h index 6f4de1ab..b6f315dc 100644 --- a/src/web_api_v1.h +++ b/web/api/web_api_v1.h @@ -1,7 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_WEB_API_V1_H -#define NETDATA_WEB_API_V1_H +#define NETDATA_WEB_API_V1_H 1 + +#include "daemon/common.h" +#include "web/api/badges/web_buffer_svg.h" +#include "web/api/formatters/rrd2json.h" -extern int web_client_api_request_v1_data_group(char *name, int def); extern uint32_t web_client_api_request_v1_data_options(char *o); extern uint32_t web_client_api_request_v1_data_format(char *name); extern uint32_t web_client_api_request_v1_data_google_format(char *name); @@ -11,9 +16,7 @@ extern int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client extern int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)); extern int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url); extern int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url); -extern int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url); extern int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url); -extern int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url); extern int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url); extern int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url); extern int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url); diff --git a/src/web_client.c b/web/server/web_client.c index 477fb3d5..282cfcd1 100644 --- a/src/web_client.c +++ b/web/server/web_client.c @@ -1,4 +1,6 @@ -#include "common.h" +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "web_client.h" // this is an async I/O implementation of the web server request parser // it is used by all netdata web servers @@ -53,6 +55,18 @@ static inline int web_client_uncrock_socket(struct web_client *w) { return 0; } +static inline char *strip_control_characters(char *url) { + char *s = url; + if(!s) return ""; + + if(iscntrl(*s)) *s = ' '; + while(*++s) { + if(iscntrl(*s)) *s = ' '; + } + + return url; +} + void web_client_request_done(struct web_client *w) { web_client_uncrock_socket(w); @@ -120,7 +134,7 @@ void web_client_request_done(struct web_client *w) { , dt_usec(&tv, &w->tv_ready) / 1000.0 , dt_usec(&tv, &w->tv_in) / 1000.0 , w->response.code - , w->last_url + , strip_control_characters(w->last_url) ); } @@ -329,10 +343,6 @@ int mysendfile(struct web_client *w, char *filename) { // skip leading slashes while (*filename == '/') filename++; - // if the filename contain known paths, skip them - if(strncmp(filename, WEB_PATH_FILE "/", strlen(WEB_PATH_FILE) + 1) == 0) - filename = &filename[strlen(WEB_PATH_FILE) + 1]; - // if the filename contains "strange" characters, refuse to serve it char *s; for(s = filename; *s ;s++) { @@ -403,7 +413,7 @@ int mysendfile(struct web_client *w, char *filename) { if(errno == EBUSY || errno == EAGAIN) { error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename); w->response.data->contenttype = CT_TEXT_HTML; - buffer_sprintf(w->response.header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename); + buffer_sprintf(w->response.header, "Location: /%s\r\n", filename); buffer_strcat(w->response.data, "File is currently busy, please try again later: "); buffer_strcat_htmlescape(w->response.data, webfilename); return 307; @@ -550,31 +560,6 @@ void buffer_data_options2string(BUFFER *wb, uint32_t options) { } } -const char *group_method2string(int group) { - switch(group) { - case GROUP_UNDEFINED: - return ""; - - case GROUP_AVERAGE: - return "average"; - - case GROUP_MIN: - return "min"; - - case GROUP_MAX: - return "max"; - - case GROUP_SUM: - return "sum"; - - case GROUP_INCREMENTAL_SUM: - return "incremental-sum"; - - default: - return "unknown-group-method"; - } -} - static inline int check_host_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) { if(unlikely(host->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) { buffer_flush(w->response.data); @@ -898,7 +883,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) { *ue = ' '; // copy the URL - we are going to overwrite parts of it - // FIXME -- we should avoid it + // TODO -- ideally we we should avoid copying buffers around strncpyz(w->last_url, w->decoded_url, NETDATA_WEB_REQUEST_URL_SIZE); w->header_parse_tries = 0; @@ -1114,11 +1099,6 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch static uint32_t hash_api = 0, hash_netdata_conf = 0, - hash_data = 0, - hash_datasource = 0, - hash_graph = 0, - hash_list = 0, - hash_all_json = 0, hash_host = 0; #ifdef NETDATA_INTERNAL_CHECKS @@ -1128,11 +1108,6 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch if(unlikely(!hash_api)) { hash_api = simple_hash("api"); hash_netdata_conf = simple_hash("netdata.conf"); - hash_data = simple_hash(WEB_PATH_DATA); - hash_datasource = simple_hash(WEB_PATH_DATASOURCE); - hash_graph = simple_hash(WEB_PATH_GRAPH); - hash_list = simple_hash("list"); - hash_all_json = simple_hash("all.json"); hash_host = simple_hash("host"); #ifdef NETDATA_INTERNAL_CHECKS hash_exit = simple_hash("exit"); @@ -1154,26 +1129,6 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch debug(D_WEB_CLIENT_ACCESS, "%llu: host switch request ...", w->id); return web_client_switch_host(host, w, url); } - else if(unlikely(hash == hash_data && strcmp(tok, WEB_PATH_DATA) == 0)) { // old API "data" - debug(D_WEB_CLIENT_ACCESS, "%llu: old API data request...", w->id); - return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_data_request_json); - } - else if(unlikely(hash == hash_datasource && strcmp(tok, WEB_PATH_DATASOURCE) == 0)) { // old API "datasource" - debug(D_WEB_CLIENT_ACCESS, "%llu: old API datasource request...", w->id); - return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_data_request_jsonp); - } - else if(unlikely(hash == hash_graph && strcmp(tok, WEB_PATH_GRAPH) == 0)) { // old API "graph" - debug(D_WEB_CLIENT_ACCESS, "%llu: old API graph request...", w->id); - return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_graph_request); - } - else if(unlikely(hash == hash_list && strcmp(tok, "list") == 0)) { // old API "list" - debug(D_WEB_CLIENT_ACCESS, "%llu: old API list request...", w->id); - return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_list_request); - } - else if(unlikely(hash == hash_all_json && strcmp(tok, "all.json") == 0)) { // old API "all.json" - debug(D_WEB_CLIENT_ACCESS, "%llu: old API all.json request...", w->id); - return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_all_json); - } else if(unlikely(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0)) { // netdata.conf if(unlikely(!web_client_can_access_netdataconf(w))) return web_client_permission_denied(w); @@ -1638,6 +1593,8 @@ ssize_t web_client_read_file(struct web_client *w) ssize_t bytes = read(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t)left); if(likely(bytes > 0)) { size_t old = w->response.data->len; + (void)old; + w->response.data->len += bytes; w->response.data->buffer[w->response.data->len] = '\0'; @@ -1691,6 +1648,8 @@ ssize_t web_client_receive(struct web_client *w) w->stats_received_bytes += bytes; size_t old = w->response.data->len; + (void)old; + w->response.data->len += bytes; w->response.data->buffer[w->response.data->len] = '\0'; diff --git a/src/web_client.h b/web/server/web_client.h index b495c37e..b9e528fc 100644 --- a/src/web_client.h +++ b/web/server/web_client.h @@ -1,6 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_WEB_CLIENT_H #define NETDATA_WEB_CLIENT_H 1 +#include "libnetdata/libnetdata.h" + #ifdef NETDATA_WITH_ZLIB extern int web_enable_gzip, web_gzip_level, @@ -70,6 +74,7 @@ typedef enum web_client_flags { #define web_client_set_tcp(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TCP_CLIENT) #define web_client_set_unix(w) web_client_flag_set(w, WEB_CLIENT_FLAG_UNIX_CLIENT) #define web_client_check_unix(w) web_client_flag_check(w, WEB_CLIENT_FLAG_UNIX_CLIENT) +#define web_client_check_tcp(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT) #define web_client_is_corkable(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT) @@ -98,7 +103,7 @@ struct response { Bytef zbuffer[NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE]; // temporary buffer for storing compressed output size_t zsent; // the compressed bytes we have sent to the client size_t zhave; // the compressed bytes that we have received from zlib - int zinitialized:1; + unsigned int zinitialized:1; #endif /* NETDATA_WITH_ZLIB */ }; @@ -179,11 +184,10 @@ extern ssize_t web_client_read_file(struct web_client *w); extern void web_client_process_request(struct web_client *w); extern void web_client_request_done(struct web_client *w); -extern int web_client_api_request_v1_data_group(char *name, int def); -extern const char *group_method2string(int group); - extern void buffer_data_options2string(BUFFER *wb, uint32_t options); extern int mysendfile(struct web_client *w, char *filename); +#include "daemon/common.h" + #endif diff --git a/src/web_server.h b/web/server/web_server.h index 7492547e..7777c897 100644 --- a/src/web_server.h +++ b/web/server/web_server.h @@ -1,10 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef NETDATA_WEB_SERVER_H #define NETDATA_WEB_SERVER_H 1 -#define WEB_PATH_FILE "file" -#define WEB_PATH_DATA "data" -#define WEB_PATH_DATASOURCE "datasource" -#define WEB_PATH_GRAPH "graph" +#include "libnetdata/libnetdata.h" +#include "web_client.h" #ifndef API_LISTEN_PORT #define API_LISTEN_PORT 19999 @@ -33,14 +33,28 @@ extern WEB_SERVER_MODE web_server_mode; extern WEB_SERVER_MODE web_server_mode_id(const char *mode); extern const char *web_server_mode_name(WEB_SERVER_MODE id); -extern void *socket_listen_main_multi_threaded(void *ptr); -extern void *socket_listen_main_single_threaded(void *ptr); -extern void *socket_listen_main_static_threaded(void *ptr); extern int api_listen_sockets_setup(void); #define DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST 60 #define DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS 60 extern int web_client_timeout; extern int web_client_first_request_timeout; +extern long web_client_streaming_rate_t; + +#ifdef WEB_SERVER_INTERNALS +extern LISTEN_SOCKETS api_sockets; +extern void web_client_update_acl_matches(struct web_client *w); +extern void web_server_log_connection(struct web_client *w, const char *msg); +extern void web_client_initialize_connection(struct web_client *w); +extern struct web_client *web_client_create_on_listenfd(int listener); + +#include "web_client_cache.h" +#endif // WEB_SERVER_INTERNALS + +#include "single/single-threaded.h" +#include "multi/multi-threaded.h" +#include "static/static-threaded.h" + +#include "daemon/common.h" #endif /* NETDATA_WEB_SERVER_H */ |