summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
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.am307
-rw-r--r--src/Makefile.in1238
-rw-r--r--src/appconfig.h74
-rw-r--r--src/backend_prometheus.h11
-rw-r--r--src/backends.h30
-rw-r--r--src/clocks.c137
-rw-r--r--src/health.h438
-rw-r--r--src/ipc.h7
-rw-r--r--src/plugin_checks.h8
-rw-r--r--src/plugin_freebsd.h130
-rw-r--r--src/plugin_idlejitter.h6
-rw-r--r--src/plugin_macos.h14
-rw-r--r--src/plugin_nfacct.h7
-rw-r--r--src/plugin_proc_diskspace.h6
-rw-r--r--src/plugin_tc.h7
-rw-r--r--src/rrd2json.c2059
-rw-r--r--src/rrd2json.h82
-rw-r--r--src/rrd2json_api_old.c487
-rw-r--r--src/rrd2json_api_old.h14
-rw-r--r--src/statsd.h9
-rw-r--r--src/web_api_old.c237
-rw-r--r--src/web_api_old.h13
-rw-r--r--src/web_server.c1292
-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 1360638f2..53a9a2395 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 bfcda9297..223b3f9f0 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 8595da6c2..f592e9fc8 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(&gtime, &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 0e2d5163a..0cf2a2633 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 f6e613c4b..9c0fd7f43 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 b99b97d40..f8a2008a8 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 0a229f38e..dca7c9076 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 ed7466ead..10279aabc 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 73f8f1824..e15845857 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 ea82b9fd1..c86f23166 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 81264b3f3..c256da8b3 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 1bd48d4bf..93dfc320b 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 1e11255aa..da5a351de 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 a0d3dc2ea..5cde37113 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 df4c019a4..a1cff3af0 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 77bd95d55..3fe3b0306 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 5e8ce0ee4..5d0ba929e 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 47d32a9f7..1c43d624c 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 cb6fa8af9..6b443c04a 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 6ac3d25d1..628a5b10d 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 02815ef04..7d42dd189 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 5693dda06..465ecd796 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 692d7cae1..adccf3f0f 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 a9076fca4..6c6bee519 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 e0afb0d6d..0c3244d61 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 a7f9b4e38..bfefe1ad4 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 8cde3334b..387b395a3 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 867f39eb2..73b117179 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 868f7d50a..db95b1689 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 3915bf0e9..f77159ebd 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 341b9e0ca..97cbc060a 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 d76972f3c..43dcf2a88 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 dd070e4c3..2dc3c59c0 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 a4c778cba..f5702859c 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 8aca31aed..20b87e9dd 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 43c010c14..ffd368f6e 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 bd71b391a..f0084aa26 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 db3070660..0c3b6e196 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 97175ccf7..687b9bdeb 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 f3c117e16..7ec783e77 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 363fbc199..f5257c0a0 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 0d6f6ee03..f0c1f47c1 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 4ccdddff1..3f17ccce2 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 a8d337539..15d63c786 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 cd7440b00..d68c69bb7 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 9d489d8e4..a96b236cb 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 d1aefb73e..fb77df647 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 ca4d7657c..20d2116ce 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 259de4760..142ae2d0c 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 52e88d888..f7c93c20a 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 caa16192e..03cbfff83 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 d04c8dc30..6e6d0acca 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 a8dfb5c91..ed980cea5 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 7ca1366b4..0f5c79c49 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 05935dd0f..1aaceb908 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 4494e70ca..fab54f59a 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 e69de29bb..e69de29bb 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 44ebd8894..c92bfd1c2 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 4b6d84e11..083cc2986 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 471c62c6e..4ad082b95 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, &param) == -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 150d74e3a..412691107 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 4f34e92df..68933e195 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 62fee6e36..9dd7db51a 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 798c7f0fc..b2c4c80bf 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 d29bf74e7..cb0bde6a9 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 331e80358..71f271887 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 2fdd36552..e7e64365d 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 e3eb146ad..9978647b4 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 68ed61fcb..0023c8de9 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 3be2d8e41..119efa62e 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 d17daacd2..19eb100cd 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 4e41539e2..7f6a896b6 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 75a7002b3..ba7e7ec94 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 a54c6452f..95e485106 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 28a3e7fa6..3c2ed75e5 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 905ae480b..f75f0adc3 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 e62e61ae8..43aa2daa2 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 bbd0ae728..3f5ba73b6 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 aec57efa9..1bb883f0b 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 6936c36f1..951a38cac 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 04e04f089..ae0c464b1 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 a25ee7227..d4af9776f 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 aba7425d7..a049dc1b2 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 a44fbadb0..dd51be2af 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 c564efff3..7f4c6c53d 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 d05a8ede7..011ee73d9 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 a2c6911e7..c44bef307 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 19648cd1d..070bb3d3d 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 50c76f6d6..50672324b 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 694c9d4ce..8e431bfd5 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 ca5715254..d576d86b9 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 2424864b5..411538446 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 512b4bbe6..dd94a801d 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 f028dbb30..61b9bfc61 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 84369f6d4..0316edac0 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 6a5562fd4..57dae9d0b 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 9ab2dca73..6a5994c12 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 94fd5e429..de330cae8 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 15fc50a6a..0bac3dc8f 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 c5b42c921..91e226902 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 36962fef2..850dd7ebc 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 edb4482a0..198e98bd9 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 81c85481b..48e1599a7 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 eda1c05b9..845363fd2 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 3dd79bb4d..90d4b829b 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 044f975b5..4a812baab 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 012c6efe1..b107358ab 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 747b5150a..57b0aecc8 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 d0b75af7e..b96a018ef 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 8bede73fd..c266efeb4 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 7b3e726ec..f5412b63d 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 d4b33fd5a..15792fd15 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 675389021..586c6b34a 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 c7bbaa8d9..db4cb700b 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 ef81863fd..5353ab60b 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 b9ca3c085..133d9a547 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 e2ed6a4ff..eec6ad0e3 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 6be4d9648..07a9f8069 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 fa44d49a8..6cef6d7a8 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 bbc2ef366..4f97eb58f 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 9aa241564..ab36de014 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 de6c634c3..d8e2bbd8d 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 654f66d12..d3e0420d2 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 44b0a1513..b54b90142 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 cceaf292b..baa2dc09d 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 cca43b09f..e0e58ede3 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 6dc8200d3..8dbeb8ea6 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 be824d168..77ab5aaf5 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 d8b6cd98a..53e3f47f4 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 5f6cc2443..30e9cb513 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 52d36a898..6a7106458 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 5ac52f5a5..c684f1c35 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 df174cbd1..000000000
--- 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 75f85632e..000000000
--- 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 7d056e6be..000000000
--- 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 b1a021baa..000000000
--- 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 e882f3db1..000000000
--- 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 2b1c36e3f..000000000
--- 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 f41571803..000000000
--- 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 04f9df5cd..000000000
--- 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 05a40bea0..000000000
--- 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 0a6f40c15..000000000
--- 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 dc82f052f..000000000
--- 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 6ccf3e861..000000000
--- 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 88a3a9230..000000000
--- 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 dcec28f75..000000000
--- 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 792c6496f..000000000
--- 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 24b3da340..000000000
--- 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 b41c814ec..000000000
--- 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 003b8626d..000000000
--- 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 f8c63814f..000000000
--- 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 17af098e8..000000000
--- 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 373e7e9f8..000000000
--- 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 dff48c2f3..000000000
--- 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 31c546411..000000000
--- 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 8f71c6d4c..df1a2177f 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 bf3d9435c..7bf3db93a 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 c05e526ed..d0600359e 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 c23abf0dc..f75677bf9 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 c32660c81..1e03828e4 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 6f4de1aba..b6f315dca 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 477fb3d57..282cfcd1a 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 b495c37e1..b9e528fca 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 7492547ef..7777c8978 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 */